06bcdb03ac
- Upgrade LLM to Qwen3-14B-4bit with Thinking mode (MlxChatModel as LangChain BaseChatModel) - Add LangGraph ReAct agent with tool calling loop (search_documents, web_search, get_current_date, remember/recall_user_info) - Add RAG pipeline: BAAI/bge-m3 embeddings + Qdrant vector store + semantic chunking (SemanticSplitter via cosine similarity) - Replace fixed-size RecursiveCharacterTextSplitter with meaning-based SemanticSplitter (numpy only, no extra deps) - Add Gradio Web UI (app.py): chat, document ingestion, document management tabs - Add multi-user support (user_id isolation in DB + per-user agent cache + dropdown selector) - Add conversation history restore from MySQL on agent init (Phase 11) - Add UserProfileRepository for persistent user profile (remember/recall tools) - Add thread-local DB connections to fix pymysql thread-safety with LangGraph ToolNode - Add Phase 14 voice interface: Whisper STT (microphone → text) + macOS TTS (say -v Yuna) - Enforce search_documents-first policy in system prompt and tool descriptions - Update ROADMAP2.md: Phase 14 완료, Phase 13 청킹 부분 완료 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
32 lines
1.2 KiB
Python
32 lines
1.2 KiB
Python
from __future__ import annotations
|
|
from services.db.mysql_service import DatabaseService
|
|
|
|
|
|
class UserProfileRepository:
|
|
"""td_user_profile 테이블을 통한 사용자 장기 메모리 저장소."""
|
|
|
|
def __init__(self, db: DatabaseService):
|
|
self._db = db
|
|
|
|
def remember(self, key: str, value: str, user_id: str = "default") -> None:
|
|
self._db.execute_write(
|
|
"""INSERT INTO td_user_profile (user_id, key_name, value)
|
|
VALUES (%s, %s, %s)
|
|
ON DUPLICATE KEY UPDATE value = VALUES(value), updated_at = NOW()""",
|
|
(user_id, key, value),
|
|
)
|
|
|
|
def recall(self, key: str, user_id: str = "default") -> str | None:
|
|
rows = self._db.execute(
|
|
"SELECT value FROM td_user_profile WHERE user_id = %s AND key_name = %s",
|
|
(user_id, key),
|
|
)
|
|
return rows[0]["value"] if rows else None
|
|
|
|
def get_all(self, user_id: str = "default") -> dict[str, str]:
|
|
rows = self._db.execute(
|
|
"SELECT key_name, value FROM td_user_profile WHERE user_id = %s ORDER BY updated_at",
|
|
(user_id,),
|
|
)
|
|
return {r["key_name"]: r["value"] for r in rows}
|