Skip to content

Commit a0e7880

Browse files
committed
Merge branch 'develop'
2 parents a066bff + 946ce26 commit a0e7880

7 files changed

Lines changed: 68 additions & 206 deletions

File tree

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,21 @@ ChatBot-AI/
3636

3737
---
3838

39+
## 📋 UML 클래스 다이어그램
40+
### 📑 ChatBot-AI/fastapi/src/utils/ai_models 클래스 다이어그램
41+
![image](https://lh3.googleusercontent.com/d/11BO1kgmcn_I0N-gAegB8p36-PrAm4IHn)
42+
43+
### 📑 ChatBot-AI/fastapi/src/utils/handlers 클래스 다이어그램
44+
![image](https://lh3.googleusercontent.com/d/10s3xwUFxnmfKb8WBEvU3jqQhJgExNa28)
45+
46+
### 📑 ChatBot-AI/fastapi/src/utils/schemas 클래스 다이어그램
47+
![image](https://lh3.googleusercontent.com/d/1Az97lKerSOJltMPWEMeAW6G72axCdIii)
48+
49+
## 📋 UML 패키지 다이어그램
50+
![image](https://lh3.googleusercontent.com/d/1_fifSzf7YFoEMQd80hUQGgF0rI0vsYtm)
51+
52+
---
53+
3954
## 🚀 빠른 시작 (Docker 기반)
4055

4156
### 1. **필수 요구사항**

fastapi/src/server-character/server.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ async def lifespan(app: FastAPI):
5252
"""
5353
try:
5454
assert AppState.LlamaCharacter_model is not None, "LlamaCharacter_model is not initialized"
55+
if AppState.mongo_handler is not None:
56+
await AppState.mongo_handler.init()
5557
except AssertionError as e:
5658
print(f"{RED}ERROR{RESET}: {str(e)}")
5759
print(f"{GREEN}INFO{RESET}: LlamaCharacter 모델 로드 완료")

fastapi/src/server-character/utils/app_state.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
RESET = "\033[0m"
88

99
LlamaCharacter_model: Optional[LlamaCharacterModel] = None
10+
mongo_handler: Optional[MongoDBHandler] = None
1011

1112
try:
12-
# Character 서버는 GPU 1 사용
13-
LlamaCharacter_model = LlamaCharacterModel() # 컨테이너 내에서는 0이 RTX 3060
14-
mongo_handler: Optional[MongoDBHandler] = MongoDBHandler()
13+
LlamaCharacter_model = LlamaCharacterModel()
14+
mongo_handler = MongoDBHandler() # 비동기 초기화는 lifespan에서!
1515
except ChatError.InternalServerErrorException as e:
1616
mongo_handler = None
1717
print(f"{RED}ERROR{RESET}: MongoDB 초기화 오류 발생: {str(e)}")

fastapi/src/server-character/utils/handlers/mongodb_handler.py

Lines changed: 16 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -66,133 +66,44 @@ def __init__(self) -> None:
6666
"&socketTimeoutMS=6000" # 네 번째 옵션
6767
)
6868

69-
# 이벤트 루프 가져오기
70-
self.loop = asyncio.get_event_loop()
71-
72-
# MongoDB 클라이언트 초기화 (이벤트 루프 지정)
73-
self.client = AsyncIOMotorClient(
74-
self.mongo_uri,
75-
io_loop = self.loop,
76-
serverSelectionTimeoutMS = 500,
77-
connectTimeoutMS = 1000,
78-
socketTimeoutMS = 6000
79-
)
80-
81-
# 연결 테스트는 비동기로 수행
82-
async def test_connection():
83-
await self.client.admin.command('ping')
84-
85-
# 연결 테스트 실행
86-
self.loop.run_until_complete(test_connection())
87-
self.db = self.client[mongo_db]
88-
print(f"{GREEN}INFO{RESET}: MongoDB 연결 성공: {mongo_host}:{mongo_port}")\
89-
90-
except PyMongoError as e:
91-
print(f"{RED}ERROR{RESET}: MongoDB 연결 실패")
92-
raise InternalServerErrorException(detail = f"MongoDB 연결 오류 - 호스트: {mongo_host}, 포트: {mongo_port}")
69+
self.client = None
70+
self.db = None
71+
print(f"{GREEN}INFO{RESET}: MongoDBHandler 초기화 완료")
9372
except Exception as e:
9473
raise InternalServerErrorException(detail = f"MongoDBHandler 초기화 오류: {str(e)}")
95-
96-
async def get_office_log(self, user_id: str, document_id: str, router: str) -> List[Dict]:
97-
try:
98-
collection = self.db[f'{router}_log_{user_id}']
99-
100-
# 이벤트 루프 확인 및 설정
101-
if self.loop != asyncio.get_event_loop():
102-
self.loop = asyncio.get_event_loop()
103-
self.client = AsyncIOMotorClient(
104-
self.mongo_uri,
105-
io_loop = self.loop
106-
)
107-
self.db = self.client[os.getenv("MONGO_DATABASE")]
108-
collection = self.db[f'{router}_log_{user_id}']
109-
110-
document = await collection.find_one({"id": document_id})
111-
112-
if document is None or not document.get("value", []):
113-
return []
114-
115-
value_list = document.get("value", [])
116-
sorted_value_list = sorted(value_list, key = lambda x: x.get("index", 0))
117-
118-
# 최신 8개만 선택
119-
latest_messages = sorted_value_list[-8:] if len(sorted_value_list) > 8 else sorted_value_list
120-
121-
# 대화 기록 형식 수정
122-
formatted_chat_list = []
123-
for chat in latest_messages:
124-
formatted_chat = {
125-
"index": chat.get("index"),
126-
"input_data": chat.get("input_data"), # input_data 직접 사용
127-
"output_data": chat.get("output_data") # output_data 직접 사용
128-
}
129-
formatted_chat_list.append(formatted_chat)
130-
131-
return formatted_chat_list
13274

75+
async def init(self):
76+
try:
77+
self.client = AsyncIOMotorClient(self.mongo_uri)
78+
await self.client.admin.command('ping')
79+
self.db = self.client[os.getenv("MONGO_DATABASE")]
80+
print(f"{GREEN}INFO{RESET}: MongoDB 연결 성공")
13381
except PyMongoError as e:
134-
raise InternalServerErrorException(detail = f"Error retrieving chatlog value: {str(e)}")
82+
print(f"{RED}ERROR{RESET}: MongoDB 연결 실패")
83+
raise InternalServerErrorException(detail = f"MongoDB 연결 오류 - 호스트: {os.getenv('MONGO_HOST')}, 포트: {os.getenv('MONGO_PORT')}")
13584
except Exception as e:
136-
raise InternalServerErrorException(detail = f"Unexpected error: {str(e)}")
137-
85+
raise InternalServerErrorException(detail = f"MongoDBHandler 초기화 오류: {str(e)}")
86+
13887
async def get_character_log(self, user_id: str, document_id: str, router: str) -> List[Dict]:
13988
"""
14089
최신 10개의 대화 기록을 가져와서 Llama 프롬프트 형식으로 변환합니다.
141-
142-
Args:
143-
user_id (str): 사용자 ID
144-
document_id (str): 문서 ID
145-
router (str): 라우터 이름
146-
147-
Returns:
148-
List[Dict]: Llama 프롬프트 형식의 대화 기록 리스트. 대화 기록이 없으면 빈 리스트 반환.
14990
"""
15091
try:
15192
collection = self.db[f'{router}_log_{user_id}']
152-
153-
# 이벤트 루프 확인 및 설정
154-
if self.loop != asyncio.get_event_loop():
155-
self.loop = asyncio.get_event_loop()
156-
self.client = AsyncIOMotorClient(
157-
self.mongo_uri,
158-
io_loop = self.loop
159-
)
160-
self.db = self.client[os.getenv("MONGO_DATABASE")]
161-
collection = self.db[f'{router}_log_{user_id}']
162-
93+
16394
document = await collection.find_one({"id": document_id})
16495

165-
# 문서가 없거나 value 리스트가 비어있는 경우 빈 리스트 반환
16696
if document is None or not document.get("value", []):
16797
return []
16898

16999
value_list = document.get("value", [])
170-
171-
# index 기준으로 정렬
172100
sorted_value_list = sorted(value_list, key = lambda x: x.get("index", 0))
173-
174-
# 최신 10개만 선택 (마지막 10개)
175101
latest_messages = sorted_value_list[-10:] if len(sorted_value_list) > 10 else sorted_value_list
176102

177-
# 대화 기록 변환 수행
178-
formatted_chat_list = []
179-
for chat in latest_messages:
180-
formatted_chat = {
181-
"index": chat.get("index"),
182-
"img_url": chat.get("img_url"),
183-
"dialogue": (
184-
f"<|start_header_id|>user<|end_header_id|>\n"
185-
f"{chat.get('input_data')}<|eot_id|>"
186-
f"<|start_header_id|>assistant<|end_header_id|>\n"
187-
f"{chat.get('output_data')}<|eot_id|>"
188-
)
189-
}
190-
formatted_chat_list.append(formatted_chat)
191-
192-
return formatted_chat_list
103+
# 필요시 포맷 변환
104+
return latest_messages
193105

194106
except PyMongoError as e:
195107
raise InternalServerErrorException(detail = f"Error retrieving chatlog value: {str(e)}")
196108
except Exception as e:
197109
raise InternalServerErrorException(detail = f"Unexpected error: {str(e)}")
198-

fastapi/src/server-office/server.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,12 @@ async def lifespan(app: FastAPI):
5252
"""
5353
try:
5454
assert AppState.LlamaOffice_model is not None, "LlamaOffice_model is not initialized"
55+
if AppState.mongo_handler is not None:
56+
await AppState.mongo_handler.init()
5557
except AssertionError as e:
5658
print(f"{RED}ERROR{RESET}: {str(e)}")
5759
print(f"{GREEN}INFO{RESET}: LlamaOffice 모델 로드 완료")
58-
5960
yield
60-
61-
# 모델 메모리 해제
6261
AppState.LlamaOffice_model = None
6362
print(f"{GREEN}INFO{RESET}: 모델 해제 완료")
6463

fastapi/src/server-office/utils/app_state.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
RESET = "\033[0m"
88

99
LlamaOffice_model: Optional[LlamaOfficeModel] = None
10+
mongo_handler: Optional[MongoDBHandler] = None
1011

1112
try:
12-
# Office 서버는 GPU 0 사용
1313
LlamaOffice_model = LlamaOfficeModel()
14-
mongo_handler: Optional[MongoDBHandler] = MongoDBHandler()
14+
mongo_handler = MongoDBHandler()
1515
except ChatError.InternalServerErrorException as e:
1616
mongo_handler = None
1717
print(f"{RED}ERROR{RESET}: MongoDB 초기화 오류 발생: {str(e)}")

fastapi/src/server-office/utils/handlers/mongodb_handler.py

Lines changed: 28 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -66,27 +66,33 @@ def __init__(self) -> None:
6666
"&socketTimeoutMS=6000" # 네 번째 옵션
6767
)
6868

69-
# 이벤트 루프 가져오기
70-
self.loop = asyncio.get_event_loop()
69+
# 클라이언트와 데이터베이스 초기화
70+
self.client = None
71+
self.db = None
7172

72-
# MongoDB 클라이언트 초기화 (이벤트 루프 지정)
73-
self.client = AsyncIOMotorClient(
74-
self.mongo_uri,
75-
io_loop = self.loop,
76-
serverSelectionTimeoutMS = 500,
77-
connectTimeoutMS = 1000,
78-
socketTimeoutMS = 6000
79-
)
80-
81-
# 연결 테스트는 비동기로 수행
82-
async def test_connection():
83-
await self.client.admin.command('ping')
84-
85-
# 연결 테스트 실행
86-
self.loop.run_until_complete(test_connection())
87-
self.db = self.client[mongo_db]
88-
print(f"{GREEN}INFO{RESET}: MongoDB 연결 성공: {mongo_host}:{mongo_port}")\
73+
print(f"{GREEN}INFO{RESET}: MongoDBHandler 초기화 완료")
8974

75+
except Exception as e:
76+
raise InternalServerErrorException(detail = f"MongoDBHandler 초기화 오류: {str(e)}")
77+
78+
async def init(self):
79+
"""
80+
MongoDB 클라이언트를 초기화하고 데이터베이스에 연결합니다.
81+
82+
Raises:
83+
InternalServerErrorException: MongoDB 연결 중 오류 발생 시
84+
"""
85+
try:
86+
# MongoDB 클라이언트 초기화
87+
self.client = AsyncIOMotorClient(self.mongo_uri)
88+
89+
# 연결 테스트
90+
await self.client.admin.command('ping')
91+
92+
# 데이터베이스 선택
93+
self.db = self.client[os.getenv("MONGO_DATABASE")]
94+
print(f"{GREEN}INFO{RESET}: MongoDB 연결 성공")
95+
9096
except PyMongoError as e:
9197
print(f"{RED}ERROR{RESET}: MongoDB 연결 실패")
9298
raise InternalServerErrorException(detail = f"MongoDB 연결 오류 - 호스트: {mongo_host}, 포트: {mongo_port}")
@@ -96,16 +102,6 @@ async def test_connection():
96102
async def get_office_log(self, user_id: str, document_id: str, router: str) -> List[Dict]:
97103
try:
98104
collection = self.db[f'{router}_log_{user_id}']
99-
100-
# 이벤트 루프 확인 및 설정
101-
if self.loop != asyncio.get_event_loop():
102-
self.loop = asyncio.get_event_loop()
103-
self.client = AsyncIOMotorClient(
104-
self.mongo_uri,
105-
io_loop = self.loop
106-
)
107-
self.db = self.client[os.getenv("MONGO_DATABASE")]
108-
collection = self.db[f'{router}_log_{user_id}']
109105

110106
document = await collection.find_one({"id": document_id})
111107

@@ -114,7 +110,7 @@ async def get_office_log(self, user_id: str, document_id: str, router: str) -> L
114110

115111
value_list = document.get("value", [])
116112
sorted_value_list = sorted(value_list, key = lambda x: x.get("index", 0))
117-
113+
118114
# 최신 8개만 선택
119115
latest_messages = sorted_value_list[-8:] if len(sorted_value_list) > 8 else sorted_value_list
120116

@@ -123,69 +119,8 @@ async def get_office_log(self, user_id: str, document_id: str, router: str) -> L
123119
for chat in latest_messages:
124120
formatted_chat = {
125121
"index": chat.get("index"),
126-
"input_data": chat.get("input_data"), # input_data 직접 사용
127-
"output_data": chat.get("output_data") # output_data 직접 사용
128-
}
129-
formatted_chat_list.append(formatted_chat)
130-
131-
return formatted_chat_list
132-
133-
except PyMongoError as e:
134-
raise InternalServerErrorException(detail = f"Error retrieving chatlog value: {str(e)}")
135-
except Exception as e:
136-
raise InternalServerErrorException(detail = f"Unexpected error: {str(e)}")
137-
138-
async def get_character_log(self, user_id: str, document_id: str, router: str) -> List[Dict]:
139-
"""
140-
최신 10개의 대화 기록을 가져와서 Llama 프롬프트 형식으로 변환합니다.
141-
142-
Args:
143-
user_id (str): 사용자 ID
144-
document_id (str): 문서 ID
145-
router (str): 라우터 이름
146-
147-
Returns:
148-
List[Dict]: Llama 프롬프트 형식의 대화 기록 리스트. 대화 기록이 없으면 빈 리스트 반환.
149-
"""
150-
try:
151-
collection = self.db[f'{router}_log_{user_id}']
152-
153-
# 이벤트 루프 확인 및 설정
154-
if self.loop != asyncio.get_event_loop():
155-
self.loop = asyncio.get_event_loop()
156-
self.client = AsyncIOMotorClient(
157-
self.mongo_uri,
158-
io_loop = self.loop
159-
)
160-
self.db = self.client[os.getenv("MONGO_DATABASE")]
161-
collection = self.db[f'{router}_log_{user_id}']
162-
163-
document = await collection.find_one({"id": document_id})
164-
165-
# 문서가 없거나 value 리스트가 비어있는 경우 빈 리스트 반환
166-
if document is None or not document.get("value", []):
167-
return []
168-
169-
value_list = document.get("value", [])
170-
171-
# index 기준으로 정렬
172-
sorted_value_list = sorted(value_list, key = lambda x: x.get("index", 0))
173-
174-
# 최신 10개만 선택 (마지막 10개)
175-
latest_messages = sorted_value_list[-10:] if len(sorted_value_list) > 10 else sorted_value_list
176-
177-
# 대화 기록 변환 수행
178-
formatted_chat_list = []
179-
for chat in latest_messages:
180-
formatted_chat = {
181-
"index": chat.get("index"),
182-
"img_url": chat.get("img_url"),
183-
"dialogue": (
184-
f"<|start_header_id|>user<|end_header_id|>\n"
185-
f"{chat.get('input_data')}<|eot_id|>"
186-
f"<|start_header_id|>assistant<|end_header_id|>\n"
187-
f"{chat.get('output_data')}<|eot_id|>"
188-
)
122+
"input_data": chat.get("input_data"),
123+
"output_data": chat.get("output_data")
189124
}
190125
formatted_chat_list.append(formatted_chat)
191126

0 commit comments

Comments
 (0)