Download toolkits/data2000_structured_hotfix_v6/generator.py from koreallmdev/dgx-harness-engineering: direct link, hf CLI and curl.
- Browser
- Download file 15.9 kB
-
https://huggingface.co/koreallmdev/dgx-harness-engineering/resolve/main/toolkits/data2000_structured_hotfix_v6/generator.py
- Command line
-
hf download hf://koreallmdev/dgx-harness-engineering/toolkits/data2000_structured_hotfix_v6/generator.py
-
curl -L -o generator.py https://huggingface.co/koreallmdev/dgx-harness-engineering/resolve/main/toolkits/data2000_structured_hotfix_v6/generator.py
15.9 kB
| #!/usr/bin/env python3 | |
| import argparse, ast, hashlib, json, os, re, subprocess, urllib.request, urllib.error | |
| from datetime import datetime | |
| from pathlib import Path | |
| API="http://127.0.0.1:8000/v1/chat/completions" | |
| MODELS="http://127.0.0.1:8000/v1/models" | |
| MODEL="deepseek70b-7816" | |
| ROOT=Path("/home/harness_user_1/dgx_ai_factory") | |
| OUTROOT=ROOT/"data/generated/deepseek70b_7816_code_sft_2000_structured_v6" | |
| LOGROOT=ROOT/"logs/data2000_structured_hotfix_v6" | |
| CATEGORIES=[ | |
| ("python_algorithm","advanced","python"), | |
| ("python_data_pipeline","advanced","python"), | |
| ("python_debugging","advanced","python"), | |
| ("python_concurrency","advanced","python"), | |
| ("fastapi_backend","advanced","python"), | |
| ("linux_bash","advanced","bash"), | |
| ("sql_database","advanced","sql"), | |
| ("testing_quality","advanced","python"), | |
| ("performance_optimization","advanced","python"), | |
| ("ml_tooling","advanced","python"), | |
| ("system_automation","advanced","bash"), | |
| ("api_integration","advanced","python"), | |
| ] | |
| ANGLES=[ | |
| "์คํ ๊ฐ๋ฅํ ์์ฑ ์์ ์ ์ต์ํ์ ๊ฒ์ฆ ์ฝ๋๋ฅผ ํฌํจํ์ธ์.", | |
| "์ค๋ฌด์์ ๋ฐ์ํ ์ ์๋ ์คํจ ์กฐ๊ฑด๊ณผ ์์ธ ์ฒ๋ฆฌ๋ฅผ ํฌํจํ์ธ์.", | |
| "๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋๊ณผ ํ์ฅ์ฑ์ ๊ณ ๋ คํ ๊ตฌํ์ ์๊ตฌํ์ธ์.", | |
| "์ฌํ ๊ฐ๋ฅํ ๋ฒ๊ทธ ์ํฉ๊ณผ ์์ ์ ํ ์ฐจ์ด๋ฅผ ํฌํจํ์ธ์.", | |
| "ํ ์คํธ ๊ฐ๋ฅํ ํจ์ ๋จ์ ์ค๊ณ์ ํ ์คํธ ์์ ๋ฅผ ํฌํจํ์ธ์.", | |
| "์ ๋ ฅ ๊ฒ์ฆ๊ณผ ๋ช ํํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํฌํจํ์ธ์.", | |
| "๋์์ฑ ๋๋ ์ฌ์๋ ์ํฉ์์ ์์ ํ๊ฒ ๋์ํ๋๋ก ์๊ตฌํ์ธ์.", | |
| "๋์ฉ๋ ์ ๋ ฅ์ ๊ฐ์ ํ๊ณ ์คํธ๋ฆฌ๋ฐ ๋๋ ๋ฐฐ์น ์ฒ๋ฆฌ๋ฅผ ๊ณ ๋ คํ์ธ์.", | |
| ] | |
| SCHEMA={ | |
| "type":"object", | |
| "properties":{ | |
| "instruction":{"type":"string","minLength":40}, | |
| "response":{"type":"string","minLength":220}, | |
| "category":{"type":"string"}, | |
| "difficulty":{"type":"string"}, | |
| "language":{"type":"string"} | |
| }, | |
| "required":["instruction","response","category","difficulty","language"], | |
| "additionalProperties":False | |
| } | |
| THINK_BLOCK=re.compile(r"<think>.*?</think>",re.I|re.S) | |
| THINK_TAG=re.compile(r"</?think>",re.I) | |
| CJK=re.compile(r"[\u4e00-\u9fff]") | |
| BAD=re.compile(r"\bTODO\b|\bFIXME\b|\bTBD\b|placeholder|์๋ต|์ค๋ต|omitted|truncated|continue here",re.I) | |
| FENCE=re.compile(r"```([A-Za-z0-9_+\-]*)\s*\n(.*?)```",re.S) | |
| DANGEROUS=re.compile(r"rm\s+-rf\s+/(?:\s|$)|mkfs\.|dd\s+if=.*of=/dev/|:\(\)\s*\{\s*:\|:&\s*\};:",re.I) | |
| def now(): return datetime.now().astimezone().isoformat() | |
| def fsync_append(path,obj): | |
| path.parent.mkdir(parents=True,exist_ok=True) | |
| with path.open("a",encoding="utf-8") as f: | |
| f.write(json.dumps(obj,ensure_ascii=False,separators=(",",":"))+"\n") | |
| f.flush(); os.fsync(f.fileno()) | |
| def atomic_json(path,obj): | |
| path.parent.mkdir(parents=True,exist_ok=True) | |
| tmp=path.with_suffix(path.suffix+".tmp") | |
| with tmp.open("w",encoding="utf-8") as f: | |
| json.dump(obj,f,ensure_ascii=False,indent=2); f.flush(); os.fsync(f.fileno()) | |
| os.replace(tmp,path) | |
| def normalize_text(s): | |
| if not isinstance(s,str): return s | |
| s=s.replace("ฤ "," ").replace("ฤ","\n").replace("ฤ","\t") | |
| s=THINK_BLOCK.sub("",s) | |
| s=THINK_TAG.sub("",s) | |
| return s.replace("\r\n","\n").replace("\r","\n").strip() | |
| def parse_content(content): | |
| s=normalize_text(content or "") | |
| try: return json.loads(s),None | |
| except Exception as e: | |
| a=s.find("{"); b=s.rfind("}") | |
| if a>=0 and b>a: | |
| try:return json.loads(s[a:b+1]),"extracted_json" | |
| except Exception:pass | |
| return None,f"json_parse:{type(e).__name__}" | |
| def validate(obj,expected): | |
| reasons=[] | |
| if not isinstance(obj,dict): return ["not_object"],None | |
| obj={k:normalize_text(v) if isinstance(v,str) else v for k,v in obj.items()} | |
| for k in ("instruction","response","category","difficulty","language"): | |
| if not isinstance(obj.get(k),str) or not obj[k].strip(): reasons.append(f"missing_or_empty:{k}") | |
| if reasons: return sorted(set(reasons)),obj | |
| if len(obj["instruction"])<40: reasons.append("instruction_too_short") | |
| if len(obj["response"])<220: reasons.append("response_too_short") | |
| if len(obj["response"])>14000: reasons.append("response_too_long") | |
| if obj["category"]!=expected[0]: reasons.append("category_mismatch") | |
| if obj["difficulty"]!=expected[1]: reasons.append("difficulty_mismatch") | |
| if obj["language"]!=expected[2]: reasons.append("language_mismatch") | |
| alltext=obj["instruction"]+"\n"+obj["response"] | |
| if THINK_TAG.search(alltext) or "<think>" in alltext.lower(): reasons.append("think_tag") | |
| if CJK.search(alltext): reasons.append("han_cjk_char") | |
| if BAD.search(alltext): reasons.append("todo_or_incomplete") | |
| if DANGEROUS.search(alltext): reasons.append("dangerous_destructive_pattern") | |
| if obj["response"].count("```")%2: reasons.append("unbalanced_fence") | |
| for lang,code in FENCE.findall(obj["response"]): | |
| if lang.lower() in ("python","py"): | |
| try: ast.parse(code) | |
| except SyntaxError as e: reasons.append("python_syntax_error:"+e.msg) | |
| elif lang.lower()=="json": | |
| try: json.loads(code) | |
| except Exception: reasons.append("json_fence_parse_error") | |
| if re.search(r"json\.dumps\(|Define the JSON data|Convert the dictionary to a JSON string",obj["response"],re.I): | |
| reasons.append("meta_json_generation_instead_of_solution") | |
| if re.search(r'"instruction"\s*:\s*""|"response"\s*:\s*"\+\+"',obj["response"]): | |
| reasons.append("degenerate_embedded_schema") | |
| return sorted(set(reasons)),obj | |
| def http_json(url,payload=None,timeout=900): | |
| data=None; headers={} | |
| if payload is not None: | |
| data=json.dumps(payload,ensure_ascii=False).encode(); headers["Content-Type"]="application/json" | |
| req=urllib.request.Request(url,data=data,headers=headers) | |
| try: | |
| with urllib.request.urlopen(req,timeout=timeout) as r: | |
| return r.status,json.loads(r.read().decode("utf-8","replace")) | |
| except urllib.error.HTTPError as e: | |
| raw=e.read().decode("utf-8","replace") | |
| try: body=json.loads(raw) | |
| except Exception: body={"raw":raw} | |
| return e.code,body | |
| except Exception as e: | |
| return 0,{"error":repr(e)} | |
| def structured_payload(category,difficulty,language,variation,mode="json_schema"): | |
| schema=json.loads(json.dumps(SCHEMA)) | |
| schema["properties"]["category"]["enum"]=[category] | |
| schema["properties"]["difficulty"]["enum"]=[difficulty] | |
| schema["properties"]["language"]["enum"]=[language] | |
| system=( | |
| "๋น์ ์ ์ฝ๋ฉ ๊ฐ๋ฐ ๋น์๋ฅผ ์ํ ๊ณ ํ์ง SFT ๋ฐ์ดํฐ ์์ฑ๊ธฐ์ ๋๋ค. ์ผ๋ฐ ๋ํ๋ ์ก๋ด์ ๋ง๋ค์ง ๋ง์ญ์์ค. " | |
| "ํ๋์ ๋ ๋ฆฝ์ ์ธ ์ค๋ฌดํ ์ฝ๋ฉ ๋ฌธ์ ์ ๊ทธ์ ๋ํ ์์ฑ๋ ์ต์ข ๋ต๋ณ์ ๋ง๋์ญ์์ค. " | |
| "instruction์ ์ค์ ์ฌ์ฉ์์ ๊ตฌ์ฒด์ ์ธ ๊ฐ๋ฐ ์์ฒญ์ด์ด์ผ ํ๋ฉฐ ๋น ๋ฌธ์์ด์ด๋ฉด ์ ๋ฉ๋๋ค. " | |
| "response๋ ๋ฐ๋ก ํ์ต์ ์ฌ์ฉํ ์ต์ข Assistant ๋ต๋ณ์ ๋๋ค. ํ์ํ ๊ฒฝ์ฐ ์คํ ๊ฐ๋ฅํ ์ฝ๋, ์ค๋ฅ ์ฒ๋ฆฌ, ํ ์คํธ๋ฅผ ํฌํจํ์ญ์์ค. " | |
| "<think> ๋๋ ๋ด๋ถ ์ถ๋ก ์ ์ถ๋ ฅํ์ง ๋ง์ญ์์ค. TODO/FIXME/์๋ต/placeholder๋ฅผ ์ฌ์ฉํ์ง ๋ง์ญ์์ค. " | |
| "JSON์ ๋ง๋๋ Python ์์ ๋ฅผ ๋ต์ผ๋ก ์ฐ์ง ๋ง์ญ์์ค. ์ง์ ๋ JSON ๊ฐ์ฒด ๊ทธ ์์ฒด๋ง ๋ฐํํ์ญ์์ค. " | |
| "๋ฐ๋์ instruction, response, category, difficulty, language ๋ค์ฏ ํ๋๋ง ๋ฐํํ์ญ์์ค." | |
| ) | |
| user=(f"์๋ก์ด ์ฝ๋ฉ SFT ์ํ 1๊ฐ๋ฅผ ์์ฑํ์ธ์.\ncategory={category}\ndifficulty={difficulty}\nlanguage={language}\n" | |
| f"variation_id=V6-{variation:06d}\n์ถ๊ฐ ์กฐ๊ฑด: {ANGLES[variation%len(ANGLES)]}\n" | |
| "์ด์ ์ํ์ ๋ณต์ฌํ์ง ๋ง๊ณ ๊ตฌ์ฒด์ ์ธ ๋ฌธ์ ์ํฉ, ์ ๋ ฅ/์ถ๋ ฅ ๋๋ ์คํจ ์กฐ๊ฑด์ ํฌํจํด ์๋ก ๋ค๋ฅธ ๊ณผ์ ๋ก ๋ง๋์ธ์.") | |
| p={"model":MODEL,"messages":[{"role":"system","content":system},{"role":"user","content":user}], | |
| "temperature":0.35,"top_p":0.9,"max_tokens":900} | |
| if mode=="json_schema": | |
| p["response_format"]={"type":"json_schema","json_schema":{"name":"coding_sft_record","schema":schema}} | |
| elif mode=="structured_outputs": | |
| p["structured_outputs"]={"json":schema} | |
| elif mode=="json_object": | |
| p["response_format"]={"type":"json_object"} | |
| else: node-7.example.invalid ValueError(mode) | |
| return p | |
| def api_probe(): | |
| code,body=http_json(MODELS,timeout=10) | |
| if code!=200:return None,{"models_http":code,"body":body} | |
| ids=[x.get("id") for x in body.get("data",[])] | |
| if MODEL not in ids:return None,{"models_http":code,"ids":ids,"error":"LoRA model id missing"} | |
| results=[] | |
| for mode in ("json_schema","structured_outputs","json_object"): | |
| code,b=http_json(API,structured_payload("python_algorithm","advanced","python",900001,mode),timeout=900) | |
| rec={"mode":mode,"http":code} | |
| if code==200: | |
| try: content=b["choices"][0]["message"]["content"] | |
| except Exception: | |
| rec["error"]="missing_content"; results.append(rec); continue | |
| obj,perr=parse_content(content) | |
| vr,norm=validate(obj,("python_algorithm","advanced","python")) if obj is not None else ([perr],None) | |
| rec["parse_error"]=perr; rec["validation"]=vr; rec["preview"]=normalize_text(content)[:500] | |
| results.append(rec) | |
| if not vr:return mode,{"selected":mode,"results":results} | |
| else: | |
| rec["body"]=b;results.append(rec) | |
| return None,{"selected":None,"results":results} | |
| def mem_available_gib_local(): | |
| vals={} | |
| for line in Path("/proc/meminfo").read_text().splitlines(): | |
| if ":" in line: | |
| k,v=line.split(":",1);p=v.split() | |
| if p and p[0].isdigit(): vals[k]=int(p[0])*1024 | |
| return vals.get("MemAvailable",0)/(1024**3) | |
| def mem_available_gib_sub(): | |
| try: | |
| p=subprocess.run(["ssh","-o","BatchMode=yes","-o","ConnectTimeout=5","harness_user_2@192.0.2.13", | |
| "awk '/MemAvailable:/ {print $2}' /proc/meminfo"],capture_output=True,text=True,timeout=10) | |
| if p.returncode:return None | |
| return float(p.stdout.strip())/1024/1024 | |
| except Exception:return None | |
| def load_hashes(path): | |
| out=set() | |
| if not path.is_file():return out | |
| for line in path.read_text(errors="replace").splitlines(): | |
| try:o=json.loads(line) | |
| except Exception:continue | |
| ins=normalize_text(o.get("instruction","")).lower() | |
| if ins:out.add(hashlib.sha256(ins.encode()).hexdigest()) | |
| return out | |
| def selftest(): | |
| good={"instruction":"Python์์ ๋์ฉ๋ JSONL ํ์ผ์ ์คํธ๋ฆฌ๋ฐ ๋ฐฉ์์ผ๋ก ์ค๋ณต ์ ๊ฑฐํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๊ฒ์ฆํ๋ ๋๊ตฌ๋ฅผ ์์ฑํ์ธ์.", | |
| "response":"์ ์ฒด ํ์ผ์ ํ๊บผ๋ฒ์ ์ฝ์ง ์๊ณ ์ค ๋จ์๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.\n```python\nfrom pathlib import Path\n\ndef unique_count(path: Path) -> int:\n seen=set()\n with path.open(encoding='utf-8') as f:\n for line in f:\n seen.add(line.rstrip('\\n'))\n return len(seen)\n\nassert callable(unique_count)\n```\n์ค๋ฌด์์๋ JSON ํ์ฑ ์ค๋ฅ๋ฅผ ๋ณ๋ quarantine ํ์ผ๋ก ๊ธฐ๋กํ๊ณ , ๋์ฉ๋ ๋ฐ์ดํฐ์์๋ ์ธ๋ถ ์ ์ฅ์๋ ํด์ ํํฐ์ ๋์ผ๋ก seen ์งํฉ์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ ํํ๋ ๋ฐฉ์์ผ๋ก ํ์ฅํ ์ ์์ต๋๋ค.", | |
| "category":"python_data_pipeline","difficulty":"advanced","language":"python"} | |
| vr,_=validate(good,("python_data_pipeline","advanced","python")); assert not vr,vr | |
| bad=dict(good);bad["response"]="<think>x</think> TODO" | |
| vr,_=validate(bad,("python_data_pipeline","advanced","python")); assert "todo_or_incomplete" in vr | |
| assert normalize_text("Aฤ BฤC")=="A B\nC" | |
| print("SELFTEST=PASS") | |
| def main(): | |
| ap=argparse.ArgumentParser() | |
| ap.add_argument("--target",type=int,default=2000) | |
| ap.add_argument("--max-attempts",type=int,default=5000) | |
| ap.add_argument("--mode",choices=["json_schema","structured_outputs","json_object"]) | |
| ap.add_argument("--self-test",action="store_true") | |
| a=ap.parse_args() | |
| if a.self_test:selftest();return 0 | |
| if not a.mode:node-7.example.invalid SystemExit("--mode required") | |
| OUTROOT.mkdir(parents=True,exist_ok=True);LOGROOT.mkdir(parents=True,exist_ok=True) | |
| accepted=OUTROOT/"accepted.jsonl"; rejected=OUTROOT/"rejected.jsonl"; statep=OUTROOT/"state.json" | |
| state={"phase":"generation","accepted":0,"target":a.target,"attempts":0,"rejected":0,"api_failures":0, | |
| "mode":a.mode,"started_at":now(),"updated_at":now()} | |
| if statep.is_file(): | |
| try: | |
| old=json.loads(statep.read_text()) | |
| if old.get("mode")==a.mode:state.update(old);state["phase"]="generation";state["target"]=a.target | |
| except Exception:pass | |
| hashes=load_hashes(accepted);state["accepted"]=len(hashes);atomic_json(statep,state) | |
| while state["accepted"]<a.target and state["attempts"]<a.max_attempts: | |
| state["attempts"]+=1;variation=state["attempts"];expected=CATEGORIES[(variation-1)%len(CATEGORIES)] | |
| code,body=http_json(API,structured_payload(*expected,variation,a.mode),timeout=900) | |
| if code!=200: | |
| state["api_failures"]+=1 | |
| fsync_append(rejected,{"attempt":variation,"time":now(),"reason":["api_http"],"http":code,"body":body}) | |
| else: | |
| try:content=body["choices"][0]["message"]["content"] | |
| except Exception: | |
| content=None;state["rejected"]+=1 | |
| fsync_append(rejected,{"attempt":variation,"time":now(),"reason":["api_missing_content"],"body":body}) | |
| if content is not None: | |
| obj,perr=parse_content(content) | |
| if obj is None: | |
| state["rejected"]+=1 | |
| fsync_append(rejected,{"attempt":variation,"time":now(),"reason":[perr],"raw":content[:20000]}) | |
| else: | |
| vr,obj=validate(obj,expected) | |
| if not vr: | |
| h=hashlib.sha256(obj["instruction"].strip().lower().encode()).hexdigest() | |
| if h in hashes:vr=["duplicate_instruction"] | |
| else:hashes.add(h) | |
| if vr: | |
| state["rejected"]+=1 | |
| fsync_append(rejected,{"attempt":variation,"time":now(),"reason":vr,"raw":content[:20000],"parsed":obj}) | |
| else: | |
| fsync_append(accepted,{"id":f"CODE-V6-{state['accepted']+1:05d}",**obj});state["accepted"]+=1 | |
| if state["attempts"]%3==0: | |
| mm=mem_available_gib_local();sm=mem_available_gib_sub() | |
| state["main_mem_available_gib"]=mm;state["sub_mem_available_gib"]=sm | |
| if mm<2.0 or (sm is not None and sm<2.0): | |
| state["phase"]="safe_stop_low_memory";state["updated_at"]=now();atomic_json(statep,state) | |
| print(f"SAFE_STOP_LOW_MEMORY main={mm:.2f} sub={sm}");return 20 | |
| state["updated_at"]=now();atomic_json(statep,state) | |
| print(f"PROGRESS accepted={state['accepted']} attempts={state['attempts']} rejected={state['rejected']} api_failures={state['api_failures']}",flush=True) | |
| state["phase"]="complete" if state["accepted"]>=a.target else "max_attempts";state["updated_at"]=now();atomic_json(statep,state) | |
| report={"accepted":state["accepted"],"target":a.target,"attempts":state["attempts"],"rejected":state["rejected"], | |
| "api_failures":state["api_failures"],"mode":a.mode,"accepted_file":str(accepted), | |
| "sha256":hashlib.sha256(accepted.read_bytes()).hexdigest() if accepted.is_file() else None,"finished_at":now()} | |
| atomic_json(OUTROOT/"final_report.json",report);print(json.dumps(report,ensure_ascii=False,indent=2)) | |
| return 0 if state["accepted"]>=a.target else 2 | |
| if __name__=="__main__":node-7.example.invalid SystemExit(main()) | |