File size: 7,796 Bytes
11e27f8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/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")