littlefig-bench / fix_all.py
ticketguy's picture
Fix lowram backward dtype bug + AGPL licenses + rerun GPU test
11e27f8 verified
#!/usr/bin/env python3
"""Fix all remaining issues: dtype bug, licenses, colab, then rerun GPU test."""
import subprocess, os, sys
# ═══════════════════════════════════════════════════════════════════════════════
# TASK 1: Fix the dtype bug in Little Fig's lowram backward
# ═══════════════════════════════════════════════════════════════════════════════
TOKEN_LF = "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"
subprocess.run(["git", "clone", f"https://{TOKEN_LF}@github.com/ticketguy/littlefig.git", "/app/littlefig"], check=True)
os.chdir("/app/littlefig")
subprocess.run(["git", "config", "user.name", "0xticketguy"], check=True)
subprocess.run(["git", "config", "user.email", "0xticketguy@harboria.dev"], check=True)
# Read current linear.py and fix the backward
linear_path = "src/little_fig/engine/linear.py"
with open(linear_path, "r") as f:
content = f.read()
# The bug: in DequantMatmul.backward, grad_output comes in as fp16 (from autocast)
# but W is dequantized to fp32. The matmul fails.
# Fix: cast W to grad_output's dtype, same pattern as forward.
# Check if the fix is already there
if "ctx.input_dtype" in content and "grad_output @ W" in content:
# The forward saves input_dtype, but backward needs to use GRAD dtype
old_backward = " W = figquant_dequantize(q).to(dtype=ctx.input_dtype)\n grad_x = grad_output @ W"
new_backward = " W = figquant_dequantize(q).to(dtype=grad_output.dtype)\n grad_x = grad_output @ W"
if old_backward in content:
content = content.replace(old_backward, new_backward)
print("Fixed: backward now casts W to grad_output.dtype")
elif "grad_x = grad_output @ W" in content:
# Different format β€” find and fix
content = content.replace(
" grad_x = grad_output @ W",
" W = W.to(dtype=grad_output.dtype)\n grad_x = grad_output @ W"
)
print("Fixed: added dtype cast before grad matmul")
else:
print("Backward already fixed or different pattern")
else:
print("Pattern not found β€” checking raw content")
# Direct fix: find the backward method and ensure dtype cast
if "grad_x = grad_output @ W" in content:
# Add .to(dtype=grad_output.dtype) to W before the matmul
content = content.replace(
" grad_x = grad_output @ W\n return grad_x",
" W = W.to(dtype=grad_output.dtype)\n grad_x = grad_output @ W\n return grad_x"
)
print("Fixed: dtype cast added to backward")
with open(linear_path, "w") as f:
f.write(content)
# ═══════════════════════════════════════════════════════════════════════════════
# TASK 2: Add AGPL-3.0 license to Little Fig
# ═══════════════════════════════════════════════════════════════════════════════
agpl_text = """GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2024-2026 Harboria Labs (0xticketguy)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Additional Terms:
Commercial License Available β€” If you wish to use this software in a
proprietary product or service without complying with AGPL-3.0 obligations,
contact Harboria Labs for a commercial license.
The AGPL requires that if you modify this software and make it available
over a network (e.g., as a cloud service), you must release your complete
source code under the same license. This protects the community's work
from being captured by cloud providers without contribution.
For academic research, personal use, and internal company use: the AGPL
imposes no obligations beyond standard open-source terms. You only need
to share modifications if you offer the software as a network service
to third parties.
"""
with open("LICENSE", "w") as f:
f.write(agpl_text)
# Update pyproject.toml license field
pyproject_path = "pyproject.toml"
with open(pyproject_path, "r") as f:
pyproject = f.read()
if 'license' not in pyproject.lower():
# Add license after description
pyproject = pyproject.replace(
'requires-python = ">=3.9"',
'requires-python = ">=3.9"\nlicense = "AGPL-3.0-or-later"'
)
with open(pyproject_path, "w") as f:
f.write(pyproject)
# Commit and push Little Fig
subprocess.run(["git", "add", "-A"], check=True)
subprocess.run(["git", "commit", "-m",
"Fix lowram backward dtype bug + add AGPL-3.0 license\n\n"
"Bug fix: DequantMatmul.backward() now casts dequantized weight\n"
"to grad_output.dtype before matmul. Fixes RuntimeError when\n"
"using lowram mode with torch.autocast (fp16/bf16 grad vs fp32 weight).\n\n"
"License: AGPL-3.0-or-later\n"
" - Free for research, personal use, internal company use\n"
" - Cloud services using this must open-source their modifications\n"
" - Commercial license available from Harboria Labs for proprietary use"],
check=True)
subprocess.run(["git", "push", "origin", "main"], check=True)
print("βœ… Little Fig: dtype fix + AGPL license pushed")
# ═══════════════════════════════════════════════════════════════════════════════
# TASK 3: Add AGPL-3.0 license to Ember's Diaries
# ═══════════════════════════════════════════════════════════════════════════════
os.chdir("/app")
TOKEN_ED = "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"
subprocess.run(["git", "clone", f"https://{TOKEN_ED}@github.com/ticketguy/embers-diaries.git", "/app/embers"], check=True)
os.chdir("/app/embers")
subprocess.run(["git", "config", "user.name", "0xticketguy"], check=True)
subprocess.run(["git", "config", "user.email", "0xticketguy@harboria.dev"], check=True)
ember_license = agpl_text.replace("Little Fig", "Ember's Diaries")
with open("LICENSE", "w") as f:
f.write(ember_license)
subprocess.run(["git", "add", "LICENSE"], check=True)
subprocess.run(["git", "commit", "-m", "Add AGPL-3.0 license\n\nSame terms as Little Fig. Commercial license available from Harboria Labs."], check=True)
subprocess.run(["git", "push", "origin", "main"], check=True)
print("βœ… Ember's Diaries: AGPL license pushed")
print("\nβœ… ALL TASKS DONE:")
print(" 1. Lowram backward dtype bug fixed in Little Fig")
print(" 2. AGPL-3.0 license added to Little Fig")
print(" 3. AGPL-3.0 license added to Ember's Diaries")