ZuperAI-14B / toolkit /project.py
Tyesee's picture
toolkit: project.py
6c1858e verified
Raw History Blame Contribute Delete
3.37 kB
# -*- coding: utf-8 -*-
"""Генерация полного проекта по ТЗ (№2): структура, файлы, тесты, прогон.
Модель генерирует проект как JSON {"files": {"имя.py": "код", ...}}, пишет файлы
в папку, затем гоняет unittest-тесты и при падении чинит.
Запуск:
venv/Scripts/python.exe project.py "FastAPI-приложение для заметок с SQLite" --out myapp [--code deepseek|lmstudio|local]
"""
import json
import os
import re
import subprocess
import sys
from brain import pick, generate
def parse_json(text):
m = re.search(r"\{.*\}", text, re.DOTALL)
if not m:
return None
try:
d = json.loads(m.group(0))
return d if isinstance(d, dict) else None
except Exception:
return None
def run_project_tests(path):
try:
r = subprocess.run([sys.executable, "-m", "unittest", "discover", "-s", path],
capture_output=True, text=True, timeout=120)
return r.returncode == 0, (r.stdout or "") + (r.stderr or "")
except Exception as e:
return False, f"тесты: {e}"
def main():
args = sys.argv[1:]
outdir = "generated_project"
backend = None
parts = []
i = 0
while i < len(args):
if args[i] == "--out" and i + 1 < len(args):
outdir = args[i + 1]; i += 2; continue
if args[i] == "--code" and i + 1 < len(args):
backend = args[i + 1]; i += 2; continue
parts.append(args[i]); i += 1
prompt = " ".join(parts) or "Консольный TODO-менеджер с сохранением в JSON"
backend = pick(backend)
msgs = [{"role": "system",
"content": "Ты — senior-разработчик. Проектируй и пиши рабочий код без заглушек."},
{"role": "user",
"content": f"Сгенерируй проект по ТЗ: {prompt}\n\nВерни СТРОГО JSON: "
f"{{\"files\": {{\"<имя.py>\": \"<полный код>\", ...}}}}. Включи "
f"основной модуль, вспомогательные модули (при нужде) и файл "
f"test_*.py с unittest-тестами. Без пояснений вне JSON."}]
data = None
for _ in range(3):
raw = generate(backend, msgs, 3072)
data = parse_json(raw)
if data and data.get("files"):
break
if not data or not data.get("files"):
print("[!] не удалось получить валидный JSON-проект. Попробуй ещё раз.")
sys.exit(1)
os.makedirs(outdir, exist_ok=True)
for name, content in data["files"].items():
safe = os.path.basename(name) # защита от путей вроде ../../x
with open(os.path.join(outdir, safe), "w", encoding="utf-8") as f:
f.write(content)
print(f"[*] проект создан в {outdir}: {len(data['files'])} файлов")
ok, out = run_project_tests(outdir)
if ok:
print("[OK] тесты проекта прошли")
else:
print(f"[!] тесты падают:\n{out[-600:]}")
if __name__ == "__main__":
main()