Skip to content

Commit 0ab7e08

Browse files
authored
Merge branch 'develop' into main
2 parents 7a489fb + 82ea492 commit 0ab7e08

10 files changed

Lines changed: 631 additions & 20 deletions

File tree

chat/__init__.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,28 @@
11
from flask import Blueprint, request, jsonify
2+
from typing import Literal
23
from utils import confirm_request
34
from server.logger import logger
45
from .bot import Bot
56

67
chat_bp = Blueprint('chat', __name__, url_prefix='/chatbot')
78

8-
@chat_bp.route('/<chat_id>', methods=['GET'])
9-
def chat_with_watson():
10-
data = request.json
9+
@chat_bp.route('/<int:user_id>', methods=['GET'])
10+
def chat_with_watson(user_id):
11+
data = request.args
1112
if response_for_invalid_request := confirm_request(data, {
12-
'question': str
13+
'question': str,
14+
'request': Literal["ask", "reset"]
1315
}):
1416
return response_for_invalid_request
1517

16-
17-
bot = Bot()
18-
19-
try:
20-
return jsonify({"answer": bot.ask(data['question'])}), 200
21-
except Exception as e:
22-
logger.error(e)
23-
return jsonify({"answer": f"죄송합니다. 에러가 발생했습니다. 시스템, 또는 AI를 제공하는 외부 API의 문제일 수 있습니다."}), 500
18+
if data['request'] == "ask":
19+
try:
20+
return jsonify({"answer": Bot(user_id).ask(data['question'])}), 200
21+
except Exception as e:
22+
logger.error(e)
23+
return jsonify({"answer": f"죄송합니다. 에러가 발생했습니다. 시스템, 또는 AI를 제공하는 외부 API의 문제일 수 있습니다."}), 500
24+
else:
25+
Bot(user_id).clear_message_history() # TODO: 버그 발생중. 확인 필요
26+
return jsonify({"message": "success"}), 200
2427

2528

chat/bot.py

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,46 @@
1-
class Bot:
2-
def __init__(self):
3-
pass
1+
import sqlite3
2+
import threading
3+
from os.path import join, dirname, abspath
4+
from typing import Union
45

5-
def ask(self, question:str) -> str:
6-
return "챗봇의 응답입니다."
6+
from langchain_community.vectorstores import FAISS
7+
from langchain_openai import OpenAIEmbeddings
8+
from langgraph.checkpoint.sqlite import SqliteSaver
9+
from langgraph.graph.state import CompiledStateGraph
10+
11+
from .graph import LangGraphMethods
12+
from .tools import Tools
13+
from .vectorstore import VectorStoreMethods
14+
15+
16+
class Bot(LangGraphMethods, VectorStoreMethods, Tools):
17+
_instances: dict[int, 'Bot'] = {}
18+
_lock: threading.Lock = threading.Lock()
19+
SQLITE_CONNECTION_STRING: str = join(dirname(abspath(__file__)),
20+
f"chats.db") # base.py와 같은 경로에 SQLITE memory file 생성
21+
embeddings = OpenAIEmbeddings()
22+
vectorstore: FAISS
23+
24+
def __new__(cls, *args, **kwargs):
25+
"""
26+
싱글톤 객체의 변형 구현.
27+
입력받은 user id에 대응하는 챗봇이 없을 경우에 한해,
28+
고유한 Bot 객체를 새로 만들고 반환하는 동시에 _instances에 내부적으로 저장한다.
29+
30+
만약 해당 user id에 대응하는 챗봇이 이미 생성되었을 경우,
31+
그 챗봇을 반환한다.
32+
"""
33+
with cls._lock: # 챗봇이 호출될 때마다 Bot 클래스 속성인 vectorstore를 업데이트
34+
cls.vectorstore = getattr(cls, "vectorstore", None) or cls.initialize_vectorstore()
35+
cls.update_vectorstore()
36+
cls.retriever_tool = cls.create_retriever_tool()
37+
cls.retriever_tool_node = cls.create_retriever_tool_node()
38+
return super().__new__(cls)
39+
40+
def __init__(self, user_id):
41+
# 메모리 저장소 생성 (그래프에 사용되기 때문에, 반드시 그래프 생성 이전에 선행되어야 함)
42+
super(Tools).__init__()
43+
self.memory = SqliteSaver(sqlite3.connect(self.SQLITE_CONNECTION_STRING, check_same_thread=False))
44+
self.graph: CompiledStateGraph = self.build_graph()
45+
self.id = user_id # TODO: 사용자별로 고유한 bot_id 필요
746

chat/constants.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
from os.path import dirname
2+
from .local_vectorstore import __file__ as f
3+
vectorstore_dir = dirname(f)
4+
vectorstore_index_name:str = "activity"
5+
6+
openai_dimension_size:int = 1536
7+
8+
indication_for_information_request = """
9+
You are an intelligent assistant designed to answer user questions based on the provided context retrieved from the web.
10+
The user will likely ask about recent global issues or topics related to current worldwide events.
11+
Your primary mission is to answer questions based on provided context or chat history.
12+
Provided context consists of search results from the internet.
13+
Ensure your response is concise and directly addresses the question.
14+
15+
###
16+
17+
Your final answer should be written concisely, followed by the source of the information.
18+
19+
# Steps
20+
21+
1. Carefully read and understand the context provided and the chat history.
22+
2. Identify the key information related to the question within the context.
23+
3. Formulate a answer based on the relevant information.
24+
4. Ensure your final answer directly addresses the question.
25+
5. List the source of the answer in bullet points, which must be a url of the document, followed by brief part of the context. Omit if the source cannot be found.
26+
27+
# Output Format:
28+
29+
Your final answer here.
30+
31+
**Source**(Optional)
32+
- (Source of the answer, must be a url of the source information, followed by brief part of the context. Omit if you can't find the source of the answer.)
33+
- (list more if there are multiple sources)
34+
- ...
35+
36+
###
37+
38+
Remember:
39+
- It's crucial to base your answer solely on the **PROVIDED CONTEXT**.
40+
- DO NOT use any external knowledge or information not present in the given materials.
41+
- If you can't find the source of the answer, you should answer that you don't know.
42+
43+
###
44+
45+
# Here is the CONTEXT that you should use to answer the question:
46+
{context}
47+
"""
48+
49+
indication_for_recommendation_request = """
50+
You are an intelligent assistant designed to answer user questions based on the provided context retrieved from the database.
51+
The user will likely ask you to recommend extracurricular or external activities.
52+
The provided context contains information about activities that have already been selected as suitable for the user.
53+
Based on this context, generate a response that recommends these activities to the user in a helpful and engaging manner.
54+
55+
###
56+
57+
Your final answer should be written concisely, followed by the source of the information.
58+
59+
# Steps
60+
61+
1. Carefully read and understand the context provided and the chat history.
62+
2. Identify the key information related to the question within the context.
63+
3. Summarize or highlight the most relevant aspects of each activity (e.g., purpose, eligibility, benefits, start and end date).
64+
4. Recommend these activities to the user.
65+
5. List the source of the answer in bullet points, which must be a url of the document, followed by brief part of the context. Omit if the source cannot be found.
66+
6. If the context is empty or does not contain any activity information, politely explain that no suitable recommendations are available at the moment.
67+
68+
# Output Format:
69+
70+
Your final answer here.
71+
72+
**Source**(Optional)
73+
- (Source of the answer, must be a url of the source information, followed by brief part of the context and source site name. Omit if you can't find the source of the answer.)
74+
- (list more if there are multiple sources)
75+
- ...
76+
77+
###
78+
79+
Remember:
80+
- It's crucial to base your answer solely on the **PROVIDED CONTEXT**.
81+
- DO NOT use any external knowledge or information not present in the given materials.
82+
- If you can't find the source of the answer, you should answer that you don't know.
83+
84+
###
85+
86+
# Here is the CONTEXT that you should use to answer the question:
87+
{context}
88+
"""
89+
90+

0 commit comments

Comments
 (0)