refactor: PAAI Clawdbot 호출 방식 개선

- HTTP API → WebSocket Gateway 방식으로 변경
- clawdbot_client.py의 ask_clawdbot() 함수 활용
- 시스템 프롬프트 분리
This commit is contained in:
thug0bin 2026-03-05 09:30:22 +09:00
parent 4275689c29
commit 59a55d6b22

View File

@ -1111,52 +1111,48 @@ def build_paai_prompt(
def call_clawdbot_ai(prompt: str) -> dict:
"""Clawdbot AI 호출 (HTTP API)"""
import requests as http_requests
"""Clawdbot AI 호출 (WebSocket Gateway)"""
import json
import re
from services.clawdbot_client import ask_clawdbot
PAAI_SYSTEM_PROMPT = """당신은 경험 많은 약사입니다.
처방 데이터를 분석하여 약사에게 유용한 정보를 제공합니다.
반드시 요청된 JSON 형식으로만 응답하세요."""
try:
# Clawdbot Gateway API 호출
response = http_requests.post(
'http://localhost:8765/api/chat',
json={
'message': prompt,
'session': 'paai-analysis',
'timeout': 60
},
timeout=65
# Clawdbot Gateway WebSocket API 호출
ai_text = ask_clawdbot(
message=prompt,
session_id='paai-analysis',
system_prompt=PAAI_SYSTEM_PROMPT,
timeout=60,
model='anthropic/claude-sonnet-4-5' # 빠른 Sonnet 사용
)
if response.status_code == 200:
result = response.json()
# AI 응답에서 JSON 파싱 시도
ai_text = result.get('response', '')
if not ai_text:
logging.warning("[PAAI] Clawdbot 응답 없음")
return generate_fallback_response(prompt)
# JSON 블록 추출
try:
import re
json_match = re.search(r'\{[\s\S]*\}', ai_text)
if json_match:
return json.loads(json_match.group())
except:
pass
except Exception as parse_err:
logging.warning(f"[PAAI] JSON 파싱 실패: {parse_err}")
# JSON 파싱 실패 시 텍스트 그대로 반환
return {
'prescription_insight': ai_text[:200] if ai_text else '분석 결과 없음',
'prescription_insight': ai_text[:500] if ai_text else '분석 결과 없음',
'kims_analysis': '',
'cautions': [],
'otc_recommendations': [],
'counseling_points': []
}
else:
raise Exception(f"Clawdbot API 오류: {response.status_code}")
except http_requests.exceptions.ConnectionError:
# Clawdbot 연결 안됨 - 기본 응답 생성
return generate_fallback_response(prompt)
except Exception as e:
logging.error(f"Clawdbot AI 호출 오류: {e}")
logging.error(f"[PAAI] Clawdbot AI 호출 오류: {e}")
return generate_fallback_response(prompt)
@ -1193,3 +1189,132 @@ def paai_feedback():
except Exception as e:
logging.error(f"PAAI 피드백 저장 오류: {e}")
return jsonify({'success': False, 'error': str(e)}), 500
# ────────────────────────────────────────────────────────────────────────────────
# PAAI 어드민 페이지
# ────────────────────────────────────────────────────────────────────────────────
@pmr_bp.route('/admin')
def paai_admin_page():
"""PAAI 어드민 대시보드 페이지"""
return render_template('pmr_admin.html')
@pmr_bp.route('/api/admin/stats')
def paai_admin_stats():
"""PAAI 통계 API"""
from db.paai_logger import get_stats
try:
stats = get_stats()
return jsonify({'success': True, 'stats': stats})
except Exception as e:
logging.error(f"PAAI 통계 조회 오류: {e}")
return jsonify({'success': False, 'error': str(e)}), 500
@pmr_bp.route('/api/admin/logs')
def paai_admin_logs():
"""PAAI 로그 목록 API"""
from db.paai_logger import get_recent_logs
try:
limit = request.args.get('limit', 50, type=int)
status = request.args.get('status')
has_severe = request.args.get('has_severe')
date = request.args.get('date')
patient_name = request.args.get('patient_name')
# has_severe 파싱
if has_severe == 'true':
has_severe = True
elif has_severe == 'false':
has_severe = False
else:
has_severe = None
logs = get_recent_logs(
limit=limit,
status=status,
has_severe=has_severe,
date=date
)
# 환자명 필터링 (클라이언트 사이드에서 하기엔 데이터가 많을 수 있음)
if patient_name:
logs = [log for log in logs if patient_name.lower() in (log.get('patient_name') or '').lower()]
return jsonify({'success': True, 'logs': logs, 'count': len(logs)})
except Exception as e:
logging.error(f"PAAI 로그 조회 오류: {e}")
return jsonify({'success': False, 'error': str(e)}), 500
@pmr_bp.route('/api/admin/log/<int:log_id>')
def paai_admin_log_detail(log_id):
"""PAAI 로그 상세 API"""
from db.paai_logger import get_log_detail
try:
log = get_log_detail(log_id)
if not log:
return jsonify({'success': False, 'error': '로그를 찾을 수 없습니다'}), 404
return jsonify({'success': True, 'log': log})
except Exception as e:
logging.error(f"PAAI 로그 상세 조회 오류: {e}")
return jsonify({'success': False, 'error': str(e)}), 500
@pmr_bp.route('/api/admin/feedback-stats')
def paai_admin_feedback_stats():
"""피드백 통계 API (일별)"""
from db.paai_logger import DB_PATH
import sqlite3
from datetime import datetime, timedelta
try:
if not DB_PATH.exists():
return jsonify({'success': True, 'stats': []})
conn = sqlite3.connect(str(DB_PATH))
cursor = conn.cursor()
# 최근 30일 일별 통계
cursor.execute("""
SELECT
DATE(created_at) as date,
COUNT(*) as total,
SUM(CASE WHEN feedback_useful = 1 THEN 1 ELSE 0 END) as useful,
SUM(CASE WHEN feedback_useful = 0 THEN 1 ELSE 0 END) as not_useful,
SUM(CASE WHEN feedback_useful IS NULL THEN 1 ELSE 0 END) as no_feedback,
SUM(CASE WHEN kims_has_severe = 1 THEN 1 ELSE 0 END) as severe,
AVG(ai_response_time_ms) as avg_ai_time
FROM paai_logs
WHERE created_at >= date('now', '-30 days')
GROUP BY DATE(created_at)
ORDER BY date DESC
""")
rows = cursor.fetchall()
stats = []
for row in rows:
stats.append({
'date': row[0],
'total': row[1],
'useful': row[2] or 0,
'not_useful': row[3] or 0,
'no_feedback': row[4] or 0,
'severe': row[5] or 0,
'avg_ai_time': int(row[6]) if row[6] else 0
})
conn.close()
return jsonify({'success': True, 'stats': stats})
except Exception as e:
logging.error(f"피드백 통계 조회 오류: {e}")
return jsonify({'success': False, 'error': str(e)}), 500