#!/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 . 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")