jeongsoo commited on
Commit
8ede064
Β·
1 Parent(s): 867f974
Files changed (1) hide show
  1. utils/deepseek_client.py +86 -38
utils/deepseek_client.py CHANGED
@@ -5,6 +5,7 @@ DeepSeek API ν΄λΌμ΄μ–ΈνŠΈ λͺ¨λ“ˆ
5
  import os
6
  import json
7
  import logging
 
8
  from typing import List, Dict, Any, Optional, Union
9
  from dotenv import load_dotenv
10
  import requests
@@ -82,22 +83,42 @@ class DeepSeekLLM:
82
 
83
  # API μš”μ²­ 보내기
84
  endpoint = f"{self.api_base}/v1/chat/completions"
 
 
 
 
 
 
85
  response = requests.post(
86
  endpoint,
87
  headers=headers,
88
- json=data
 
89
  )
90
 
91
- # 응닡 검증
92
- response.raise_for_status()
93
- return response.json()
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
  except requests.exceptions.RequestException as e:
96
  logger.error(f"DeepSeek API μš”μ²­ μ‹€νŒ¨: {e}")
97
- raise Exception(f"DeepSeek API μš”μ²­ μ‹€νŒ¨: {e}")
98
- except json.JSONDecodeError as e:
99
- logger.error(f"DeepSeek API 응닡 νŒŒμ‹± μ‹€νŒ¨: {e}")
100
- raise Exception(f"DeepSeek API 응닡 νŒŒμ‹± μ‹€νŒ¨: {e}")
 
101
 
102
  def generate(
103
  self,
@@ -135,16 +156,31 @@ class DeepSeekLLM:
135
  **kwargs
136
  )
137
 
138
- # 응닡 검증 및 처리
139
- if not response or 'choices' not in response or not response['choices']:
140
- logger.error("DeepSeek API μ‘λ‹΅μ—μ„œ μƒμ„±λœ ν…μŠ€νŠΈλ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.")
141
- return ""
 
 
 
 
 
 
142
 
143
- return response['choices'][0]['message']['content'].strip()
 
 
 
 
 
 
 
 
144
 
145
  except Exception as e:
146
- logger.error(f"ν…μŠ€νŠΈ 생성 쀑 였λ₯˜ λ°œμƒ: {e}")
147
- return f"였λ₯˜: {str(e)}"
 
148
 
149
  def rag_generate(
150
  self,
@@ -177,39 +213,51 @@ class DeepSeekLLM:
177
  - 검색 λ‚΄μš©μ„ κ·ΈλŒ€λ‘œ λ³΅μ‚¬ν•˜μ§€ 말고, μžμ—°μŠ€λŸ¬μš΄ ν•œκ΅­μ–΄λ‘œ 닡변을 μž‘μ„±ν•˜μ„Έμš”.
178
  - 닡변은 κ°„κ²°ν•˜κ³  μ •ν™•ν•˜κ²Œ μ œκ³΅ν•˜μ„Έμš”."""
179
 
180
- # μ€‘μš”: μ»¨ν…μŠ€νŠΈ 길이 μ œν•œ
181
- max_context = 10
182
- if len(context) > max_context:
183
- logger.warning(f"μ»¨ν…μŠ€νŠΈκ°€ λ„ˆλ¬΄ κΈΈμ–΄ 처음 {max_context}개만 μ‚¬μš©ν•©λ‹ˆλ‹€.")
184
- context = context[:max_context]
185
-
186
- # 각 μ»¨ν…μŠ€νŠΈ μ•‘μ„ΈμŠ€
187
- limited_context = []
188
- for i, doc in enumerate(context):
189
- # 각 λ¬Έμ„œλ₯Ό 1000자둜 μ œν•œ
190
- if len(doc) > 1000:
191
- logger.warning(f"λ¬Έμ„œ {i+1}의 길이가 μ œν•œλ˜μ—ˆμŠ΅λ‹ˆλ‹€ ({len(doc)} -> 1000)")
192
- doc = doc[:1000] + "...(μƒλž΅)"
193
- limited_context.append(doc)
194
-
195
- context_text = "\n\n".join([f"λ¬Έμ„œ {i+1}: {doc}" for i, doc in enumerate(limited_context)])
196
-
197
- prompt = f"""질문: {query}
 
198
 
199
  <context>
200
  {context_text}
201
  </context>
202
 
203
  μœ„ 검색 κ²°κ³Όλ₯Ό μ°Έκ³ ν•˜μ—¬ μ§ˆλ¬Έμ— λ‹΅λ³€ν•΄ μ£Όμ„Έμš”."""
204
-
205
- try:
206
- return self.generate(
 
207
  prompt=prompt,
208
  system_prompt=system_prompt,
209
  temperature=temperature,
210
  max_tokens=max_tokens,
211
  **kwargs
212
  )
 
 
 
 
 
 
 
 
 
213
  except Exception as e:
214
- logger.error(f"RAG ν…μŠ€νŠΈ 생성 쀑 였λ₯˜ λ°œμƒ: {e}")
215
- return f"였λ₯˜: {str(e)}"
 
 
5
  import os
6
  import json
7
  import logging
8
+ import traceback
9
  from typing import List, Dict, Any, Optional, Union
10
  from dotenv import load_dotenv
11
  import requests
 
83
 
84
  # API μš”μ²­ 보내기
85
  endpoint = f"{self.api_base}/v1/chat/completions"
86
+
87
+ # 디버깅: API μš”μ²­ 데이터 λ‘œκΉ… (민감 정보 μ œμ™Έ)
88
+ debug_data = data.copy()
89
+ debug_data["messages"] = f"[{len(data['messages'])}개 λ©”μ‹œμ§€]"
90
+ logger.debug(f"DeepSeek API μš”μ²­ 데이터: {json.dumps(debug_data)}")
91
+
92
  response = requests.post(
93
  endpoint,
94
  headers=headers,
95
+ json=data,
96
+ timeout=30 # 30초 νƒ€μž„μ•„μ›ƒ μ„€μ •
97
  )
98
 
99
+ # 응닡 μƒνƒœ μ½”λ“œ 확인
100
+ if not response.ok:
101
+ logger.error(f"DeepSeek API 였λ₯˜: μƒνƒœ μ½”λ“œ {response.status_code}")
102
+ logger.error(f"응닡 λ‚΄μš©: {response.text}")
103
+ return {"error": f"API 였λ₯˜: μƒνƒœ μ½”λ“œ {response.status_code}", "detail": response.text}
104
+
105
+ # 응닡 νŒŒμ‹±
106
+ try:
107
+ result = response.json()
108
+ logger.debug(f"API 응닡 ꡬ쑰: {list(result.keys())}")
109
+ return result
110
+ except json.JSONDecodeError as e:
111
+ logger.error(f"DeepSeek API JSON νŒŒμ‹± μ‹€νŒ¨: {e}")
112
+ logger.error(f"원본 응닡: {response.text[:500]}...")
113
+ return {"error": "API 응닡을 νŒŒμ‹±ν•  수 μ—†μŠ΅λ‹ˆλ‹€", "detail": str(e)}
114
 
115
  except requests.exceptions.RequestException as e:
116
  logger.error(f"DeepSeek API μš”μ²­ μ‹€νŒ¨: {e}")
117
+ return {"error": f"API μš”μ²­ μ‹€νŒ¨: {str(e)}"}
118
+ except Exception as e:
119
+ logger.error(f"DeepSeek API 호좜 쀑 μ˜ˆμƒμΉ˜ λͺ»ν•œ 였λ₯˜: {e}")
120
+ logger.error(traceback.format_exc())
121
+ return {"error": f"μ˜ˆμƒμΉ˜ λͺ»ν•œ 였λ₯˜: {str(e)}"}
122
 
123
  def generate(
124
  self,
 
156
  **kwargs
157
  )
158
 
159
+ # 였λ₯˜ 응닡 확인
160
+ if "error" in response:
161
+ logger.error(f"ν…μŠ€νŠΈ 생성 쀑 API 였λ₯˜: {response['error']}")
162
+ error_detail = response.get("detail", "")
163
+ return f"API 였λ₯˜: {response['error']} {error_detail}"
164
+
165
+ # 응닡 ν˜•μ‹ 검증
166
+ if 'choices' not in response or not response['choices']:
167
+ logger.error(f"API 응닡에 'choices' ν•„λ“œκ°€ μ—†μŠ΅λ‹ˆλ‹€: {response}")
168
+ return "응닡 ν˜•μ‹ 였λ₯˜: μƒμ„±λœ ν…μŠ€νŠΈλ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."
169
 
170
+ # λ©”μ‹œμ§€ 컨텐츠 확인
171
+ choice = response['choices'][0]
172
+ if 'message' not in choice or 'content' not in choice['message']:
173
+ logger.error(f"API 응닡에 μ˜ˆμƒ ν•„λ“œκ°€ μ—†μŠ΅λ‹ˆλ‹€: {choice}")
174
+ return "응닡 ν˜•μ‹ 였λ₯˜: λ©”μ‹œμ§€ λ‚΄μš©μ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."
175
+
176
+ generated_text = choice['message']['content'].strip()
177
+ logger.info(f"ν…μŠ€νŠΈ 생성 μ™„λ£Œ (길이: {len(generated_text)})")
178
+ return generated_text
179
 
180
  except Exception as e:
181
+ logger.error(f"ν…μŠ€νŠΈ 생성 쀑 μ˜ˆμ™Έ λ°œμƒ: {e}")
182
+ logger.error(traceback.format_exc())
183
+ return f"였λ₯˜ λ°œμƒ: {str(e)}"
184
 
185
  def rag_generate(
186
  self,
 
213
  - 검색 λ‚΄μš©μ„ κ·ΈλŒ€λ‘œ λ³΅μ‚¬ν•˜μ§€ 말고, μžμ—°μŠ€λŸ¬μš΄ ν•œκ΅­μ–΄λ‘œ 닡변을 μž‘μ„±ν•˜μ„Έμš”.
214
  - 닡변은 κ°„κ²°ν•˜κ³  μ •ν™•ν•˜κ²Œ μ œκ³΅ν•˜μ„Έμš”."""
215
 
216
+ try:
217
+ # μ€‘μš”: μ»¨ν…μŠ€νŠΈ 길이 μ œν•œ
218
+ max_context = 10
219
+ if len(context) > max_context:
220
+ logger.warning(f"μ»¨ν…μŠ€νŠΈκ°€ λ„ˆλ¬΄ κΈΈμ–΄ 처음 {max_context}개만 μ‚¬μš©ν•©λ‹ˆλ‹€.")
221
+ context = context[:max_context]
222
+
223
+ # 각 μ»¨ν…μŠ€νŠΈ μ•‘μ„ΈμŠ€
224
+ limited_context = []
225
+ for i, doc in enumerate(context):
226
+ # 각 λ¬Έμ„œλ₯Ό 1000자둜 μ œν•œ
227
+ if len(doc) > 1000:
228
+ logger.warning(f"λ¬Έμ„œ {i+1}의 길이가 μ œν•œλ˜μ—ˆμŠ΅λ‹ˆλ‹€ ({len(doc)} -> 1000)")
229
+ doc = doc[:1000] + "...(μƒλž΅)"
230
+ limited_context.append(doc)
231
+
232
+ context_text = "\n\n".join([f"λ¬Έμ„œ {i+1}: {doc}" for i, doc in enumerate(limited_context)])
233
+
234
+ prompt = f"""질문: {query}
235
 
236
  <context>
237
  {context_text}
238
  </context>
239
 
240
  μœ„ 검색 κ²°κ³Όλ₯Ό μ°Έκ³ ν•˜μ—¬ μ§ˆλ¬Έμ— λ‹΅λ³€ν•΄ μ£Όμ„Έμš”."""
241
+
242
+ logger.info(f"RAG ν”„λ‘¬ν”„νŠΈ 생성 μ™„λ£Œ (길이: {len(prompt)})")
243
+
244
+ result = self.generate(
245
  prompt=prompt,
246
  system_prompt=system_prompt,
247
  temperature=temperature,
248
  max_tokens=max_tokens,
249
  **kwargs
250
  )
251
+
252
+ # κ²°κ³Όκ°€ 였λ₯˜ λ©”μ‹œμ§€μΈμ§€ 확인
253
+ if result.startswith("였λ₯˜") or result.startswith("API 였λ₯˜") or result.startswith("응닡 ν˜•μ‹ 였λ₯˜"):
254
+ logger.error(f"RAG 생성 κ²°κ³Όκ°€ 였λ₯˜λ₯Ό ν¬ν•¨ν•©λ‹ˆλ‹€: {result}")
255
+ # μ’€ 더 μ‚¬μš©μž μΉœν™”μ μΈ 였λ₯˜ λ©”μ‹œμ§€ λ°˜ν™˜
256
+ return "μ£„μ†‘ν•©λ‹ˆλ‹€. ν˜„μž¬ 응닡을 μƒμ„±ν•˜λŠ”λ° λ¬Έμ œκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. μž μ‹œ ν›„ λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”."
257
+
258
+ return result
259
+
260
  except Exception as e:
261
+ logger.error(f"RAG ν…μŠ€νŠΈ 생성 쀑 μ˜ˆμ™Έ λ°œμƒ: {str(e)}")
262
+ logger.error(traceback.format_exc())
263
+ return "μ£„μ†‘ν•©λ‹ˆλ‹€. 응닡 생성 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. μž μ‹œ ν›„ λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”."