|
|
|
|
|
|
|
|
""" |
|
|
๋ํ ํ์คํ ๋ฆฌ ๊ด๋ฆฌ์ (๋ฉ๋ชจ๋ฆฌ ๊ธฐ๋ฐ) |
|
|
|
|
|
๊ธฐ๋ฅ: |
|
|
- UI ํ์์ฉ / ๋ถ์์ฉ ํ์คํ ๋ฆฌ ๋ถ๋ฆฌ |
|
|
- ์ ์ฒด ๋ํ ์ ์ฅ (greeting, thanks, document, out_of_scope) |
|
|
- JSON ๋ด๋ณด๋ด๊ธฐ |
|
|
- ํต๊ณ ๊ธฐ๋ฅ |
|
|
""" |
|
|
|
|
|
from datetime import datetime |
|
|
from typing import List, Dict, Optional |
|
|
import json |
|
|
import logging |
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
|
|
|
class ConversationManager: |
|
|
""" |
|
|
๋ํ ํ์คํ ๋ฆฌ ๊ด๋ฆฌ (๋ฉ๋ชจ๋ฆฌ ๊ธฐ๋ฐ) |
|
|
|
|
|
Streamlit session_state์ ํจ๊ป ์ฌ์ฉ: |
|
|
- UI ํ์คํ ๋ฆฌ: Streamlit ๋ฉ์์ง ํ์ |
|
|
- DB ํ์คํ ๋ฆฌ: ๋ถ์/์ ์ฅ์ฉ ํ์ |
|
|
""" |
|
|
|
|
|
def __init__(self): |
|
|
"""์ด๊ธฐํ""" |
|
|
self.ui_history: List[Dict] = [] |
|
|
self.db_history: List[Dict] = [] |
|
|
|
|
|
logger.info("๐ฌ ConversationManager ์ด๊ธฐํ ์๋ฃ") |
|
|
|
|
|
def add_message( |
|
|
self, |
|
|
user_msg: str, |
|
|
ai_msg: str, |
|
|
query_type: str, |
|
|
sources: Optional[List] = None, |
|
|
usage: Optional[Dict] = None, |
|
|
search_mode: Optional[str] = None, |
|
|
used_retrieval: bool = False, |
|
|
routing_info: Optional[Dict] = None |
|
|
): |
|
|
""" |
|
|
๋ฉ์์ง ์ถ๊ฐ (์ ์ฒด ์ ์ฅ) |
|
|
|
|
|
Args: |
|
|
user_msg: ์ฌ์ฉ์ ์ง๋ฌธ |
|
|
ai_msg: AI ๋ต๋ณ |
|
|
query_type: ์ง๋ฌธ ์ ํ (greeting/thanks/document/out_of_scope) |
|
|
sources: ์ฐธ๊ณ ๋ฌธ์ ๋ฆฌ์คํธ |
|
|
usage: ํ ํฐ ์ฌ์ฉ๋ |
|
|
search_mode: ๊ฒ์ ๋ชจ๋ |
|
|
used_retrieval: ๊ฒ์ ์ฌ์ฉ ์ฌ๋ถ |
|
|
routing_info: ๋ผ์ฐํ
์ ๋ณด |
|
|
""" |
|
|
timestamp = datetime.now() |
|
|
|
|
|
|
|
|
|
|
|
self.ui_history.append({ |
|
|
'role': 'user', |
|
|
'content': user_msg, |
|
|
'timestamp': timestamp |
|
|
}) |
|
|
|
|
|
|
|
|
self.ui_history.append({ |
|
|
'role': 'assistant', |
|
|
'content': ai_msg, |
|
|
'sources': sources or [], |
|
|
'usage': usage or {}, |
|
|
'search_mode': search_mode, |
|
|
'used_retrieval': used_retrieval, |
|
|
'routing_info': routing_info, |
|
|
'type': query_type, |
|
|
'timestamp': timestamp |
|
|
}) |
|
|
|
|
|
|
|
|
self.db_history.append({ |
|
|
'user': user_msg, |
|
|
'assistant': ai_msg, |
|
|
'type': query_type, |
|
|
'timestamp': timestamp.isoformat(), |
|
|
'sources_count': len(sources) if sources else 0, |
|
|
'used_retrieval': used_retrieval, |
|
|
'search_mode': search_mode, |
|
|
'routing_info': routing_info |
|
|
}) |
|
|
|
|
|
logger.info(f"๐พ ๋ํ ์ ์ฅ: {query_type} - {user_msg[:30]}...") |
|
|
|
|
|
def get_ui_history(self) -> List[Dict]: |
|
|
""" |
|
|
UI ํ์์ฉ ํ์คํ ๋ฆฌ ๋ฐํ (Streamlit ํ์) |
|
|
|
|
|
Returns: |
|
|
Streamlit ๋ฉ์์ง ๋ฆฌ์คํธ |
|
|
""" |
|
|
return self.ui_history |
|
|
|
|
|
def get_db_history(self, last_n: Optional[int] = None) -> List[Dict]: |
|
|
""" |
|
|
๋ถ์/์ ์ฅ์ฉ ํ์คํ ๋ฆฌ ๋ฐํ |
|
|
|
|
|
Args: |
|
|
last_n: ์ต๊ทผ N๊ฐ๋ง ๋ฐํ (None์ด๋ฉด ์ ์ฒด) |
|
|
|
|
|
Returns: |
|
|
๋ํ ๊ธฐ๋ก ๋ฆฌ์คํธ |
|
|
""" |
|
|
if last_n: |
|
|
return self.db_history[-last_n:] |
|
|
return self.db_history |
|
|
|
|
|
def get_history_by_type(self, query_type: str) -> List[Dict]: |
|
|
""" |
|
|
ํน์ ์ง๋ฌธ ์ ํ๋ง ํํฐ๋ง |
|
|
|
|
|
Args: |
|
|
query_type: 'greeting', 'thanks', 'document', 'out_of_scope' |
|
|
|
|
|
Returns: |
|
|
ํํฐ๋ง๋ ๋ํ ๋ฆฌ์คํธ |
|
|
""" |
|
|
return [ |
|
|
msg for msg in self.db_history |
|
|
if msg['type'] == query_type |
|
|
] |
|
|
|
|
|
def get_statistics(self) -> Dict[str, int]: |
|
|
""" |
|
|
์ง๋ฌธ ์ ํ๋ณ ํต๊ณ |
|
|
|
|
|
Returns: |
|
|
{'greeting': 5, 'document': 20, ...} |
|
|
""" |
|
|
from collections import Counter |
|
|
|
|
|
types = [msg['type'] for msg in self.db_history] |
|
|
stats = dict(Counter(types)) |
|
|
|
|
|
|
|
|
stats['total'] = len(self.db_history) |
|
|
|
|
|
return stats |
|
|
|
|
|
def export_to_json(self) -> str: |
|
|
""" |
|
|
JSON ํ์์ผ๋ก ๋ด๋ณด๋ด๊ธฐ |
|
|
|
|
|
Returns: |
|
|
JSON ๋ฌธ์์ด |
|
|
""" |
|
|
export_data = { |
|
|
'timestamp': datetime.now().isoformat(), |
|
|
'total_conversations': len(self.db_history), |
|
|
'statistics': self.get_statistics(), |
|
|
'conversations': self.db_history |
|
|
} |
|
|
|
|
|
return json.dumps(export_data, ensure_ascii=False, indent=2) |
|
|
|
|
|
def clear(self): |
|
|
"""ํ์คํ ๋ฆฌ ์ด๊ธฐํ""" |
|
|
self.ui_history = [] |
|
|
self.db_history = [] |
|
|
logger.info("๐๏ธ ๋ํ ํ์คํ ๋ฆฌ ์ด๊ธฐํ") |
|
|
|
|
|
def __len__(self): |
|
|
"""๋ํ ๊ฐ์ (์ฌ์ฉ์ ์ง๋ฌธ ๊ธฐ์ค)""" |
|
|
return len(self.db_history) |
|
|
|
|
|
def __repr__(self): |
|
|
stats = self.get_statistics() |
|
|
return ( |
|
|
f"ConversationManager(" |
|
|
f"total={stats.get('total', 0)}, " |
|
|
f"document={stats.get('document', 0)}, " |
|
|
f"greeting={stats.get('greeting', 0)}, " |
|
|
f"thanks={stats.get('thanks', 0)}, " |
|
|
f"out_of_scope={stats.get('out_of_scope', 0)})" |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
manager = ConversationManager() |
|
|
|
|
|
|
|
|
manager.add_message( |
|
|
user_msg="์๋
ํ์ธ์", |
|
|
ai_msg="์๋
ํ์ธ์! ๋ฌด์์ ๋์๋๋ฆด๊น์?", |
|
|
query_type="greeting" |
|
|
) |
|
|
|
|
|
manager.add_message( |
|
|
user_msg="์์ฐ์ด ์ผ๋ง์ธ๊ฐ์?", |
|
|
ai_msg="์์ฐ์ 5์ต์์
๋๋ค.", |
|
|
query_type="document", |
|
|
sources=[{'content': '์์ฐ: 5์ต์', 'score': 0.95}], |
|
|
used_retrieval=True, |
|
|
search_mode="hybrid_rerank" |
|
|
) |
|
|
|
|
|
manager.add_message( |
|
|
user_msg="๊ณ ๋ง์์", |
|
|
ai_msg="์ฒ๋ง์์! ์ธ์ ๋ ์ง๋ฌธํ์ธ์.", |
|
|
query_type="thanks" |
|
|
) |
|
|
|
|
|
|
|
|
print("\n===== ํต๊ณ =====") |
|
|
print(manager.get_statistics()) |
|
|
|
|
|
|
|
|
print("\n===== DB ํ์คํ ๋ฆฌ =====") |
|
|
for msg in manager.get_db_history(): |
|
|
print(f"{msg['type']}: {msg['user'][:20]}...") |
|
|
|
|
|
|
|
|
print("\n===== JSON Export =====") |
|
|
print(manager.export_to_json()) |
|
|
|
|
|
|
|
|
print("\n===== Manager Info =====") |
|
|
print(manager) |