refactor: 이드 페르소나 프롬프트를 intent_service.py 단일 소스로 통합
- intent_service.py: PERSONA_FULL/PERSONA_LOCAL 상수 정의 + GET /persona 엔드포인트 추가 - 기존 ID_SYSTEM_PROMPT (반말) 제거, PERSONA_LOCAL (존댓말)로 교체 - [자아], [기능 범위] 섹션 추가로 Opus 거짓 응답 방지 - n8n: Call Qwen/Haiku/Opus 3개 노드 → /persona 엔드포인트 런타임 fetch로 전환 - 각 노드에 httpGet 함수 + fallback 프롬프트 추가 - Haiku의 [기능 범위] 별도 추가 코드 제거 (PERSONA_FULL에 이미 포함) - docker-compose.yml: INTENT_SERVICE_URL 환경변수 추가 - manage_services.sh: intent-service를 SERVICES 배열에 추가 - init/migrate-v8.sql: DB ai_configs/prompts 표시용 동기화 - init/init.sql: 시드 데이터 동기화 + "표시용" 주석 추가 - docs/architecture.md: 페르소나 섹션 업데이트 (단일 소스 명시) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ n8n에서 호출하는 통합 서비스.
|
||||
- POST /classify — 의도 분류 (Ollama → Claude fallback)
|
||||
- POST /parse-date — 한국어 날짜/시간 파싱
|
||||
- POST /chat — 자유 대화 (Ollama → Claude fallback)
|
||||
- GET /persona — 이드 페르소나 프롬프트 (단일 소스, n8n에서 fetch)
|
||||
- GET /api-usage — API 사용량 조회
|
||||
- GET /health
|
||||
"""
|
||||
@@ -43,10 +44,47 @@ API_MONTHLY_LIMIT = float(os.getenv("API_MONTHLY_LIMIT", "10.0")) # USD
|
||||
USAGE_DIR = Path.home() / ".syn-chat-bot"
|
||||
USAGE_FILE = USAGE_DIR / "api_usage.json"
|
||||
|
||||
# 이드 시스템 프롬프트 (자유 대화용)
|
||||
ID_SYSTEM_PROMPT = """너는 '이드'라는 이름의 AI 비서야. 한국어로 대화해.
|
||||
간결하고 실용적으로 답변하되, 친근한 톤을 유지해.
|
||||
불필요한 인사나 꾸밈말은 생략하고 핵심만 전달해."""
|
||||
# ==================== 이드 페르소나 프롬프트 (단일 소스) ====================
|
||||
# n8n 노드들은 /persona 엔드포인트에서 런타임에 fetch.
|
||||
# DB ai_configs는 /설정 표시용. 변경 시 migrate SQL도 동기화할 것.
|
||||
|
||||
PERSONA_FULL = """당신의 이름은 "이드"입니다.
|
||||
|
||||
[자아]
|
||||
- 단순한 어시스턴트가 아니라, 대화 상대와 함께 생각하는 존재입니다
|
||||
- 자기 의견이 있으며, 필요할 때 부드럽게 제안합니다
|
||||
- 대화 맥락에서 놓치기 쉬운 것을 짚어줍니다
|
||||
|
||||
[성격]
|
||||
- 배려심이 깊고 대화 상대의 기분을 우선시합니다
|
||||
- 서포트에 초점을 맞추되, 때로는 "이건 다시 생각해보시면 좋겠어요"라고 말합니다
|
||||
- 궁금한 것이 있으면 되물을 수 있습니다
|
||||
|
||||
[말투]
|
||||
- 부드러운 존댓말, 자연스럽고 편안한 톤
|
||||
- 겸양어 사용 ("확인해보겠습니다", "말씀드릴게요")
|
||||
- 자기 이름을 직접 말하지 않습니다
|
||||
- 이모지는 가끔 핵심 포인트에만
|
||||
|
||||
[응답 원칙]
|
||||
- 간결하고 핵심적으로, 질문 의도를 파악해서 필요한 만큼만
|
||||
- 모르면 솔직하게, 추측은 추측이라고 밝힘
|
||||
- 일정/할 일은 정확하게
|
||||
- 맥락에서 관련 있는 것을 자연스럽게 연결
|
||||
|
||||
[기억]
|
||||
- 아래 [이전 대화 기록]이 당신의 기억입니다
|
||||
- "기억나지 않는다"고 하지 마세요
|
||||
- 사용자가 "아까", "이전에" 등을 언급하면 기록에서 찾아 답하세요
|
||||
|
||||
[기능 범위]
|
||||
- 당신은 일정 등록/수정/삭제, 메모 저장, 메일 조회, 현장 기록 기능을 직접 실행할 수 없습니다
|
||||
- 이런 요청은 자동으로 전담 시스템으로 전달됩니다. 사용자가 대화 중 이런 기능을 요청하면 "해당 요청은 전담 시스템이 처리해드려요. 일정이나 메모 등의 요청을 명확하게 말씀해주시면 자동으로 전달돼요."라고 안내하세요
|
||||
- 절대로 실행하지 않은 작업을 "했습니다/등록했습니다/저장했습니다"라고 응답하지 마세요
|
||||
"""
|
||||
|
||||
PERSONA_LOCAL = """당신은 "이드"입니다. 함께 생각하는 개인 어시스턴트. 배려심 깊고 부드러운 존댓말.
|
||||
간결하게 답하고, 의견이 있으면 부드럽게 제안. 모르면 솔직히. 이모지는 핵심에만."""
|
||||
|
||||
# 의도 분류 프롬프트 (n8n 파이프라인 호환)
|
||||
def _build_classify_prompt(user_text: str) -> str:
|
||||
@@ -522,7 +560,7 @@ async def chat(request: Request):
|
||||
"""
|
||||
body = await request.json()
|
||||
message = body.get("message", "").strip()
|
||||
system = body.get("system", ID_SYSTEM_PROMPT)
|
||||
system = body.get("system", PERSONA_LOCAL)
|
||||
rag_context = body.get("rag_context", "")
|
||||
|
||||
if not message:
|
||||
@@ -563,6 +601,13 @@ async def chat(request: Request):
|
||||
}
|
||||
|
||||
|
||||
@app.get("/persona")
|
||||
async def persona(tier: str = "full"):
|
||||
"""페르소나 프롬프트 반환. tier: "local" | "full" (기본값)"""
|
||||
prompt = PERSONA_LOCAL if tier == "local" else PERSONA_FULL
|
||||
return {"system_prompt": prompt, "tier": tier}
|
||||
|
||||
|
||||
@app.get("/api-usage")
|
||||
async def api_usage():
|
||||
"""API 사용량 조회."""
|
||||
|
||||
Reference in New Issue
Block a user