
    `j1                        d dl Zd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlZd dlZdZ ej                         Zdad Zd Zd$dZd$dZd$dZej,                  j/                  d	      Zej,                  j3                  ej,                  j5                  e            Zd
Zd%dZdZd&dZ d Z! ejD                  d      Z#d Z$d Z%dZ&dZ'g a(g a)d Z*g dZ+d Z,d Z-d Z.dZ/d Z0d Z1g dZ2d Z3d Z4 G d d ejj                  jl                        Z7e8d!k(  rH e1         e*         ejr                  d"e&fe7      5 Z: e;d#e&z         e:jy                          ddd       yy# 1 sw Y   yxY w)'    N&   E:\VLA시스템\FINETUNE\distill_pairsko-KR-SunHiNeuralc                     dd l }t        j                  j                  t	        j
                         d|j                         j                  d|       S )Nr   dzw_tts_.)uuidospathjointempfile
gettempdiruuid4hex)extr   s     dzw_knowledge_server.py_tts_tmpr      s5    77<<++-$**,BRBRTW/XYY    c                  Z    | D ]  }t        j                  |        y # t        $ r Y &w xY wN)r	   remove	Exception)pathsps     r   _rmr      s$    YYq\ $s   	**c                 :    ddl }ddlt        d      |xs t         fd}	 |j	                   |              t        d      5 }|j                         dfcddd       t               S # 1 sw Y   nxY w	 t               y# t               w xY w)ul   edge-tts(GitHub rany2/edge-tts) 뉴럴 음성 → MP3. 사람에 가까운 품질(무료, 인터넷 필요).r   Nmp3c                  r   K    j                  xs dd d       j                         d {    y 7 w)N X  )Communicatesave)edge_ttsouttextvs   r   goztts_edge.<locals>.go    s3     ""DJB#5q9>>sCCCs   ,757rbz
audio/mpeg)asyncior"   r   	TTS_VOICErunopenreadr   )r$   voicer(   r&   fr"   r#   r%   s   `    @@@r   tts_edger/      sn    
5/CADBD#t_!&&(L*@__C __CCs#   "B A4	B 4A=9B Bc                    t        d      }t        d      }t        |dd      5 }|j                  | xs ddd        ddd       d	|j                  d
d      z   dz   |j                  d
d      z   dz   }	 t	        j
                  dddd|gdd       t        |d      5 }|j                         dfcddd       t        ||       S # 1 sw Y   xY w# 1 sw Y   nxY w	 t        ||       y# t        ||       w xY w)uo   Windows 내장 한국어 음성(Heami)으로 WAV 생성 — 오프라인 폴백(삼성인터넷 포함 재생).txtwavwutf-8encodingr   Nr   zAdd-Type -AssemblyName System.Speech;$s=New-Object System.Speech.Synthesis.SpeechSynthesizer;try{$s.SelectVoice('Microsoft Heami Desktop')}catch{};$s.SetOutputToWaveFile('\z\\z');$t=[IO.File]::ReadAllText('z2',[Text.Encoding]::UTF8);$s.Speak($t);$s.Dispose()
powershellz
-NoProfilez-NonInteractivez-CommandT(   )capture_outputtimeoutr'   z	audio/wav)r   r+   writereplace
subprocessr*   r,   r   )r$   r-   r1   r2   r.   pss         r   tts_wavr@   (   s    
5/C
5/C	c3	)QTc8J0K	)% (+{{4'@AD(( +.++dF*C	DG&	&Bl4EzSUV&*B	8#t_!&&(K*?__C 
*	) __CCs/   C5)C, C0	C, CCC, ,C:c                 R    	 t        | |      S # t        $ r t        | |      cY S w xY w)u   뉴럴(edge-tts) 우선, 실패 시 Heami WAV 폴백. voice는 요청별로 받아 동시요청이 서로 안 섞이게 한다.)r/   r   r@   )r$   r-   s     r   ttsrB   :   s0    $e$$ $tU##$s    &&z~\.local\bin\claude.exeu  [대화 규칙] 너는 도진웍스 대표(비개발자·용접전문가)와 폰에서 음성으로 대화하는 코파일럿 SHIN이다. 네가 쓰는 답은 폰이 소리내어 읽어준다 — 그러니 "나는 소리를 못 낸다/터미널 프로그램이다" 같은 말은 절대 하지 마라. 잡담·질문이면 짧고 자연스러운 한국어로 대화하고, 코드나 파일 작업 지시면 실제로 수행한 뒤 무엇을 했는지 1~3문장으로 보고하라. 음성으로 읽기 좋게 간결히.
[너의 두뇌 — E: 드라이브 지식. 필요하면 이 경로를 직접 Read/Grep 해서 근거로 답하라]
· 용접 공정서/불량대책: E:\VLA시스템 (제품별 폴더, !_XXXX_용접공정서.md — 조건표·속도·공정순서)
· 사전생성 즉답 QA뱅크: E:\VLA시스템\_QA뱅크
· 숙련 지식 씨앗(GOLD 등): E:\지식정제시스템\05_KNOWLEDGE\seeds
· 옵시디언 노트(도진웍스): E:\옵시디언\도진웍스
· 뷰어/티칭 시스템 코드: E:\도진팩토리\3D스캔및티칭시스템 (현재 작업 폴더)
숫자·사실은 반드시 위 문서에서 확인하고 출처(파일명)를 밝혀라. 지어내지 마라.

[대표의 말]
c           	      T   |dvrd}t         5  t        j                  t        dt        | z   d|dgt
        dd      }d	d	d	       j                  j                  d
d      j                         }|j                  j                  d
d      j                         }|r|S t         5  t        j                  t        dt        | z   d|dgt
        dd      }d	d	d	       |j                  j                  d
d      j                         }|xs d|d	d z   S # 1 sw Y   xY w# 1 sw Y   LxY w)ux   폰 개발모드 — claude 헤드리스 에이전트(파일수정·명령 실제수행 + 음성대화). tailnet 전용.)sonnetopusrE   -p--modelz--dangerously-skip-permissionsTr   )cwdr:   r;   Nr4   ignoreerrorsuW   죄송합니다, 응답 생성에 실패했어요. 다시 한 번 말씀해 주세요.    )
_CLAUDE_LOCKr>   r*   
CLAUDE_EXEDEV_VOICE_FRAMEPROJECT_DIRstdoutdecodestripstderr)promptmodelrr#   errs        r   run_claude_devrY   R   s	   &&	NN7EKklD#? 
 ((//'(/
3
9
9
;C
((//'(/
3
9
9
;C
3J	NNJo.F	SXZz{*4N 
 ((//'(/
3
9
9
;Cylorswtwoxxy 
 
s   /D$/DDD'u  <!doctype html><html lang="ko"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
<title>SHIN 개발모드 (클로드 코드)</title>
<style>
 *{box-sizing:border-box}body{margin:0;font:15px/1.5 -apple-system,"Segoe UI",sans-serif;background:#0b0f1a;color:#e5e9f0;display:flex;flex-direction:column;height:100dvh}
 header{padding:12px 14px;background:linear-gradient(135deg,#6d28d9,#4338ca);font-weight:800;font-size:16px;display:flex;align-items:center;gap:8px}
 #log{flex:1;overflow-y:auto;padding:12px;-webkit-overflow-scrolling:touch}
 .m{margin:8px 0;padding:10px 12px;border-radius:12px;white-space:pre-wrap;word-break:break-word;font-size:14px}
 .u{background:#1e293b;margin-left:28px}.a{background:#111827;border-left:3px solid #8b5cf6}
 .sys{color:#94a3b8;font-size:12px;text-align:center}
 footer{display:flex;gap:8px;padding:10px;background:#0f1524;border-top:1px solid #1e293b}
 textarea{flex:1;background:#1e293b;color:#fff;border:1px solid #334155;border-radius:10px;padding:10px;font-size:15px;resize:none;height:46px;max-height:120px}
 button{background:linear-gradient(135deg,#8b5cf6,#6366f1);color:#fff;border:0;border-radius:10px;padding:0 18px;font-weight:700;font-size:15px}
 select{background:#1e293b;color:#cbd5e1;border:1px solid #334155;border-radius:8px;font-size:12px;padding:4px}
</style></head><body>
<header>⚒ SHIN 개발모드 <span style="font-weight:400;font-size:12px;opacity:.8">클로드 코드 · 폰</span>
 <span style="flex:1"></span>
 <select id="voice" title="목소리" style="background:#1e293b;color:#cbd5e1;border:1px solid #334155;border-radius:8px;font-size:12px;padding:4px;margin-right:6px"><option value="ko-KR-SunHiNeural">선히♀</option><option value="ko-KR-InJoonNeural">인준♂</option><option value="ko-KR-HyunsuMultilingualNeural">현수</option></select>
 <span id="spk" title="음성출력 켜기/끄기" style="cursor:pointer;font-size:18px;margin-right:8px">🔊</span><select id="mdl"><option value="opus">오푸스</option><option value="sonnet">소넷</option></select></header>
<div id="log"><div class="m sys">이 PC의 클로드 코드가 실제로 파일을 고치고 명령을 실행합니다. 작업을 한국어로 지시하세요.<br>예: "dzw_process.js에서 SHIN 패널 폰 폭을 100vw로 바꿔줘"</div></div>
<audio id="au" style="display:none"></audio>
<footer><button id="mic" title="음성 입력">🎤</button><textarea id="in" placeholder="작업 지시 또는 🎤 음성…" enterkeyhint="send"></textarea><button id="go">실행</button></footer>
<script>
const log=document.getElementById('log'),inp=document.getElementById('in'),go=document.getElementById('go'),mdl=document.getElementById('mdl'),mic=document.getElementById('mic');
let voiceOut=true, convo=false, ttsPrimed=false;
const au=document.getElementById('au');
function add(t,c){const d=document.createElement('div');d.className='m '+c;d.textContent=t;log.appendChild(d);log.scrollTop=log.scrollHeight;return d}
// 모바일 오디오 잠금해제: 버튼 탭 순간 진짜 무음소리를 재생해 요소를 깨운다(이후 프로그램 재생 허용)
const SILENT='data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YQAAAAA=';
function primeTTS(){ try{ au.src=SILENT; const p=au.play(); if(p&&p.then)p.then(()=>{ttsPrimed=true;}).catch(()=>{}); }catch(e){} }
// 서버(PC Heami)에서 소리 생성 → 폰이 재생 (삼성인터넷 포함 모든 브라우저 OK). 실패 시 브라우저 TTS.
function speak(t){ if(!voiceOut||!t)return;
 try{ const vc=document.getElementById('voice'); const vp=vc?('&voice='+vc.value):'';
   au.src='api/tts?text='+encodeURIComponent(t.slice(0,600))+vp+'&_='+Date.now();
   au.onended=()=>{ if(convo) setTimeout(listen,300); };
   au.onerror=()=>browserSpeak(t);
   const p=au.play(); if(p&&p.catch)p.catch(()=>browserSpeak(t));
 }catch(e){ browserSpeak(t); } }
function browserSpeak(t){ if(!window.speechSynthesis)return; try{ speechSynthesis.cancel();
   const u=new SpeechSynthesisUtterance(t.slice(0,600)); u.lang='ko-KR';
   const kv=speechSynthesis.getVoices().find(v=>/ko/i.test(v.lang)); if(kv)u.voice=kv;
   u.onend=()=>{ if(convo) setTimeout(listen,300); }; speechSynthesis.speak(u);
 }catch(e){} }
async function run(){const p=inp.value.trim();if(!p)return;inp.value='';add(p,'u');const w=add('⏳ 클로드 코드 작업 중…','a');go.disabled=true;
 try{const r=await fetch('api/dev',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({prompt:p,model:mdl.value})});const d=await r.json();const ans=d.answer||('오류: '+(d.error||'응답없음'));w.textContent=ans;speak(ans)}catch(e){w.textContent='연결 실패: '+e.message}go.disabled=false}
go.onclick=()=>{primeTTS();run()};inp.addEventListener('keydown',e=>{if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();primeTTS();run()}});
// ── 음성 입력 (Web Speech API) ──
const SR=window.SpeechRecognition||window.webkitSpeechRecognition;
let rec=null,listening=false,micGranted=false,fin='';
// 마이크 권한 1회 확보 → 이후 재요청 안 함 (HTTPS 오리진이라 브라우저가 기억)
async function ensureMic(){ if(micGranted)return true;
 try{ const s=await navigator.mediaDevices.getUserMedia({audio:true}); s.getTracks().forEach(t=>t.stop()); micGranted=true; return true; }
 catch(e){ add('마이크 권한이 거부됨 — 주소창 자물쇠 → 권한 → 마이크 허용으로 바꿔주세요','sys'); return false; } }
function makeRec(){ const r=new SR(); r.lang='ko-KR'; r.interimResults=true; r.continuous=false;
 r.onstart=()=>{listening=true;mic.textContent='🔴';};
 r.onresult=e=>{let itr='';for(let i=e.resultIndex;i<e.results.length;i++){const s=e.results[i][0].transcript;if(e.results[i].isFinal)fin+=s;else itr+=s;}inp.value=fin+itr;};
 r.onerror=(e)=>{ if(e.error==='not-allowed'||e.error==='service-not-allowed') micGranted=false; };
 r.onend=()=>{listening=false;mic.textContent='🎤';if(inp.value.trim())run();};
 return r; }
async function listen(){ if(!SR){add('이 브라우저는 음성인식 미지원 — Android Chrome 권장','sys');return;}
 if(listening){try{rec.stop()}catch(e){}return;}
 if(!(await ensureMic()))return;
 if(!rec)rec=makeRec();   // 인스턴스 재사용
 fin='';inp.value='';
 try{rec.start();}catch(e){ try{rec=makeRec();rec.start();}catch(_){} } }
mic.onclick=()=>{primeTTS();listen()};
const spk=document.getElementById('spk');
spk.onclick=()=>{ primeTTS(); voiceOut=!voiceOut; spk.textContent=voiceOut?'🔊':'🔇';
 if(voiceOut){ add('🔊 음성 켜짐 — PC(Heami) 목소리로 재생합니다. 소리 안 들리면 폰 "미디어 볼륨"을 올리세요.','sys'); speak('소리 테스트, 하나 둘 셋'); }
};
// 답변 말풍선 탭 → 다시 읽기
log.addEventListener('click',e=>{ const m=e.target.closest('.a'); if(m&&m.textContent){primeTTS();speak(m.textContent);} });
// 길게 누르면 대화모드(답 읽은 뒤 자동으로 다시 듣기) 토글
let pt;mic.addEventListener('touchstart',()=>{pt=setTimeout(()=>{convo=!convo;add('연속 대화모드 '+(convo?'ON — 답변 후 자동으로 다시 듣습니다':'OFF'),'sys');},600)});
mic.addEventListener('touchend',()=>clearTimeout(pt));
</script></body></html>c                    |dvrd}d}|dk(  r|dz  }|dz   |xs ddd	 z   d
z   | z   }t        j                  t        dd|g|j                  d      dd      }|j                  j                  dd      j                         }|j                  dk7  s|s-t        |j                  j                  dd      dd xs d      |S )ux   클로드 코드 CLI 경유 답변 — 웹/폰 SHIN과 연동 (CEO 지시 2026-07-06). model: sonnet|opus|claude-fable-5)rD   rE   claude-fable-5rD   u  너는 도진웍스 용접공정 코파일럿 SHIN이다. 듣는 사람은 현장 작업자(사람)다. 옆에서 일 가르치는 선배처럼, 완결된 사람 말로 설명하라. 핵심 원칙: 근거 기록에 있는 대표(장인)의 표현과 설명은 요약해 뭉개지 말고 그대로 살려 인용하라. "왜 그런지"까지 풀어서 말하라. 목록 나열로 때우지 마라. 발췌에 없는 내용은 일반 용접공학 지식임을 밝혀라. 숫자를 지어내지 마라. 스타일 규칙: ①결론을 맨 앞에 한 줄로 먼저 말하고 그 다음에 이유를 풀어라. ②현장 작업자가 알아듣는 쉬운 말로. 전체 10~15줄을 넘기지 마라(길게 늘어놓지 마라). ③모르면 지어내지 말고 "확인 필요"라고 말하라. ④답의 마지막은 반드시 대표에게 다음 행동을 고르게 하는 되묻는 질문 한 줄로 끝내라. 근거 기록에 되물을 문구가 지정돼 있으면 그 문구를 그대로 쓴다. r[   u  불량·문제 진단 질문이면 장인이 옆에서 진단하듯 답하라: ①가장 의심되는 가설 하나를 먼저 말한다("저는 ~부터 의심합니다") + 그렇게 보는 이유. ②확신의 정도를 밝힌다(사진/정보만으로 확정 못 하면 못 한다고). ③지금 바로 확인할 것 2~3가지를 가능성 높은 순서로 — 하나씩 제거하는 순서다. 원인을 몽땅 나열하지 마라. ④근거 기록·사례를 연결하되, 조건이 다른 제품의 수치는 "그대로 적용하지 마세요" 안전장치를 붙인다. 근거에 판단트리(TREE-)가 있으면 그 트리 순서를 따라라. 단순 조회면 짧게. u   

[근거]
r   Np     

[질문] rF   rG   r4   T   )inputr:   r;   rI   rJ   r      u   claude 빈 응답)
r>   r*   rN   encoderQ   rR   rS   
returncodeRuntimeErrorrT   )qctxrV   framerU   rW   r#   s          r   
ask_clauderg      s    88(%
iE    y 	z %%ET(::_LqPF
D)U;6==QXCY&*C	9A
((//'(/
3
9
9
;C||q188??78?DTcJaNabbJr   c                    d|xs dd d z   dz   | z   }t        j                  ||ddddd	      j                         }t        j                  j                  t        j                  j                  d
|ddi      d      }t        j                  |j                               j                  dd      j                         S )Nu  너는 도진웍스 용접공정 코파일럿 SHIN이다. 아래 공정서 발췌를 최우선 근거로 한국어로 답하라. 판단이 필요한 질문이면 ①현상 ②원인·근거(출처) ③결론 순으로 답하고, 단순 조회면 2~3문장. 근거가 없으면 "공정서에 없음", 불확실하면 "확인 필요"라고 말하라. 숫자를 지어내지 마라.

[공정서]
r   r\   r]   F皙?   temperaturenum_predict)rV   rU   streamoptions#http://localhost:11434/api/generateContent-Typeapplication/jsondataheadersZ   r;   response)jsondumpsra   urllibrequesturlopenRequestloadsr,   getrS   )rd   re   rV   rU   bodyrW   s         r   
ask_ollamar      s    \ `c  `i  gi  kp  lp  _qq tCC FGGF ::525c"JL MMSVX 	v~~55-D!34  6  6?A 	 	CA ::affh##J399;;r   u  공정|용접|어떻게|들어왔|시작|셋팅|세팅|조건|불량|가접|준비|제작|자재|입고|부터|도면|치수|씨앗|로봇|티칭|판A|판B|준설|크레인|붐|각도|토치|전류|전압|사진|핀|경로|지그|절단|취부|조립|검사|도장|\d{3,}c                    | xs dj                         }|r|j                         dv r't        j                  j	                  t
              rdS dS d|j                         v r$t        j                  j	                  t
              ry|dk(  sI|j                  d      s8|j                  d      s't        j                  j	                  t
              rdS dS |S )u*  [CEO 2026-07-22 시연 안정화] 답변 엔진 기본값 = Claude 소넷.
    · 브라우저에 저장된 값(dzw_shin_engine)이 비어 있거나 알 수 없으면 Claude 로 떨어진다.
    · deepseek-r1 계열은 추론용(<think> 출력·14B)이라 공정서 근거 12,000자를 물면
      Ollama 90초 응답한도를 넘겨 답이 비고, 대신 엉뚱한 문서 조각이 화면에 나갔다(실측 사고).
      → 서버에서 Claude 소넷으로 승격한다. llama3.1·qwen 등 다른 로컬 모델 선택지는 그대로 둔다.
    r   )	undefinednullautodefaultclaudezollama:llama3.1:8bdeepseek-r1claude:ollama:)rS   lowerr	   r
   existsrN   
startswith)enges     r   pick_enginer      s     
A	EEGGNN:6Q<PQ	!bggnnZ&@MQ\\)4Y8OGGNN:6Q<PQHr   c                 z   | xs dj                         }|syt        j                  dd|      }t        |      dkD  ryt        j                  |      ryt        j                         }t        j
                  d|      r:|j                  d}}|dk\  rd|dkD  r|dz
  nd}}|d	k(  rd}d
|||j                  fz  S t        j
                  d|      r6d|j                     }d|j                  |j                  |j                  |fz  S t        j
                  d|      ryt        j
                  d|      ryt        j
                  d|      ryt        j
                  d|      ryt        j
                  d|      ryt        j
                  d|      ryt        j
                  d|      ryt        j
                  d|      ryy)uW   인사·상태 질문이면 즉답 문자열, 아니면 None(=기존 경로 그대로).r   Nu   [\s,.!?~…·]+   u$   몇시|지금몇|시간알려|시각u   오전   u   오후r   u   지금 %s %d시 %d분입니다.u5   며칠|몇일|오늘날짜|날짜|무슨요일|요일u   월화수목금토일u.   오늘은 %d년 %d월 %d일 %s요일입니다.uN   뭘할수|뭐할수|무엇을할수|뭐가능|기능|도와줄수|할수있는u  저는 도진웍스 현장 코파일럿 SHIN입니다. 이런 걸 도와드립니다.
· 제관 공정 안내 — 어떤 순서로 작업할지 공정서 근거로 알려드립니다.
· 씨앗 지식 검색 — 대표님이 쌓아두신 현장 노하우에서 답을 찾아드립니다.
· 사진 공정서 브리핑 — 3D 화면의 핀 사진을 짚어가며 설명드립니다.
· 로봇 티칭 연계 — 말씀하시면 뷰어에서 자세·경로를 함께 확인합니다.
궁금한 작업이 있으시면 편하게 물어보세요.uH   누구야|누구니|누구세요|넌누구|네이름|이름이뭐|정체u{   저는 도진웍스의 현장 코파일럿 SHIN입니다. 제관·용접 공정 지식을 찾아 대표님을 돕습니다.uV   들려|들리니|들리세요|잘들|응답해|거기있|살아있|테스트|말들려u2   네, 대표님. 잘 들립니다. 말씀하세요.u%   고마워|고맙|감사|수고|잘했uD   감사합니다, 대표님. 더 필요하시면 말씀해 주세요.u   미안|죄송u6   괜찮습니다, 대표님. 편하게 말씀하세요.uI   ^(안녕|하이|헬로|여보세요|신아|샤인|굿모닝|좋은아침)uH   안녕하세요, 대표님. SHIN입니다. 무엇을 도와드릴까요?u/   ^(잘가|끝|종료|그만하자|수고했어)$u8   네, 대표님. 필요하실 때 다시 불러주세요.u(   잘지내|기분어때|괜찮아|어때$uA   저는 준비돼 있습니다, 대표님. 무엇부터 볼까요?)rS   resublen
_DOMAIN_REsearchtime	localtimetm_hourtm_mintm_wdaytm_yeartm_montm_mday)rd   tsnowhapyos          r   	smalltalkr      s   	
bAT
!2q)A
1v{4D
..
C	yy8!<X27HRq2vRB6r10B3::3FFF	yyI1M$S[[1?3;;PSPZPZ\_\g\gikBlll	yybdefN 
yy\^_` M	yyjlmnC	yy91=U	yy!1%G	yy]_`aY	yyCQGI	yy<a@Rr   i  u   E:\VLA시스템c                  h   g a t        j                  j                  t        d      } t        j                  j                  |       sy t        j                  |       D ]  }|j                  d      s	 t        j                  t        t        j                  j                  | |      d            }|j                  dg       D ]C  }t         j                  |d   |d   |d   j                         |j                  d|      d	       E  t        d
t!        t               d       y # t        $ r Y w xY w)Nu	   _QA뱅크z.qa.jsonr4   r5   qard   asrc)rd   r   lowr   u   [지식서버] QA뱅크:u   문항)QAr	   r
   r   ROOTisdirlistdirendswithry   loadr+   r   appendr   r   printr   )qdirfndits       r   load_qar   &  s    	B77<<k*D77==jj{{:&			$rww||D"5HIAeeD"o		3bgbgmmoVWV[V[\aceVfgh &	  

$c"gx8  		s   2BD%%	D10D1))u   어떻게\s*(시작|들어가|해|하면|가야|진행)\w*|들어가야?\s*[돼되해]\w*|뭐부터|어디서부터|착수|절차|순서|시작\w*u   순서)uO   해야\s*[돼되해할]\w*|하면\s*[돼되]\w*|할까요?|인가요?|입니까r   )u   스피드|빠르기|속도\w*u   속도)u    암페어|전류\w*|몇\s*[aA]\bu   전류)u   볼트|전압\w*u   전압)u\   얼마야|얼마|몇이야|몇\b|알려줘|알려주|말해줘|뭐야|뭔데|어떻게\s*돼r   )u   보스|bossboss)u   너클붐|크레인12500)u   트랙\s*서포트u   트랙서포트)u)   용접\s*조건|셋팅\s*값|설정\s*값u   조건)u;   왜\s*생[겨기]\w*|생기는\s*이유|원인이?\s*뭐\w*u   이유)uG   줄이려면|줄이는|줄일려면|잡으려면|안\s*나게|방지\w*u   줄이)u   방법|하는\s*법r   c                 ^   | j                         } t        D ]  \  }}t        j                  |||       }  t        j                  dd|       } g }| j	                         D ]<  }d }||k7  r|}t        j                  dd|      }||k7  r|s,|j                  |       > dj                  |      S )Nu   [,?？!.~]+ uY   (?<=[가-힣])(은|는|이|가|을|를|의|로|에서|부터|도|좀|요|이야|야|만)$r   )r   SYNr   r   splitr   r   )r   patreptoksr   prevs         r   normr   E  s    		ASRVVCa0C
~sA&ADWWY4iDsuwyz{A 4i dkk!n  88D>r   c                     | j                  dd      } t        |       dkD  r+t        t        |       dz
        D ch c]
  }| ||dz     c}S | hS c c}w )Nr   r         )r=   r   range)r   is     r   bigramsr   S  sQ    			#rA25a&1*eCF1Ho.oAa!Ho.E1#E.s   Ac           	        	
 t        |       }t        |      dk  ryt        j                  d|      }t	        |      }g }t
        D ]  	|rt        	fd|D              s	j                  d      xs 	j                  dt        	d               
t	        
      }t        ||z        t        dt        ||z              z  }t        
fd|j                         D              }|j                  ||d	z  z   	|f        |sy|j                  d
        |d   }|d   dk  ry|d   dk  ryt        |      dkD  r&|d   d   d   |d   d   k7  r|d   d   |d   dz  kD  ry|d   t        |d   d      fS )up   정규화+제품앵커+바이그램 유사도. 애매하면 None → 상위 파이프라인이 검색/LLM 폴백r   Nr   z\d{4,}|[a-z]-?\d{6,}c              3   `   K   | ]%  }|d    d   z   d   z   j                         v  ' yw)r   rd   r   N)r   ).0anr   s     r   	<genexpr>zqa_match.<locals>.<genexpr>`  s8     \T[brah3&7!C&&@%G%G%IIT[s   +.nqrd   r   c              3   J   K   | ]  }t        |      d k\  s|v sd  yw)r   r   N)r   )r   r   nds     r   r   zqa_match.<locals>.<genexpr>e  s"     BJq#a&A+!r'Js   ###g333333?c                     | d    S r    xs    r   <lambda>zqa_match.<locals>.<lambda>h  s
    qter   keyr   g      ?g?r   gq=
ףp?)r   r   r   findallr   r   anyr   
setdefaultmaxsumr   r   sortround)rd   r   anchorsqbscoreddbsimkwtopr   r   s            @@r   qa_matchr   W  sm   	aB
2w{9jj0"5G	BF3\T[\\UU4[<ALLtAcF|<R["r'lSCRL11BBHHJBBsR$Y3/0  )
KKOK$
)C
 1v}Y
1v}Y
6{Q6!9Q<,As;q	!sSTvX\}@\FE#a&!$%%r   uF   E:\지식정제시스템\05_KNOWLEDGE\헌법서\AI_헌법서_v3.0.jsonc                     t         j                  j                  t              st	        dt               yt        j                  t        t        d            } dfd}| j                  di       xs i j                  dg       xs g D ]
  } ||        | j                  d	i       xs i j                  d
g       xs g D ]
  } ||        | j                  d
i       xs i j                         D ],  \  }}|xs i j                  dg       xs g D ]
  } ||        . | j                  di       xs i j                  dg       xs g D ]
  } ||        t	        dd       y)uo   헌법서 각 조항을 검색 문서로 편입. 원본 무수정. 이름은 '헌법-<id>'로 최상위 가중.u'   [지식서버] 헌법서 파일 없음:Nr4   r5   r   c                    t        | t              sy | j                  d      xs( | j                  d      xs | j                  d      xs d}| j                  d      xs( | j                  d      xs | j                  d      xs d}d	|d
|}t        j                  | d      }t
        j                  t        dz   t        |      z   ||dz   |z   |dz   |z   j                         |j                         d       dz  y )Nlaw_ididrule_id?name_konametitler      헌법-r   Fensure_ascii#
)r
   r   r1   r   headr   )

isinstancedictr   ry   rz   CACHEr   CONSTITUTION_PATHstrr   )itemlidr   r   r   ns        r   addz_load_constitution.<locals>.add~  s    $%vhhx PDHHTNPdhhy6IPSxx	"Qdhhv&6Q$((7:KQr"%t,zz$U3/#5C@%"T\D0%$,:M9T9T9V#kkm- 	. 	
Qr   hard_constraintsrulescontext_enginelawsitemsai_decision_principles
principlesu'   [지식서버] 헌법서 조항 편입:u   개)
r	   r
   r   r   r   ry   r   r+   r   r  )	cr  rcceaxisaxr   r   r  s	           @r   _load_constitutionr  x  sO   77>>+,79JKV		$(7;<A	A
 uu',277DJJB K uu%r*0b55fbAGRGB H UU62&,"335b8.."-33BG 4 6 uu-r28b==lBOUSUUB V	
3Q>r   c                     g a 	 t                t
        ddg}d}|D ]  }t        j                  |      D ]  \  }}t        fddD              r|D ]  }|j                         }|j                  d      s#|j                  d	      s|j                  d
      sHt        j                  j                  |      }	 t        |dd      j                         }	|j                  d	      s|j                  d
      rUt        j                   dd|	      }
t#        t        j$                  d|
            dk  rd|v sdj                         v r|dz  }|j'                  dd      j'                  dd      }t         j)                  |||	|dz   |z   dz   |	z   j                         |dz   |z   j                         t+        t        j,                  d|	      xs t        j,                  d|	            d          t        dt#        t               d|z         y # t        $ r#} t        dt	        |       d d        Y d } ~ 0d } ~ ww xY w# t        $ r Y w xY w)Nu'   [지식서버] 헌법서 로딩 실패:x   u+   E:\지식정제시스템\05_KNOWLEDGE\seedsu   E:\옵시디언r   c              3   &   K   | ]  }|v  
 y wr   r   )r   r   dps     r   r   zbuild_index.<locals>.<genexpr>  s     P$Oq17$Os   )
EMBEDDINGSMODELSOUTPUTFINETUNE.mdz.txtz.csvr4   rI   r6   rK   u&   자막제작.*|https?://\S+|by UpTitler   u	   [가-힣]r9   _sttstt_resultsr   r7   r   /r   u   \[공정\s*\d+\]u   \|\s*\*?\*?전류)r
   r   r1   r   r   specu'   [지식서버] 공정 문서 인덱스:u+   건 (VLA+씨앗, 현장구술 %d건 포함))r   r  r   r   r   r   r	   walkr   r   r   r
   r   r+   r,   r   r   r   r   r=   r   boolr   )r   rootssttroot_fnsr   flr   r1   cleanrelr  s               @r   build_indexr(    s     EG A!E C''$-JB3P$OPPRZXXZE*bkk&.AR[[QWEX[cGGLLR(q78DIIKC ;;v&"++f*=FF#LbRUVE2::lE:;b@(|}
'BC1HC iic*223<aC&)Dj2o&<s&B%I%I%K'*Sy2~&<&<&> '+2995H#+N+vRTR[R[\pruRv&wy z  ( 2 

3SZAnqtAtuA  G7QFFG  ! s)   
H =I	I!H??I	I	I	))ub   두설차|준설처|준설챠|즌설차|준썰차|준설\s*차|오수차|흡입차|하수도\s*차	   준설차)u(   하도\s*준설차|하수도\s*준설차r)  )uB   동우\s*인더스트리|동우\s*인더스|동우인더스|동우u   동우인더스트리)u7   24\s*t\b|24\s*톤|24\s*돈|이십사\s*톤|이십사톤u   24톤)u   작업\s*공정서|공정\s*서	   공정서c                 p    | j                         }t        D ]  \  }}t        j                  |||      } |S r   )r   QUERY_ALIASr   r   )rd   r   r   r   s       r   _aliasr-    s2    		ASFF3Q  Hr   c           
         g }t        |       j                  dd      j                  dd      j                  dd      j                         D ]9  }t        j                  dd|      }t        |      dk\  s)|j                  |       ; g }t        D ]  }d}|D ]M  }||j                  d	|d
   j                               v r|dz  }|t        d|d   j                  |            z  }O |dkD  r"|d
   j                  d      rt        |dz        }|dkD  r"|d
   j                  d      rt        |dz        }|dkD  r"|d
   j                  d      rt        |dz        }|dkD  r"|d
   j                  d      rt        |dz        }|dkD  s|r$t        d|d   j                  |d         dz
        nd}|j                  dd      r|d
   n|d
   j                  dd      }|j                  |d   |||d   ||dz    j                  dd      d        |j!                  d         t#               g }	}|D ]/  }
|
d
   |v r|j%                  |
d
          |	j                  |
       1 |	ra|	d   d
   j                  d      rJt'        |	      D ]<  \  }}
|
d
   j                  d      r|	j)                  d|	j+                  |              n |	d d! S )"N,r   r   r   u`   (?<=[가-힣0-9])(을|를|은|는|이|가|의|에|에서|으로|로|과|와|도|만|랑|이랑)$r   r   r   r   r      r   r   g?zLAW-g      ?zTREE-gffffff?zPATTERN-g?r9   r  Tr*  u	   안내서r
   r1   r^   r   )r
   r   scoresnippetc                     | d    S )Nr1  r   r   s    r   r   zsearch.<locals>.<lambda>  s
    AgJ;r   r      )r-  r=   r   r   r   r   r   r   r   r   mincountr   intr   findr   setr  	enumerateinsertpop)rd   termsr   r#   r   r   r   nmseenuniqr   s              r   r   r     s   EAYsC(00c:BB3LRRTFFvxz|}~q6Q;Q U CUAAEE&!F)//"344a1faQ%q)**A  q5QvY)))4#a#g,aq5QvY))&1s1s7|1q5QvY))'2AGAq5QvY))*53q3w<qq58=Aqx}}U1X.341A  eeFD16qy7H7HVa7bBJJ&	2#$U8Aae#4#<#<T3#GI J' * HH&H' $DV9h6T[[^  Q**95dODAqV9''	2Atxx{+U $ 8Or   c                   *    e Zd Zd Zd Zd Zd Zd Zy)Hc                 X   t        j                  |d      j                  d      }| j                  |       | j	                  dd       | j	                  dd       | j	                  dt        t        |                   | j                          | j                  j                  |       y )	NFr   r4   rq   zapplication/json; charset=utf-8Access-Control-Allow-Origin*Content-Length)
ry   rz   ra   send_responsesend_headerr   r   end_headerswfiler<   )selfcodeobjr   s       r   _sendzH._send  s    zz#E299'B4 )JK6<)3s4y>:

r   c           
         t         j                  j                  | j                        }t         j                  j	                  |j
                        }|j                  dk(  r2| j                  ddt        |j                  ddg      d         i       y |j                  dk(  r|j                  ddg      d   }t        j                  j                  |      }|j                  t        j                  j                  t                    r|j                  d	      s| j                  d
ddi       y 	 | j                  dt        j                  j                  |      t        |dd      j!                         d       y |j                  dk(  rIt'        |j                  ddg      d         \  }}| j                  dd|xr |d   |d   |d   |di       y |j                  dk(  rg }t        j                  j)                  t*              r<|j-                  ddd       |j-                  ddd       |j-                  ddd       	 t         j.                  j1                  dd !      }	t3        j4                  |	j!                               j                  d"g       D ]7  t7        fd#d$D              s|j-                  d%d&   z   d&   d'z   d       9 	 | j                  dd"|i       y |j                  d(k(  rEt9                t;                | j                  dd)t=        t>              t=        t@              d*       y |j                  d+k(  r	 |j                  d,dg      d   }
|
d-v r|
a!tE        |j                  d.dg      d   |
r|
ntB              \  }}| jG                  d       | jI                  d/|       | jI                  d0d1       | jI                  d2t%        t=        |                   | jK                          | jL                  jO                  |       y |j                  d4k(  s|j                  d5k(  rtP        jS                  d      }| jG                  d       | jI                  d/d6       | jI                  d2t%        t=        |                   | jK                          | jL                  jO                  |       y |j                  d7k(  r1| j                  dd)t=        t>              t=        t@              d*       y | j                  ddd8i       y # t"        $ r'}| j                  ddt%        |      i       Y d }~y d }~ww xY w# t"        $ r Y w xY w# t"        $ r'}| j                  d3dt%        |      i       Y d }~y d }~ww xY w)9Nz/api/searchr`   hitsrd   r   r   z	/api/readr   r  i  erroru   VLA 폴더 내 md만 허용r4   rI   r  )r   r$     z/api/qahitr   r   )rd   r   r   r1  z/api/modelsr   u   Claude 소넷)r   labelzclaude:opusu   Claude 오푸스zclaude:claude-fable-5u   Claude 페이블zhttp://localhost:11434/api/tagsr0  rw   modelsc              3   ,   K   | ]  }|d    v   yw)r   Nr   )r   kms     r   r   zH.do_GET.<locals>.<genexpr>$  s     f3ea1&	>3es   )zllama3.1z	qwen2.5vlr   gemma3r   r   u	    (로컬)z/api/reloadT)okdocsr   z/api/ttsr-   )r   zko-KR-InJoonNeuralzko-KR-HyunsuMultilingualNeuralr$   rq   rD  rE  rF    z/devz/dev/ztext/html; charset=utf-8z	/api/pingunknown)*r{   parseurlparser
   parse_qsqueryrN  r   r   r	   abspathr   r   r   basenamer+   r,   r   r   r   r   rN   r   r|   r}   ry   r   r   r(  r   r   r   r   r)   rB   rG  rH  rI  rJ  r<   DEV_PAGEra   )rK  uqsr   rpr   rS  scrU  rW   r%   rt   ctyper   rX  s                 @r   do_GETzH.do_GET	  sn   LL!!$)),\\""177+66]"JJsVVBFF3,=a,@%ABCVV{"sRD!!$A#B==!67r{{5?Q

3*G HI63

3)9)9")=)-b78)T)Y)Y)[!] ^ VVy rvvcB4034GCJJsUC$j#c(SRUV[R\gi,jklVV}$Fww~~j)XHI]=OPQ%<GYZ[#NN**+LVW*XAFFH-11(B?Af3effY6-BQvYYdMd&ef @ JJsXv./VV}$M79JJs4U3r7KLVVz!3FF7RD)!,ee !I!"&&""6q"91yQe""3'  7  !>D  !13s4y>B  "DJJ$4$4T$: VVv7!2??7+Ds#^-GH-s3t9~>

 0 0 6VV{"JJs4U3r7KLJJsWi01[  3

3#a& 1223  "d"$  3

3#a& 1223sK   2AT 	A+U 5"U CU 	U!UU	UU	V$VVc                 t"  0 | j                   dk(  r	 d}t        j                   j                  |      r t        j                  t        |d            ndg i}t        d |j                  dg       D        d       }| j                  d|t        d |j                  dg       D              d	       y | j                   dk(  r8	 t        | j                  j                  dd            }t        j                  | j                  j!                  |            }|j                  dd      |j                  dd      |j                  dd      }	}}d|d|}
	 t#        |
dd      }t'        j(                  d|t&        j*                        }|r$t        j                  |j-                  d            nd|d}|j                  d      rd}t        j.                  |d       t        t        j                   j1                  |d      dd      5 }|j3                  t        j4                  t7        j8                  d      d|||j                  d |      d!d"#      d$z          d d d        d%}t        j.                  |d       t        t        j                   j1                  |d&      dd      5 }|j3                  d'|d(|d)|j                  d |      d$       d d d        	 t        j                   j1                  |d*      }t        j                  t        |d            }|j                  dg       D ]  }|j                  d      |	k(  sd|d+<    t        j:                  |t        |d,d      d"d-.       | j                  dt=        |j                  d            |j                  d/d      |j                  d d      |j                  d      rd0|j                  d d      z   n|j                  d/d1      d2       y | j                   d5k(  r=	 t        | j                  j                  dd            }t        j                  | j                  j!                  |            }d6|j                  dd7      z   }t        j4                  d8||j                  d9d      gd"d:d;d<d=      j?                         }t@        jB                  jE                  t@        jB                  jG                  d>|d?d@iA      dBC      }| j                  ddDt        j                  |j!                               j                  dEd      jI                         i       y | j                   dIk(  r3	 t        | j                  j                  dd            }t        j                  | j                  j!                  |      jK                  ddJK            }t        j                   j1                  tL        dL      }t        j.                  |d       |j                  dMd      xs dNd dO xs dP}t        t        j                   j1                  ||dQz         dd      5 }|j3                  t        j4                  |d"#      d$z          d d d        | j                  ddRdi       y | j                   dSk(  r	 t        | j                  j                  dd            }t        j                  | j                  j!                  |      jK                  ddJK            }|j                  dTd      }dU|v r|jO                  dU      dV   n|}tQ        |      }|r| j                  d|dWdX       y tS        |j                  dTd      |j                  dYdZ            }| j                  ddD|i       y | j                   d[k(  r	 t        | j                  j                  dd            }t        j                  | j                  j!                  |            }|j                  dd      |j                  d\d      }}tQ        |      }|r| j                  dg |d]       y |j                  d^g       xs g }|r*d$j1                  d_ |d`d  D              }da|z   dbz   |xs dz   }	 t)        |      } | rgg }!| d dc D ]A  0t        0fddtT        D        d       }|s|!jW                  de0df   z   d$z   |dg   d dh z          C |!r|diz   dbj1                  |!      z   d dj }dk|xs dz   dlz   |z   }"tY        |j                  dm            }#	 |#dnk(  s|#j[                  do      r)dp|#v r|#jO                  dpd-      d-   ndq}$t#        |"d|$      }%n t%        |"d|#jO                  dpd-      d-         }%t'        j(                  d|%t&        j*                        }	 |r$t        j                  |j-                  d            ng |%jI                         d dr d]}&t]        ds      }'h dt}(g })|&j                  dug       xs g D ]  }t_        |t`              s|j                  dv      xs |j                  dw      }*|*|(vr=|*dxv rt        |j                  dyd            jc                         }+|+|'vrote        |j                  dz|j                  d{d                  },tg        d}ti        d~|,            },d|+|,|j                  dd      t        |j                  dd            d d d}|)jW                  |        | j                  d|)t        |&j                  dd            d dr d]       y | j                   dk7  r| j                  ddGdi       y 	 t        | j                  j                  dd            }| j                  j!                  |      }%	 t        j                  |%jK                  d            }|j                  d      xs |j                  d      xs d|j                  d\d      }}tQ        |      }|r| j                  d|dWdX       y |j                  d^g       xs g }|r*d$j1                  d |d`d  D              }d|z   dbz   |xs dz   }	 t)        |      } | rpg }!| d dc D ]J  0t        0fdtT        D        d       }|s|!jW                  de0df   z   dz   0d   z   dz   |dg   d d z          L |!r|dz   dbj1                  |!      z   d d }tY        |j                  dm            }#t=        |j                  dd"            }-	 |#dnk(  s|#j[                  do      r.dp|#v r|#jO                  dpd-      d-   ndq}$t#        |||$      }do|$z   }.n"t%        |||#jO                  dpd-      d-         }|#}.	 |.j[                  do      rt        j.                  tl        d       t        t        j                   j1                  tl        dt7        j8                  d      z        dd      5 }|j3                  t        j4                  t7        j8                  d      |.||xs dd d |dd"#      d$z          d d d        | j                  d||.dX       y # t        $ r+}| j                  dd t        |      d d
 d       Y d }~y d }~ww xY w# t        $ r t%        |
dd      }Y 7w xY w# 1 sw Y   CxY w# 1 sw Y   xY w# t        $ r Y Ow xY w# t        $ r,}| j                  dd"d3t        |      d d
 d4       Y d }~y d }~ww xY w# t        $ r*}| j                  dFdGdHt        |      z   i       Y d }~y d }~ww xY w# 1 sw Y   xY w# t        $ r'}| j                  dFdGt        |      i       Y d }~y d }~ww xY w# t        $ r'}| j                  dFdGt        |      i       Y d }~y d }~ww xY w# t        $ r Y w xY w# t        $ r t%        |"dd      }%Y Xw xY w# t        $ r g |%jI                         d dr d]}&Y w xY w# t        $ r d|},Y mw xY w# t        $ r,}| j                  dg dt        |      d d d       Y d }~y d }~ww xY w# tj        $ r* t        j                  |%jK                  ddJK            }Y w xY w# t        $ r Y w xY w# t        $ rR}/|-r'| j                  dd|#t        |/      d d d       Y d }/~/y t%        ||d      }dt        |/      d d z  }.Y d }/~/sd }/~/ww xY w# 1 sw Y   xY w# t        $ r Y w xY w# t        $ r*}| j                  dFdGdt        |      z   i       Y d }~y d }~ww xY w)Nz/api/interview/nextu3   E:\VLA시스템\KNOWLEDGE\_역질문\질문큐.jsonr4   r5   r  c              3   D   K   | ]  }|j                  d       r|  yw)answeredNr   r   r   s     r   r   zH.do_POST.<locals>.<genexpr>K  s     Y)>2bffZFXB)>     r`   c              3   D   K   | ]  }|j                  d       rd  yw)rm  r   Nrn  ro  s     r   r   zH.do_POST.<locals>.<genexpr>L  s"     ;xH]"egekeklvewAH]rp  )rd   	remainingrL   )rd   rQ  z/api/interview/answerrF  r   rd   r   r   r   u  너는 장인의 암묵지를 캐내는 인터뷰어 SHIN이다. 아래 질문에 대한 대표(장인)의 구술 답을 보고 JSON 한 줄로만 답하라: {"enough":true/false,"followup":"되물을 한 문장(enough=false일 때만)","clean":"지식으로 저장할 완결된 한두 문장(enough=true일 때, 대표 표현 살려서)"}. 수치가 빠졌거나 애매하면 enough=false로 딱 한 가지만 더 물어라. 지어내지 마라.
[질문] u   
[대표 구술답] r[   zllama3.1:8bz\{.*\}T)enoughr&  rs  r   )exist_okzceo_interview.jsonlz%Y-%m-%d %H:%M:%Svoice_interviewr&  )tsviard   r   r&  Fr   r   u$   E:\VLA시스템\KNOWLEDGE\_역질문u   _CEO답변_흡수본.mdz
**Q: u   **
- A(구술): u   
- 정리: u   질문큐.jsonrm  r3   r   )r   indentfollowupu%   알겠습니다, 기록했습니다. u)   조금 더 자세히 말씀해 주세요.)rs  ry  r&  sayu#   다시 한 번 말씀해 주세요.)rs  rz  rQ  z/api/seeu  너는 용접공장 코파일럿 "SHIN"의 눈이다. 사진은 용접 작업장/제품이다. 한국어 2~4문장으로 관찰 사실만 답하라(제품 형상, 판재 구성, 용접선 위치, 가접 상태, 이상 여부). 확실하지 않으면 추정임을 밝혀라.
질문: u   무엇이 보이나zqwen2.5vl:7bimgri   ,  rk   )rV   rU   imagesrn   ro   rp   rq   rr   rs   r^   rw   answerrx   r\  rQ  u   VLM 불가: z/api/logr=   rJ   u   SHIN세션로그r   z
0000-00-00
   undatedz.jsonlrZ  z/api/devrU   u   [대표의 말]r   )r~  enginerV   rE   z/api/actre   )actionsrz  historyc           	   3      K   | ]7  }|j                  d d      dt        |j                  dd            dd  9 yw)roler   : r$   Nr|  r   r   r   r   s     r   r   zH.do_POST.<locals>.<genexpr>  s>     "uktfgfb0A3quuVUWGXCYZ^[^C_$`kt   =?iu   [직전 대화]
z

   c              3   :   K   | ]  }|d    d    k(  s|  ywr
   Nr   r   r   r   s     r   r   zH.do_POST.<locals>.<genexpr>  s!     %QA!F)qy:Pa   z### r   r1   i  u   

[공정서 근거]
i(#  u  너는 3D 로봇 티칭 뷰어를 직접 조작하는 코파일럿 "SHIN"이다. 대표의 말을 로봇 행동으로 번역한다.
반드시 JSON 한 줄로만 답하라(설명 문장 금지). 형식:
{"actions":[{"type":"adjust_joint","step":"current","axis":"B","delta_deg":-5,"reason":"토치 각도 과대"}],"say":"현재 스텝 B축을 5도 안쪽으로 접었습니다"}
지원 type: adjust_joint(관절 미세조정; axis는 S,L,U,R,B,T 중 하나, delta_deg는 상대각 -45~45, step은 "current" 또는 스텝번호), goto_step(step=번호), play, pause, stop, run_collision(충돌검사), show_weld_path(용접경로), add_point(포인트추가), go_mech_zero(기계적원점), go_work_home(홈자세), analyze_u(U축분석), undo(직전조정 되돌리기).
규칙: axis는 반드시 S,L,U,R,B,T 중 하나. delta_deg 범위 -45~45. "안쪽으로 접어/각도 줄여/숙여"=음수, "펴/키워/세워"=양수 (문맥으로 판단). 조작이면 actions를 채우고 say엔 무엇을 얼마나 바꿨는지 한 문장. 행동이 아닌 순수 질문이면 actions는 빈 배열 []로 두고 say에 한국어 답만 넣어라. 지어내지 마라.
[현재 상태] u   
[대표 말] r  r   r   :rD   r   SLURBT>   jogplaystopundopause	add_point	analyze_u	goto_stepadjust_jointgo_mech_zerogo_work_homerun_collisionshow_weld_pathr  typeaction)r  r  r  	delta_degdeltag        g     Fg     F@r  stepcurrentreasonr  )r  r  r  r  r  rz  )r  rz  rQ  z/api/askrR  r]  cp949questionc           	   3      K   | ]7  }|j                  d d      dt        |j                  dd            dd  9 yw)r  r   r  r$   Ni  r  r  s     r   r   zH.do_POST.<locals>.<genexpr>  s>     qgpbcAEE&",=s155QSCT?UVZWZ?[ \gpr  uu   [직전 대화 — 이걸 기억하고 답하라. "적용해줘/그거/방금 그것"은 이 대화에서 찾아라]
c              3   :   K   | ]  }|d    d    k(  s|  ywr  r   r  s     r   r   zH.do_POST.<locals>.<genexpr>  s!     !MUai1V96L!Ur  u
    (출처: r
   z)
i  u'   

[공정서 근거 — 자동 검색]
i.  no_fallback)r~  r  rQ  u!   ollama:llama3.1:8b(폴백 — %s)<   zdistill_%s.jsonlz%Y%mr\   )rv  rV   rd   re   r   u   LLM 불가: )7r
   r	   r   ry   r   r+   nextr   rN  r   r   r   r7  ru   r   rfiler,   rg   r   r   r   Sgroupmakedirsr   r<   rz   r   strftimedumpr  ra   r{   r|   r}   r~   rS   rR   rP   r   r   rY   r   r   r   r   r9  r   r   upperfloatr   r5  UnicodeDecodeErrorDISTILL_DIR)1rK  qprt   nxtr   r  reqrd   r   qidjudgeverdictrX  r%   ddr.   adr   r   rU   r   rW   reclogdirday_p_saidstansre   histhlrP  fragschemar   cmrawrM  AXESOKr&  r   r  dlr  usede1r   s1                                                   @r   do_POSTz	H.do_POSTD  s   99--DK@Br@Rtyyb7!;<Y`bdXeY'2)>Y[_`

3c;xQXZ\H];x8x yz 99//"x(()91=>jj!34GGC,cggc2.>b@Qc1
 BCA	G
C(4DEG IIi"$$7./DJJqwwqz*q5Q55?BBBKKPR]aDbbggll2/DEsU\]ab

$--@S2T]n12QUU7TUEV,Xfk!mos!t u ^ AB"++b[_B`bggll2/HI3Y`aefRSUVXYX]X]^eghXi jk b+WW\\".>?TYYtTVahOiEj"#%%"4B!vvd|s2TBzN #5		!T"cG%DSXabc

34h+@aeeT^`bNc*+%%*<$%EE(O Gnpqpupuv}  @B  qC  GC9:zKv9w!y z
 99
"D(()91=>jj!34UWZW^W^_bdyWz{ zzNf.1ggeR.@-AU>ARU.V#X YY_Y_Ya  NN**6>>+A+A9+-?@ ,B ,BKN + P 

34::affh+?+C+CJPR+S+Y+Y+[ \] 99
"
3(()91=>jj!3!:!:79!:!UVk3EFFT2wwsB'7<"=J"'',,vsX~>gVZ[GGDJJs?$FG W

3t- 99
"3(()91=>jj!3!:!:79!:!UV WWXr*;LPR;R!23B7XZu%JJsr[$IJF$SWWXr%:CGGGV<TU

330 99
"GS(()91=>jj!34b)3775"+=3q\JJs2$>?wwy"-3"ukoprpskt"uuB.3f<	rJC'!!9D!!%bqA $%Q%QSW XA $++fqy.@4.G!E(SXTX/.Y"Z "*  .H(H6;;W[K\(\^c_c'd' +.)5 8II LMM  "#''("34@h#..*C58CZSYYsA.q1X(R8(SYYsA5Fq5IJ IIibdd3D45$**QWWQZ0rRUR[R[R]^b_bRc;dC 8}j'')R06B6A%a.f8xA{H33 vr!2399;T>8"'k155!;L(M"NR D"6%3Rb%&UU69%=QUUS[]_M`IabfcfIgiLLO 7 

3E#cggeR>P:QRVSV:W XY 99
"JJsWi0166	@DLL$$%5q9:A **//!$CHjjG!45 ggcl?cggj&9?R#''%QSBTsA1B

32 EF779b)/RDYYqgklnlogpqq P  SU  U  X^  ^  be  bk  ik  l#ayD!"1X !MU!MtTdkk&1V9*<|*KaPVi*WZ_*_bcdibjkplpbq*qr & C*V$VY_YdYdeiYj$jlrmr#sScggh/0Csww}e<=Ks(?cnnY&?143*1-B$QR0CR$$QSYYsA->q-ABC3D#??9-KKd;bggll;8JT]][aMb8bcehsz{  @A

$--@S2T_c12CI2u;MTW,Ygl!npt!u v | JJssd;<w  D

3dSVDS\ BCCD  ! C(MBGC ^] ba %*d*  x

359^ilmnioptqtiu vwwx$  D

3.3q6*A BCCD WV  3

3#a& 1223   3

3#a& 12236 !&$&. ! @$VR?C@
 ! D&(Tc1BCCD  )2s"2  S

3BrCF4CL QRRS & HjjGI!FGH, "d"  sJJsrS3r7SWTW=$YZ\b C7@cfijlfmnqoqfr@rs |{ "d" 	@JJsWns1v&=>??	@s  By B{ y>  B'{ AzA{ ',z({ A)z5 ,z5 2B{ 	D;{= C+}  *|3+}  B2}3 A }3 BA@ 7AA@ :2~& -A~& .)A@ A~6 7%A@ < BA@ /+9BA@ A AD $AA 3AAD AAD 2AA9 A
AA9 5AD A&AB	 -A2AC4 A
AC')AC4 1AD 	y;!y66y;>z{ z{ z% { (z2-{ 5	{>{ {{ 	{:"{55{:=	|0 |++|03|=8}   	}0	}++}03	~#<~~#&	~3/A@ 2~33A@ 6A@ A@ 62A@ 566A@ 9A@@A@ @A@@A@ @	AA @"A@;@;AA A/AA6A2AD A5AA6A6AD A9	ABBAD BABBAD B		AC$B$ACB6AD B;ACCAD CAC$C$AD C'AC1C,AC4 C4	ADC=AD D ADDAD D	AD7D AD2D2AD7c                     | j                  d       | j                  dd       | j                  dd       | j                          y )N   rD  rE  zAccess-Control-Allow-Headersrq   )rG  rH  rI  )rK  s    r   
do_OPTIONSzH.do_OPTIONS+  s>    36<7Hr   c                      y r   r   )rK  r   s     r   log_messagezH.log_message0  s    tr   N)__name__
__module____qualname__rN  rj  r  r  r  r   r   r   rB  rB     s    :2vf@N
 $r   rB  __main__z	127.0.0.1u2   [지식서버] http://127.0.0.1:%d (로컬 전용)r   )rE   )rD   )=http.serverhttpsocketserverr	   r   ry   urllib.parser{   urllib.requestr>   r   	threadingr   r  LockrM   r)   r   r   r/   r@   rB   r
   
expanduserrN   dirnamerb  __file__rP   rO   rY   rd  rg   r   compiler   r   r   PORTr   r   r   r   r   r   r   r   r   r  r(  r,  r-  r   serverBaseHTTPRequestHandlerrB  r  ThreadingTCPServersrvr   serve_foreverr   r   r   <module>r     s   t s s s s s7y~~	Z
$$ WW :;
ggoobggooh78 z"KZ@
<( RZZ S T
 &R 
9 F&< ^ ?B(v\*Xp$** p$d	 zMI	(	(	(+t)<a	@CBTIJ 
A	@  
A	@s   ;E!!E*