import ollama import json import re def analyze_voc_with_gemma(voc_content): """ Gemma 3 1B를 이용해 VOC 본문의 문맥을 분석하고 구조화된 데이터를 반환합니다. """ # 모델에게 부여할 페르소나와 규칙 system_prompt = ( "너는 부산교통공사의 열차 운행 민원 분석 전문가야. " "다음 민원 내용을 분석해서 반드시 아래의 JSON 형식으로만 응답해줘.\n" "형식: {\"line\": \"\", \"set_num\": \"\", \"car_num\": \"\", \"direction\": \"\", \"summary\": \"\"}\n" "단, 정보가 없으면 빈 문자열로 둬." ) # Few-shot: 소형 모델일수록 예시를 주는 것이 중요합니다. user_prompt = f""" 민원 예시 1: "사하역에서 노포방향 열차를 탔는데 34편성 3호차 바닥이 더러워요." 응답: {{"line": "1호선", "set_num": "34편성", "car_num": "3호차", "direction": "노포행(하선)", "summary": "34편성 3호차 객실 바닥 오염 제보"}} 민원 내용: "{voc_content}" 응답:""" try: response = ollama.generate( model='gemma3:1b', # 또는 본인이 설정한 gemma3 모델명 system=system_prompt, prompt=user_prompt, options={ "temperature": 0.1, # 낮을수록 일관된 결과가 나옵니다. "num_predict": 150 # 출력 길이를 제한하여 속도를 높입니다. } ) # JSON 결과만 추출 (소형 모델은 가끔 앞뒤에 설명을 붙일 수 있음) result_text = response['response'] json_match = re.search(r'\{.*\}', result_text, re.DOTALL) if json_match: return json.loads(json_match.group(0)) else: return {"error": "JSON 파싱 실패", "raw": result_text} except Exception as e: return {"error": str(e)} # --- 실제 테스트 실행 --- if __name__ == "__main__": # 1. 테스트용 비정형 민원 test_voc = "방금 서면역에서 다대포가는 기차 탔는데 3호차 구석에 누가 음료수를 쏟았네요. 34편성입니다." print(f"--- VOC 분석 시작 (Gemma 3 1B) ---") analysis_result = analyze_voc_with_gemma(test_voc) # 2. 결과 출력 print(json.dumps(analysis_result, indent=4, ensure_ascii=False)) # 3. 기존 HWP 자동화 로직과 연계 예시 if "error" not in analysis_result: print(f"\n[알림] 분석된 방향: {analysis_result.get('direction')}") print(f"[알림] 요약 내용: {analysis_result.get('summary')}")