
    i_                       d dl mZ 	 d dlZd dlZd dlZd dlZd dlmZ ddlm	Z	 ddl
mZ ddlmZ ddlmZ dd	lmZ d
ZdZdZdZ ej,                  ej.                  dd        ej0                  e      Zd"dZd#dZd$dZd%dZd%dZd%dZ d%dZ!d%dZ"d%dZ#d%dZ$d%dZ%d%dZ&d%dZ'd%dZ(d&dZ)d'd Z*ed!k(  r ejV                   e*              yy)(    )annotationsN)Path   )parse_kakao_chat)extract_knowledge)extract_knowledge_v2ChatMessage)	WikiStorez+/home/jay/projects/insuwiki/data/chroma_db/z*/home/jay/projects/insuwiki/data/insights/z+/home/jay/projects/insuwiki/data/graph.jsonz4/home/jay/projects/insuwiki/data/insights_index.jsonz1%(asctime)s [%(levelname)s] %(name)s: %(message)sz%H:%M:%S)levelformatdatefmtc                x    | j                         }|d   D cg c]  }|j                          c}|d<   |S c c}w )uS   parse_kakao_chat 결과의 ChatMessage 리스트를 dict 리스트로 변환한다.messages)copy
model_dump)resultdatams      ?/home/jay/projects/insuwiki/scripts/kakao_knowledge/__main__.py_serialize_parse_resultr   8   s8    ;;=D04Z0@A1ADK Bs   7c                >    | D cg c]  }t        di | c}S c c}w )uM   JSON에서 로드한 dict 리스트를 ChatMessage 리스트로 복원한다. r	   )messages_rawr   s     r   _deserialize_messagesr   ?   s    &23K!333s   c                    t        j                  | dd      }|r+t        |      j                  |d       t	        d|        yt	        |       y)u=   데이터를 JSON으로 파일 또는 stdout에 출력한다.F   ensure_asciiindentutf-8encodingu   저장 완료: N)jsondumpsr   
write_textprint)r   output_pathtexts      r   _write_outputr*   I   sE    ::dq9D[$$TG$<}-.d    c           	     (   t        d| j                          t        | j                        }t        |      }t	        || j
                         |j                  di       }t        d|j                  dd       d|j                  dd       d       y)	uF   parse 서브커맨드: 카카오톡 txt 파일 파싱 → JSON 저장.u   파싱 중: statsu   파싱 완료 — 메시지: total_messagesr      건, 고유 사용자: unique_users   명)r'   inputr   r   r*   outputget)argsr   
serializedr-   s       r   	cmd_parser7   X   s    	L
%&djj)F(0J*dkk*JJw#E	
'		2BA(F'G H"YY~q9:#	? r+   c           	     D   t        d| j                          t        j                  t	        | j                        j                  d            }t        |j                  dg             }|j                  di       j                  dd      }| j                  r| j                  }t        dt        |       d	| j                  rd
nd d       t        || j                  t        | dd      |      }t        || j                         t        dt        |       d       y)uJ   extract 서브커맨드: 파싱된 JSON → 지식 추출 → JSON 저장.   로딩 중: r!   r"   r   header	chat_name u   지식 추출 중 (메시지 	   건, LLM=	   활성화   비활성화) ...api_keyNuse_llmrA   source_chatu   추출 완료 — wiki_entry:    건r   )r'   r2   r$   loadsr   	read_textr   r4   r;   lenrC   r   getattrr*   r3   r5   rawr   rD   entriess        r   cmd_extractrM   f   s    	L
%&
**T$**%///A
BC$SWWZ%<=Hwwx,00bAK~~nn	
'H 7"ll{?u	F  i.	G '4;;'	*3w<.
<=r+   c                   t        d| j                          t        j                  t	        | j                        j                  d            }t        |t              st        dt        j                         y|}t        | dd      xs d}t        |      }	 |j                  |      }|j                          t        d	| d
t        |       d       y# |j                          w xY w)uL   import 서브커맨드: JSON 파일의 항목을 WikiStore에 일괄 저장.r9   r!   r"   u9   오류: JSON 파일의 최상위가 list여야 합니다.filer   db_pathNu   import 완료 — /u
   건 저장r   )r'   r2   r$   rF   r   rG   
isinstancelistsysstderrrI   r   bulk_importcloserH   )r5   rK   rL   rQ   storecounts         r   
cmd_importr[      s    	L
%&
**T$**%///A
BCc4 IPSPZPZ[G!$	48@DGgE!!'*	ugQs7|nJ
?@ 	s   C C+c                    t        | dd      xs d}t        |      }	 |j                         }|j                          t	        t        j                  |dd             y# |j                          w xY w)u/   stats 서브커맨드: WikiStore 통계 출력.rQ   NFr   r   r   )rI   r   	get_statsrX   r'   r$   r%   )r5   rQ   rY   r-   s       r   	cmd_statsr^      s^    !$	48@DGgE!	$**Uq
9: 	s   A   A2c                h   t        | dd      xs d}t        |      }	 |j                  | j                  | j                        }|j                          t        t        j                  |dd             t        dt        |       dt        j                  	       y
# |j                          w xY w)u5   search 서브커맨드: WikiStore FTS5 전문 검색.rQ   N)limitFr   r      검색 결과: rE   rO   r   )rI   r   search_entriesqueryr`   rX   r'   r$   r%   rH   rU   rV   )r5   rQ   rY   resultss       r   
cmd_searchre      s    !$	48@DGgE&&tzz&D	$**W5
;<	OCL>
-CJJ? 	s   'B B1c           	     \   t        d| j                          t        | j                        }|j                  di       j                  dd      }| j                  r| j                  }|j                  dg       }|j                  di       }t        d|j                  dd	       d
|j                  dd	       d       t        d| j
                  rdnd d       t        || j
                  t        | dd      |      }t        || j                         t        dt        |       d       y	)u8   pipeline 서브커맨드: parse + extract 연속 실행.u!   [파이프라인] 파싱 시작: r:   r;   r<   r   r-   u/   [파이프라인] 파싱 완료 — 메시지: r.   r   r/   r0   r1   u)   [파이프라인] 지식 추출 중 (LLM=r>   r?   r@   rA   NrB   u)   [파이프라인] 완료 — wiki_entry: rE   )r'   r2   r   r4   r;   rC   r   rI   r*   r3   rH   r5   r   rD   r   r-   rL   s         r   cmd_pipelinerh      s   	-djj\
:;djj)Fzz(B/33KDK~~nn"(**Z"<HJJw#E	
9%))DTVW:X9Y Z"YY~q9:#	?
 

34<<KUc3ddij  i.	G '4;;'	5c'l^3
GHr+   c                   t        d| j                          t        j                  t	        | j                        j                  d            }t        |j                  dg             }|j                  di       j                  dd      }| j                  r| j                  }t        dt        |       d	| j                  rd
nd d       t        || j                  |t        | dd      | j                  t        | dd      t        | dd            }t        || j                         t        dt        |       d       y)uP   extract-v2 서브커맨드: 파싱된 JSON → v2 지식 추출 → JSON 저장.r9   r!   r"   r   r:   r;   r<   u    지식 추출 중 v2 (메시지 r=   r>   r?   r@   
output_dirNprogress_filemonth)rC   rD   rj   
batch_sizerk   rl   u   추출 완료 — insight_v2: rE   r   )r'   r2   r$   rF   r   rG   r   r4   r;   rH   rC   r   rI   rm   r*   r3   rJ   s        r   cmd_extract_v2rn      s   	L
%&
**T$**%///A
BC$SWWZ%<=Hwwx,00bAK~~nn	
*3x=/ :"ll{?u	F #4t4??dOT:dGR(G '4;;'	*3w<.
<=r+   c                    ddl m} ddlm} ddlm} t        | dd      xs t        }t        | dd      xs t        }t        }t        }t        d| j                          t        | j                        }|j                  d	i       j                  d
d      }	|j                  dg       }
|j                  di       }t        d|j                  dd       d       t        d       t        |
d|	      }t        dt!        |       d       t        d        ||      } ||||      } |||      }|j#                  |      }t        t%        j&                  |dd             t        d|d    d|d    d       y) uA   update 서브커맨드: 새 카톡 파일로 증분 업데이트.r   )IncrementalUpdaterKnowledgeGraphVectorStorerQ   Ninsights_diru   [update] 파싱 중: r:   r;   r<   r   r-   u&   [update] 파싱 완료 — 메시지: r.   r   rE   u4   [update] 인사이트 추출 중 (규칙 기반) ...F)rC   rD   u   [update] 추출 완료 — u7   [update] VectorStore + KnowledgeGraph 초기화 중 ...rQ   ru   
graph_path
index_path)vector_storegraphr   r   u   [update] 완료 — 신규: newu   건, 보강: 	augmented)incremental_updaterrp   knowledge_graphrr   rz   rt   rI   _DEFAULT_DB_PATH_DEFAULT_INSIGHTS_DIR_DEFAULT_GRAPH_PATH_DEFAULT_INDEX_PATHr'   r2   r   r4   r   rH   updater$   r%   )r5   rp   rr   rt   rQ   ru   rx   ry   r   rD   r   stats_parsenew_insightsrY   r{   updaterupdate_statss                    r   
cmd_updater      sy   7/)dIt,@0@G46O:OL$J$J	!$**
./djj)Fzz(B/33KDK"(**Z"<H**Wb)K	2;??CSUV3W2XX[
\]	
@A'%[L 
'L(9':#
>?	
CD(E!E !e5AG>>,/L	$**\a
@A	
&|E':&; <,-S	2 r+   c                2   ddl m} t        | dd      xs t        }t        | dd      } ||      }|j	                  | j
                  |      }t        t        j                  |d	d
             t        dt        |       dt        j                         y)u4   similar 서브커맨드: 유사 인사이트 검색.r   rs   rQ   Ntop_k   rv   )r   Fr   r   ra   rE   rO   r   )rz   rt   rI   r   search_similarrc   r'   r$   r%   rH   rU   rV   )r5   rt   rQ   r   rY   rd   s         r   cmd_similarr     s}    )dIt,@0@GD'1%E(E""4::U";G	$**W5
;<	OCL>
-CJJ?r+   c                   ddl m} t        | dd      xs t        }t        | dd      } ||t        t
              }t        t              }|j                         r*ddl}|j                  |j                  d	            |_        |j                  | j                  |
      }t        t        j                  |dd             t        dt!        |       dt"        j$                         y)u<   graph 서브커맨드: 특정 인사이트의 연결 조회.r   rq   ru   Ndepthrw   r   r!   r"   )	max_depthFr   r   u   연결된 인사이트: rE   rO   )r   rr   rI   r   r   r   r   existsr$   rF   rG   _graphget_related
insight_idr'   r%   rH   rU   rV   )r5   rr   ru   r   r{   graph_json_path_jsonrelateds           r   	cmd_graphr      s    /46O:OLD'1%E!&&E ./O{{?#<#<g#<#NO5AG	$**W5
;<	$S\N#
6SZZHr+   c                   t        d| j                          t        | j                        }|j                  di       j                  dd      }| j                  r| j                  }|j                  dg       }|j                  di       }t        d|j                  dd	       d
|j                  dd	       d       t        d| j
                  rdnd d       t        || j
                  |t        | dd      | j                  t        | dd      t        | dd      t        | dd	            }t        || j                         t        dt        |       d       y	)u>   pipeline-v2 서브커맨드: parse + extract_v2 연속 실행.u$   [파이프라인 v2] 파싱 시작: r:   r;   r<   r   r-   u2   [파이프라인 v2] 파싱 완료 — 메시지: r.   r   r/   r0   r1   u,   [파이프라인 v2] 지식 추출 중 (LLM=r>   r?   r@   rj   Nrk   rl   skip_threads)rC   rD   rj   rm   rk   rl   r   u,   [파이프라인 v2] 완료 — insight_v2: rE   )r'   r2   r   r4   r;   rC   r   rI   rm   r*   r3   rH   rg   s         r   cmd_pipeline_v2r   :  sF   	0
=>djj)Fzz(B/33KDK~~nn"(**Z"<HJJw#E	
<UYYGWYZ=[<\ ]"YY~q9:#	?
 

6dll{Xf6gglm #4t4??dOT:dGR(T>15	G '4;;'	8Wc
JKr+   c                 	   t        j                  dd      } | j                  dd      }|j                  dd	      }|j	                  d
d	       |j	                  dd d       |j	                  dd dd       |j                  dd	      }|j	                  d
d	       |j	                  dd d       |j	                  ddddd       |j	                  dd dd       |j	                  dd dd       |j                  d d!	      }|j	                  d
d	       |j	                  dd d       |j	                  ddddd       |j	                  dd dd       |j	                  dd dd       |j                  d"d#	      }|j	                  d
d	       |j	                  dd d       |j	                  ddddd$       |j	                  dd dd       |j	                  d%t
        d&d'd()       |j	                  d*d d+d,       |j	                  d-d d.d/       |j	                  d0t        d1d23       |j                  d4d5	      }|j	                  d
d	       |j	                  dd d       |j	                  ddddd$       |j	                  dd dd       |j	                  d%t
        d&d'd()       |j	                  d*d d+d,       |j	                  d-d d.d/       |j	                  d0t        d1d23       |j	                  d6t
        d7d8d9)       |j                  d:d;	      }|j	                  d
d	       |j	                  d<d d=d>t         d?       |j	                  d@d dAdBt         d?       |j                  dCdD	      }|j	                  dEdF	       |j	                  dGt
        dHdIdJ)       |j	                  d<d d=d>t         d?       |j                  dKdL	      }	|	j	                  dMdN	       |	j	                  dOt
        dPdQ3       |	j	                  d@d dAdBt         d?       |j                  dRdS	      }
|
j	                  d
dT	       |
j	                  d<d d=dU       |j                  dVdW	      }|j	                  d<d d=dU       |j                  dXdY	      }|j	                  dEdZ	       |j	                  d[t
        d\d]3       |j	                  d<d d=dU       | S )^Nkakao_knowledgeuB   카카오톡 대화에서 보험 실무 지식을 추출합니다.)progdescriptioncommandT)destrequiredparseuC   카카오톡 txt 파일을 파싱하여 JSON으로 저장합니다.)helpr2   u   카카오톡 txt 파일 경로z--outputu(   출력 파일 경로 (기본값: stdout))defaultr   z--chat-namer;   u+   채팅방 이름 (source_chat 값 override))r   r   r   extractu=   파싱된 JSON에서 보험 실무 지식을 추출합니다.u   파싱된 JSON 파일 경로z	--use-llm
store_trueFrC   u   Gemini LLM 분석 활성화)actionr   r   r   u   source_chat 값 overridez	--api-keyrA   uA   Gemini API 키 (환경변수 GLM_API_KEY / GEMINI_API_KEY 대체)pipelineu7   parse + extract 연속 실행 (전체 파이프라인).
extract-v2uV   파싱된 JSON에서 v2 파이프라인으로 보험 실무 지식을 추출합니다.u   Claude CLI LLM 분석 활성화z--batch-size2   rm   u   배치 크기 (기본값: 50))typer   r   r   z--output-dirrj   u(   중간 결과 저장 디렉토리 경로z--progress-filerk   u<   진행 상태 JSON 파일 경로 (배치마다 업데이트)z--monthr<   uf   처리할 월 (YYYY-MM, YYYY-MM-H1, YYYY-MM-H2 형식). H1=상반기(1~15일), H2=하반기(16~말일))r   r   r   pipeline-v2u=   parse + extract-v2 연속 실행 (v2 전체 파이프라인).z--skip-threadsr   r   u8   처음 N개 스레드를 건너뜀 (이어서 정제용)r   u2   새 카톡 파일로 증분 업데이트합니다.z	--db-pathrQ   u#   chromadb 저장 경로 (기본값: )z--insights-dirru   u4   인사이트 마크다운 저장 경로 (기본값: similaru;   유사 인사이트를 의미 기반으로 검색합니다.rc   u   검색 쿼리z--top-kr   r   u    최대 결과 수 (기본값: 5)r{   uA   특정 인사이트의 연결된 인사이트를 조회합니다.r   u"   인사이트 ID (예: insight-001)z--depthr   u   탐색 깊이 (기본값: 1)importu=   JSON 파일의 위키 항목을 DB에 일괄 저장합니다.u   wiki_entries JSON 파일 경로uF   DB 파일 경로 (기본값: /home/jay/projects/insuwiki/data/wiki.db)r-   u>   WikiStore 카테고리별/상태별 통계를 출력합니다.searchu4   WikiStore에서 키워드를 전문 검색합니다.u	   검색어z--limit   u$   최대 결과 건수 (기본값: 20))	argparseArgumentParseradd_subparsers
add_parseradd_argumentintstrr   r   )parser
subparsersparse_parserextract_parserpipeline_parserextract_v2_parserpipeline_v2_parserupdate_parsersimilar_parsergraph_parserimport_parserstats_parsersearch_parsers                r   _build_parserr   b  s   $$XF &&I&EJ ((R ) L g,LM7  
 :	    **L + N .LM7   
 *    '	    P	    !++F , O   /O P  7 ! 
   * !    '	 !    P	 !  #--e .  ""71O"P""7 # 
 "". #  ""'	 #  "", #  ""7	 #  ""K	 #  ""u	 #  $..L /  ##G2R#S##7 $ 
 ##. $  ##'	 $  ##, $  ##7	 $  ##K	 $  ##u	 $  ##G $  ))A * M w-MN23C2DAF	   CDYCZZ[\	    **J + N o>/    23C2DAF	    ((P ) L l1UV+	   CDYCZZ[\	   ))L * M w-NOU	   ((M ) L U	   ))C * M w[93	   U	   Mr+   c                    t               } | j                         }t        t        t        t
        t        t        t        t        t        t        t        d}|j                  |j                        }|| j                          y ||      S )N)r   r   r   r   r   r   r-   r   r   r   r{   r   )r   
parse_argsr7   rM   rn   rh   r   r[   r^   re   r   r   r   r4   r   
print_help)r   r5   handlershandlers       r   mainr     ss    _FD $ &#H ll4<<(G4=r+   __main__)r   dictreturnr   )r   rT   r   zlist[ChatMessage])r   objectr(   z
str | Noner   None)r5   zargparse.Namespacer   r   )r   zargparse.ArgumentParser)r   r   ),
__future__r   r   r$   loggingrU   pathlibr   kakao_parserr   knowledge_extractorr   knowledge_extractor_v2r   modelsr
   
wiki_storer   r   r   r   r   basicConfigINFO	getLogger__name__loggerr   r   r*   r7   rM   r[   r^   re   rh   rn   r   r   r   r   r   r   exitr   r+   r   <module>r      s    "     
  * 2 8  ! A D C L    
,,>
 
		8	$44$	
>:(V4 Ph`	4 zCHHTV r+   