Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -7,11 +7,11 @@ import time
|
|
7 |
from datasets import load_dataset
|
8 |
from sentence_transformers import SentenceTransformer, util
|
9 |
|
10 |
-
#
|
11 |
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
12 |
genai.configure(api_key=GEMINI_API_KEY)
|
13 |
|
14 |
-
#
|
15 |
model = genai.GenerativeModel("gemini-2.0-flash-thinking-exp-1219")
|
16 |
|
17 |
# PharmKG 데이터셋 로드
|
@@ -23,11 +23,11 @@ embedding_model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')
|
|
23 |
|
24 |
def format_chat_history(messages: list) -> list:
|
25 |
"""
|
26 |
-
|
27 |
"""
|
28 |
formatted_history = []
|
29 |
for message in messages:
|
30 |
-
#
|
31 |
if not (message.get("role") == "assistant" and "metadata" in message):
|
32 |
formatted_history.append({
|
33 |
"role": "user" if message.get("role") == "user" else "assistant",
|
@@ -36,6 +36,9 @@ def format_chat_history(messages: list) -> list:
|
|
36 |
return formatted_history
|
37 |
|
38 |
def find_most_similar_data(query):
|
|
|
|
|
|
|
39 |
query_embedding = embedding_model.encode(query, convert_to_tensor=True)
|
40 |
most_similar = None
|
41 |
highest_similarity = -1
|
@@ -55,21 +58,21 @@ def find_most_similar_data(query):
|
|
55 |
|
56 |
def stream_gemini_response(user_message: str, messages: list) -> Iterator[list]:
|
57 |
"""
|
58 |
-
|
59 |
"""
|
60 |
-
if not user_message.strip(): #
|
61 |
-
messages.append(ChatMessage(role="assistant", content="
|
62 |
yield messages
|
63 |
return
|
64 |
|
65 |
try:
|
66 |
-
print(f"\n===
|
67 |
-
print(f"
|
68 |
|
69 |
-
#
|
70 |
chat_history = format_chat_history(messages)
|
71 |
|
72 |
-
#
|
73 |
most_similar_data = find_most_similar_data(user_message)
|
74 |
|
75 |
system_message = "사용자 질문에 대해 의약품 정보를 제공하는 전문 약학 어시스턴트입니다."
|
@@ -104,27 +107,27 @@ def stream_gemini_response(user_message: str, messages: list) -> Iterator[list]:
|
|
104 |
PharmKG는 복잡한 약물 관련 정보를 체계적으로 정리하고 분석할 수 있게 해주어, 약학 연구와 임상 의사결정에 중요한 도구로 활용되고 있습니다.
|
105 |
"""
|
106 |
|
107 |
-
#
|
108 |
if most_similar_data:
|
109 |
prefixed_message = f"{system_prefix} {system_message} 관련 정보: {most_similar_data}\n\n 사용자 질문:{user_message}"
|
110 |
else:
|
111 |
prefixed_message = f"{system_prefix} {system_message}\n\n 사용자 질문:{user_message}"
|
112 |
|
113 |
-
#
|
114 |
chat = model.start_chat(history=chat_history)
|
115 |
response = chat.send_message(prefixed_message, stream=True)
|
116 |
|
117 |
-
#
|
118 |
thought_buffer = ""
|
119 |
response_buffer = ""
|
120 |
thinking_complete = False
|
121 |
|
122 |
-
#
|
123 |
messages.append(
|
124 |
ChatMessage(
|
125 |
role="assistant",
|
126 |
content="",
|
127 |
-
metadata={"title": "⚙️
|
128 |
)
|
129 |
)
|
130 |
|
@@ -133,20 +136,20 @@ def stream_gemini_response(user_message: str, messages: list) -> Iterator[list]:
|
|
133 |
current_chunk = parts[0].text
|
134 |
|
135 |
if len(parts) == 2 and not thinking_complete:
|
136 |
-
#
|
137 |
thought_buffer += current_chunk
|
138 |
-
print(f"\n===
|
139 |
|
140 |
messages[-1] = ChatMessage(
|
141 |
role="assistant",
|
142 |
content=thought_buffer,
|
143 |
-
metadata={"title": "⚙️
|
144 |
)
|
145 |
yield messages
|
146 |
|
147 |
-
#
|
148 |
response_buffer = parts[1].text
|
149 |
-
print(f"\n===
|
150 |
|
151 |
messages.append(
|
152 |
ChatMessage(
|
@@ -157,9 +160,9 @@ def stream_gemini_response(user_message: str, messages: list) -> Iterator[list]:
|
|
157 |
thinking_complete = True
|
158 |
|
159 |
elif thinking_complete:
|
160 |
-
#
|
161 |
response_buffer += current_chunk
|
162 |
-
print(f"\n===
|
163 |
|
164 |
messages[-1] = ChatMessage(
|
165 |
role="assistant",
|
@@ -167,162 +170,37 @@ def stream_gemini_response(user_message: str, messages: list) -> Iterator[list]:
|
|
167 |
)
|
168 |
|
169 |
else:
|
170 |
-
#
|
171 |
thought_buffer += current_chunk
|
172 |
-
print(f"\n===
|
173 |
|
174 |
messages[-1] = ChatMessage(
|
175 |
role="assistant",
|
176 |
content=thought_buffer,
|
177 |
-
metadata={"title": "⚙️
|
178 |
)
|
179 |
-
#time.sleep(0.05) #
|
180 |
|
181 |
yield messages
|
182 |
|
183 |
-
print(f"\n===
|
184 |
|
185 |
except Exception as e:
|
186 |
-
print(f"\n===
|
187 |
messages.append(
|
188 |
ChatMessage(
|
189 |
role="assistant",
|
190 |
-
content=f"
|
191 |
)
|
192 |
)
|
193 |
yield messages
|
194 |
|
195 |
def user_message(msg: str, history: list) -> tuple[str, list]:
|
196 |
-
"""
|
197 |
history.append(ChatMessage(role="user", content=msg))
|
198 |
return "", history
|
199 |
|
200 |
|
201 |
-
# Create the Gradio interface
|
202 |
-
with gr.Blocks(theme=gr.themes.Soft(primary_hue="teal", secondary_hue="slate", neutral_hue="neutral")) as demo: # Using Soft theme with adjusted hues for a refined look
|
203 |
-
gr.Markdown("# 💭 PharmAI: 추론 기반 약리학 전문 AI 서비스 💭")
|
204 |
-
|
205 |
-
|
206 |
-
gr.HTML("""<a href="https://visitorbadge.io/status?path=https%3A%2F%2Faiqcamp-Gemini2-Flash-Thinking.hf.space">
|
207 |
-
<img src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Faiqcamp-Gemini2-Flash-Thinking.hf.space&countColor=%23263759" />
|
208 |
-
</a>""")
|
209 |
-
|
210 |
-
|
211 |
-
with gr.Tabs():
|
212 |
-
with gr.TabItem("Chat"):
|
213 |
-
chatbot = gr.Chatbot(
|
214 |
-
type="messages",
|
215 |
-
label="Gemini2.0 'Thinking' Chatbot (Streaming Output)", #Label now indicates streaming
|
216 |
-
render_markdown=True,
|
217 |
-
scale=1,
|
218 |
-
avatar_images=(None,"https://lh3.googleusercontent.com/oxz0sUBF0iYoN4VvhqWTmux-cxfD1rxuYkuFEfm1SFaseXEsjjE4Je_C_V3UQPuJ87sImQK3HfQ3RXiaRnQetjaZbjJJUkiPL5jFJ1WRl5FKJZYibUA=w214-h214-n-nu"),
|
219 |
-
elem_classes="chatbot-wrapper" # Add a class for custom styling
|
220 |
-
)
|
221 |
-
|
222 |
-
with gr.Row(equal_height=True):
|
223 |
-
input_box = gr.Textbox(
|
224 |
-
lines=1,
|
225 |
-
label="Chat Message",
|
226 |
-
placeholder="Type your message here...",
|
227 |
-
scale=4
|
228 |
-
)
|
229 |
-
|
230 |
-
clear_button = gr.Button("Clear Chat", scale=1)
|
231 |
-
|
232 |
-
# Add example prompts - removed file upload examples. Kept text focused examples.
|
233 |
-
example_prompts = [
|
234 |
-
["Explain the interplay between CYP450 enzymes and drug metabolism, specifically focusing on how enzyme induction or inhibition might affect the therapeutic efficacy of a drug such as warfarin."],
|
235 |
-
["만성 신장 질환 환자에서 빈혈 치료를 위해 사용하는 에리스로포이에틴 제제의 약동학적 및 약력학적 특성을 상세히 분석하고, 투여 용량 및 투여 간격 결정에 영향을 미치는 요인들을 설명해 주십시오."],
|
236 |
-
["간경변 치료(간 섬유화 해소)를 위한 신약 개발을 위한 '천연 식물'들을 추출하고 이에 대한 구체적인 약리기전과 그 이유, 그리고 어떻게 조합해야 최상의 효과가 있을지 추론하여 최적의 답변을 하라."],
|
237 |
-
["만성 신장 질환 환자에서 빈혈 치료를 위해 사용하는 에리스로포이에틴 제제의 약동학적 및 약력학적 특성을 상세히 분석하고, 투여 용량 및 투여 간격 결정에 영향을 미치는 요인들을 설명해 주십시오."],
|
238 |
-
["간경변 환자에서 약물 대사의 변화를 설명하고, 간 기능 저하가 약물 투여량 조절에 미치는 영향을 구체적인 약물 예시와 함께 논의해 주십시오. 특히, 간 대사 효소의 활성 변화와 그 임상적 중요성을 설명해 주십시오."],
|
239 |
-
["알츠하이머병 치료에 효과적인 천연 식물 물질과 약리기전 등을 한방(한의학)적 관점에서 설명하고 알려줘"],
|
240 |
-
["Compare and contrast the mechanisms of action of ACE inhibitors and ARBs in managing hypertension, considering their effects on the renin-angiotensin-aldosterone system."],
|
241 |
-
["Describe the pathophysiology of type 2 diabetes and explain how metformin achieves its glucose-lowering effects, including any key considerations for patients with renal impairment."],
|
242 |
-
["Please discuss the mechanism of action and clinical significance of beta-blockers in the treatment of heart failure, with reference to specific beta-receptor subtypes and their effects on the cardiovascular system."],
|
243 |
-
["알츠하이머병의 병태생리학적 기전을 설명하고, 현재 사용되는 약물들이 작용하는 주요 타겟을 상세히 기술하십시오. 특히, 아세틸콜린에스테라제 억제제와 NMDA 수용체 길항제의 작용 방식과 임상적 의의를 비교 분석해 주십시오."]
|
244 |
-
|
245 |
-
]
|
246 |
-
|
247 |
-
gr.Examples(
|
248 |
-
examples=example_prompts,
|
249 |
-
inputs=input_box,
|
250 |
-
label="Examples: Try these prompts to see Gemini's thinking!",
|
251 |
-
examples_per_page=3 # Adjust as needed
|
252 |
-
)
|
253 |
-
|
254 |
-
|
255 |
-
# Set up event handlers
|
256 |
-
msg_store = gr.State("") # Store for preserving user message
|
257 |
-
|
258 |
-
input_box.submit(
|
259 |
-
lambda msg: (msg, msg, ""), # Store message and clear input
|
260 |
-
inputs=[input_box],
|
261 |
-
outputs=[msg_store, input_box, input_box],
|
262 |
-
queue=False
|
263 |
-
).then(
|
264 |
-
user_message, # Add user message to chat
|
265 |
-
inputs=[msg_store, chatbot],
|
266 |
-
outputs=[input_box, chatbot],
|
267 |
-
queue=False
|
268 |
-
).then(
|
269 |
-
stream_gemini_response, # Generate and stream response
|
270 |
-
inputs=[msg_store, chatbot],
|
271 |
-
outputs=chatbot
|
272 |
-
)
|
273 |
-
|
274 |
-
clear_button.click(
|
275 |
-
lambda: ([], "", ""),
|
276 |
-
outputs=[chatbot, input_box, msg_store],
|
277 |
-
queue=False
|
278 |
-
)
|
279 |
-
|
280 |
-
|
281 |
-
with gr.TabItem("Instructions"):
|
282 |
-
gr.Markdown(
|
283 |
-
"""
|
284 |
-
## PharmAI: Your Expert Pharmacology Assistant
|
285 |
-
|
286 |
-
Welcome to PharmAI, a specialized chatbot powered by Google's Gemini 2.0 Flash model. PharmAI is designed to provide expert-level information on pharmacology topics, leveraging a large dataset of pharmaceutical knowledge ("PharmKG").
|
287 |
-
|
288 |
-
**Key Features:**
|
289 |
-
|
290 |
-
* **Advanced Pharmacology Insights**: PharmAI provides responses that are structured, detailed, and based on a vast knowledge graph of pharmacology.
|
291 |
-
* **Inference and Reasoning**: The chatbot can handle complex, multi-faceted questions, showcasing its ability to reason and infer from available information.
|
292 |
-
* **Structured Responses**: Responses are organized logically to include definitions, mechanisms of action, indications, dosages, side effects, drug interactions, pharmacokinetics, and references when applicable.
|
293 |
-
* **Thinking Process Display**: You can observe the model's thought process as it generates a response (experimental feature).
|
294 |
-
* **Conversation History**: PharmAI remembers the previous parts of the conversation to provide more accurate and relevant information across multiple turns.
|
295 |
-
* **Streaming Output**: The chatbot streams responses for an interactive experience.
|
296 |
-
|
297 |
-
**How to Use PharmAI:**
|
298 |
-
|
299 |
-
1. **Start a Conversation**: Type your pharmacology question into the input box under the "Chat" tab. The chatbot is specifically designed to handle complex pharmacology inquiries.
|
300 |
-
|
301 |
-
2. **Use Example Prompts**: You can try out the example questions provided to see the model in action. These examples are formulated to challenge the chatbot to exhibit its expertise.
|
302 |
-
|
303 |
-
3. **Example Prompt Guidance**:
|
304 |
-
* **Mechanisms of Action**: Ask about how a specific drug works at the molecular level. Example: "Explain the mechanism of action of Metformin."
|
305 |
-
* **Drug Metabolism**: Inquire about how the body processes drugs. Example: "Explain the interplay between CYP450 enzymes and drug metabolism..."
|
306 |
-
* **Clinical Implications**: Pose questions about the clinical use of drugs in treating specific diseases. Example: "Discuss the mechanism of action and clinical significance of beta-blockers in heart failure..."
|
307 |
-
* **Pathophysiology and Drug Targets**: Ask about diseases, what causes them, and how drugs can treat them. Example: "Explain the pathophysiology of type 2 diabetes and how metformin works..."
|
308 |
-
* **Complex Multi-Drug Interactions**: Pose questions about how one drug can affect another drug in the body.
|
309 |
-
* **Traditional Medicine Perspectives**: Ask about traditional medicine (like Hanbang) approaches to disease and treatment. Example: "Explain effective natural plant substances and their mechanisms for treating Alzheimer's from a Hanbang perspective."
|
310 |
-
|
311 |
-
4. **Review Responses**: The chatbot will then present its response with a "Thinking" section that reveals its internal processing. Then it provides the more structured response, with sections including definition, mechanism of action, indications, etc.
|
312 |
-
|
313 |
-
5. **Clear Conversation**: Use the "Clear Chat" button to start a new session.
|
314 |
-
|
315 |
-
**Important Notes:**
|
316 |
-
|
317 |
-
* The 'thinking' feature is experimental, but it shows the steps the model took when creating the response.
|
318 |
-
* The quality of the response is highly dependent on the user prompt. Please be as descriptive as possible when asking questions to the best results.
|
319 |
-
* This model is focused specifically on pharmacology information, so questions outside this scope may not get relevant answers.
|
320 |
-
* This chatbot is intended as an informational resource and should not be used for medical diagnosis or treatment recommendations. Always consult with a healthcare professional for any medical advice.
|
321 |
-
|
322 |
-
"""
|
323 |
-
)
|
324 |
-
|
325 |
-
|
326 |
# 메인 Blocks 인터페이스 생성
|
327 |
with gr.Blocks(
|
328 |
theme=gr.themes.Soft(primary_hue="teal", secondary_hue="slate", neutral_hue="neutral"),
|
@@ -333,43 +211,43 @@ with gr.Blocks(
|
|
333 |
}
|
334 |
"""
|
335 |
) as demo:
|
336 |
-
gr.Markdown("#
|
337 |
-
|
338 |
gr.HTML("""<a href="https://visitorbadge.io/status?path=https%3A%2F%2Faiqcamp-Gemini2-Flash-Thinking.hf.space">
|
339 |
<img src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Faiqcamp-Gemini2-Flash-Thinking.hf.space&countColor=%23263759" />
|
340 |
</a>""")
|
341 |
|
342 |
-
with gr.Tabs():
|
343 |
-
with gr.TabItem("
|
344 |
chatbot = gr.Chatbot(
|
345 |
type="messages",
|
346 |
-
label="Gemini2.0 '
|
347 |
render_markdown=True,
|
348 |
scale=1,
|
349 |
avatar_images=(None,"https://lh3.googleusercontent.com/oxz0sUBF0iYoN4VvhqWTmux-cxfD1rxuYkuFEfm1SFaseXEsjjE4Je_C_V3UQPuJ87sImQK3HfQ3RXiaRnQetjaZbjJJUkiPL5jFJ1WRl5FKJZYibUA=w214-h214-n-nu"),
|
350 |
-
elem_classes="chatbot-wrapper" #
|
351 |
)
|
352 |
|
353 |
with gr.Row(equal_height=True):
|
354 |
input_box = gr.Textbox(
|
355 |
lines=1,
|
356 |
-
label="
|
357 |
-
placeholder="
|
358 |
scale=4
|
359 |
)
|
360 |
|
361 |
-
clear_button = gr.Button("
|
362 |
|
363 |
-
#
|
364 |
example_prompts = [
|
365 |
-
["
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
["알츠하이머병의 병태생리학적 기전을 설명하고, 현재 사용되는 약물들이 작용하는 주요 타겟을 상세히 기술하십시오. 특히, 아세틸콜린에스테라제 억제제와 NMDA 수용체 길항제의 작용 방식과 임상적 의의를 비교 분석해 주십시오."]
|
374 |
|
375 |
]
|
@@ -377,26 +255,26 @@ with gr.Blocks(
|
|
377 |
gr.Examples(
|
378 |
examples=example_prompts,
|
379 |
inputs=input_box,
|
380 |
-
label="
|
381 |
-
examples_per_page=3 #
|
382 |
)
|
383 |
|
384 |
|
385 |
-
#
|
386 |
-
msg_store = gr.State("") #
|
387 |
|
388 |
input_box.submit(
|
389 |
-
lambda msg: (msg, msg, ""), #
|
390 |
inputs=[input_box],
|
391 |
outputs=[msg_store, input_box, input_box],
|
392 |
queue=False
|
393 |
).then(
|
394 |
-
user_message, #
|
395 |
inputs=[msg_store, chatbot],
|
396 |
outputs=[input_box, chatbot],
|
397 |
queue=False
|
398 |
).then(
|
399 |
-
stream_gemini_response, #
|
400 |
inputs=[msg_store, chatbot],
|
401 |
outputs=chatbot
|
402 |
)
|
@@ -407,65 +285,52 @@ with gr.Blocks(
|
|
407 |
queue=False
|
408 |
)
|
409 |
|
410 |
-
with gr.TabItem("
|
411 |
gr.Markdown(
|
412 |
"""
|
413 |
-
## PharmAI:
|
414 |
|
415 |
-
|
416 |
|
417 |
-
|
418 |
|
419 |
-
*
|
420 |
-
*
|
421 |
-
*
|
422 |
-
*
|
423 |
-
*
|
424 |
-
*
|
425 |
|
426 |
-
**
|
427 |
|
428 |
-
1.
|
429 |
|
430 |
-
2.
|
431 |
|
432 |
-
3.
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
|
|
439 |
|
440 |
-
4.
|
441 |
|
442 |
-
5.
|
443 |
|
444 |
-
|
445 |
|
446 |
-
*
|
447 |
-
*
|
448 |
-
*
|
449 |
-
*
|
450 |
|
451 |
"""
|
452 |
)
|
453 |
|
454 |
|
455 |
-
# Add CSS styling
|
456 |
-
demo.load(js="""
|
457 |
-
() => {
|
458 |
-
const style = document.createElement('style');
|
459 |
-
style.textContent = `
|
460 |
-
.chatbot-wrapper .message {
|
461 |
-
white-space: pre-wrap; /* 채팅 메시지 내의 줄바꿈 유지 */
|
462 |
-
word-wrap: break-word; /* 긴 단어가 영역을 벗어날 경우 자동 줄바꿈 */
|
463 |
-
}
|
464 |
-
`;
|
465 |
-
document.head.appendChild(style);
|
466 |
-
}
|
467 |
-
""")
|
468 |
-
|
469 |
|
470 |
# Launch the interface
|
471 |
if __name__ == "__main__":
|
|
|
7 |
from datasets import load_dataset
|
8 |
from sentence_transformers import SentenceTransformer, util
|
9 |
|
10 |
+
# Gemini API 키를 환경 변수에서 가져오기
|
11 |
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
12 |
genai.configure(api_key=GEMINI_API_KEY)
|
13 |
|
14 |
+
# Gemini 2.0 Flash 모델 (Thinking 기능 포함) 사용
|
15 |
model = genai.GenerativeModel("gemini-2.0-flash-thinking-exp-1219")
|
16 |
|
17 |
# PharmKG 데이터셋 로드
|
|
|
23 |
|
24 |
def format_chat_history(messages: list) -> list:
|
25 |
"""
|
26 |
+
대화 기록을 Gemini가 이해할 수 있는 구조로 변환
|
27 |
"""
|
28 |
formatted_history = []
|
29 |
for message in messages:
|
30 |
+
# 생각 메시지(메타데이터가 있는 메시지)는 건너뜁니다.
|
31 |
if not (message.get("role") == "assistant" and "metadata" in message):
|
32 |
formatted_history.append({
|
33 |
"role": "user" if message.get("role") == "user" else "assistant",
|
|
|
36 |
return formatted_history
|
37 |
|
38 |
def find_most_similar_data(query):
|
39 |
+
"""
|
40 |
+
주어진 쿼리와 가장 유사한 데이터 찾기
|
41 |
+
"""
|
42 |
query_embedding = embedding_model.encode(query, convert_to_tensor=True)
|
43 |
most_similar = None
|
44 |
highest_similarity = -1
|
|
|
58 |
|
59 |
def stream_gemini_response(user_message: str, messages: list) -> Iterator[list]:
|
60 |
"""
|
61 |
+
대화 기록 지원을 통해 생각과 응답을 스트리밍합니다(텍스트 입력만 해당).
|
62 |
"""
|
63 |
+
if not user_message.strip(): # 텍스트 메시지가 비어 있거나 공백인지 확인
|
64 |
+
messages.append(ChatMessage(role="assistant", content="비어 있지 않은 텍스트 메시지를 제공해주세요. 빈 입력은 허용되지 않습니다.")) # 더 구체적인 메시지
|
65 |
yield messages
|
66 |
return
|
67 |
|
68 |
try:
|
69 |
+
print(f"\n=== 새로운 요청 (텍스트) ===")
|
70 |
+
print(f"사용자 메시지: {user_message}")
|
71 |
|
72 |
+
# Gemini용 대화 기록 포맷
|
73 |
chat_history = format_chat_history(messages)
|
74 |
|
75 |
+
# 유사 데이터 검색
|
76 |
most_similar_data = find_most_similar_data(user_message)
|
77 |
|
78 |
system_message = "사용자 질문에 대해 의약품 정보를 제공하는 전문 약학 어시스턴트입니다."
|
|
|
107 |
PharmKG는 복잡한 약물 관련 정보를 체계적으로 정리하고 분석할 수 있게 해주어, 약학 연구와 임상 의사결정에 중요한 도구로 활용되고 있습니다.
|
108 |
"""
|
109 |
|
110 |
+
# 시스템 프롬프트 및 관련 컨텍스트를 사용자 메시지 앞에 추가
|
111 |
if most_similar_data:
|
112 |
prefixed_message = f"{system_prefix} {system_message} 관련 정보: {most_similar_data}\n\n 사용자 질문:{user_message}"
|
113 |
else:
|
114 |
prefixed_message = f"{system_prefix} {system_message}\n\n 사용자 질문:{user_message}"
|
115 |
|
116 |
+
# Gemini 채팅 시작
|
117 |
chat = model.start_chat(history=chat_history)
|
118 |
response = chat.send_message(prefixed_message, stream=True)
|
119 |
|
120 |
+
# 버퍼 및 플래그 초기화
|
121 |
thought_buffer = ""
|
122 |
response_buffer = ""
|
123 |
thinking_complete = False
|
124 |
|
125 |
+
# 초기 생각 메시지 추가
|
126 |
messages.append(
|
127 |
ChatMessage(
|
128 |
role="assistant",
|
129 |
content="",
|
130 |
+
metadata={"title": "⚙️ 생각 중: *모델에 의해 생성된 생각은 실험적입니다."}
|
131 |
)
|
132 |
)
|
133 |
|
|
|
136 |
current_chunk = parts[0].text
|
137 |
|
138 |
if len(parts) == 2 and not thinking_complete:
|
139 |
+
# 생각 완료 및 응답 시작
|
140 |
thought_buffer += current_chunk
|
141 |
+
print(f"\n=== 생각 완료 ===\n{thought_buffer}")
|
142 |
|
143 |
messages[-1] = ChatMessage(
|
144 |
role="assistant",
|
145 |
content=thought_buffer,
|
146 |
+
metadata={"title": "⚙️ 생각 중: *모델에 의해 생성된 생각은 실험적입니다."}
|
147 |
)
|
148 |
yield messages
|
149 |
|
150 |
+
# 응답 시작
|
151 |
response_buffer = parts[1].text
|
152 |
+
print(f"\n=== 응답 시작 ===\n{response_buffer}")
|
153 |
|
154 |
messages.append(
|
155 |
ChatMessage(
|
|
|
160 |
thinking_complete = True
|
161 |
|
162 |
elif thinking_complete:
|
163 |
+
# 스트리밍 응답
|
164 |
response_buffer += current_chunk
|
165 |
+
print(f"\n=== 응답 청크 ===\n{current_chunk}")
|
166 |
|
167 |
messages[-1] = ChatMessage(
|
168 |
role="assistant",
|
|
|
170 |
)
|
171 |
|
172 |
else:
|
173 |
+
# 스트리밍 생각
|
174 |
thought_buffer += current_chunk
|
175 |
+
print(f"\n=== 생각 청크 ===\n{current_chunk}")
|
176 |
|
177 |
messages[-1] = ChatMessage(
|
178 |
role="assistant",
|
179 |
content=thought_buffer,
|
180 |
+
metadata={"title": "⚙️ 생각 중: *모델에 의해 생성된 생각은 실험적입니다."}
|
181 |
)
|
182 |
+
#time.sleep(0.05) # 디버깅/시각화를 위해 약간의 지연을 추가하려면 주석 해제합니다. 최종 버전에서는 제거합니다.
|
183 |
|
184 |
yield messages
|
185 |
|
186 |
+
print(f"\n=== 최종 응답 ===\n{response_buffer}")
|
187 |
|
188 |
except Exception as e:
|
189 |
+
print(f"\n=== 오류 ===\n{str(e)}")
|
190 |
messages.append(
|
191 |
ChatMessage(
|
192 |
role="assistant",
|
193 |
+
content=f"죄송합니다. 오류가 발생했습니다: {str(e)}"
|
194 |
)
|
195 |
)
|
196 |
yield messages
|
197 |
|
198 |
def user_message(msg: str, history: list) -> tuple[str, list]:
|
199 |
+
"""사용자 메시지를 대화 기록에 추가"""
|
200 |
history.append(ChatMessage(role="user", content=msg))
|
201 |
return "", history
|
202 |
|
203 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
# 메인 Blocks 인터페이스 생성
|
205 |
with gr.Blocks(
|
206 |
theme=gr.themes.Soft(primary_hue="teal", secondary_hue="slate", neutral_hue="neutral"),
|
|
|
211 |
}
|
212 |
"""
|
213 |
) as demo:
|
214 |
+
gr.Markdown("# 💭 PharmAI: 추론 기반 약리학 전문 AI 서비스 💭")
|
215 |
+
|
216 |
gr.HTML("""<a href="https://visitorbadge.io/status?path=https%3A%2F%2Faiqcamp-Gemini2-Flash-Thinking.hf.space">
|
217 |
<img src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Faiqcamp-Gemini2-Flash-Thinking.hf.space&countColor=%23263759" />
|
218 |
</a>""")
|
219 |
|
220 |
+
with gr.Tabs() as tabs:
|
221 |
+
with gr.TabItem("대화", id="chat_tab"):
|
222 |
chatbot = gr.Chatbot(
|
223 |
type="messages",
|
224 |
+
label="Gemini2.0 '생각' 챗봇 (스트리밍 출력)", # 스트리밍임을 나타내는 레이블
|
225 |
render_markdown=True,
|
226 |
scale=1,
|
227 |
avatar_images=(None,"https://lh3.googleusercontent.com/oxz0sUBF0iYoN4VvhqWTmux-cxfD1rxuYkuFEfm1SFaseXEsjjE4Je_C_V3UQPuJ87sImQK3HfQ3RXiaRnQetjaZbjJJUkiPL5jFJ1WRl5FKJZYibUA=w214-h214-n-nu"),
|
228 |
+
elem_classes="chatbot-wrapper" # 사용자 정의 스타일용 클래스 추가
|
229 |
)
|
230 |
|
231 |
with gr.Row(equal_height=True):
|
232 |
input_box = gr.Textbox(
|
233 |
lines=1,
|
234 |
+
label="대화 메시지",
|
235 |
+
placeholder="여기에 메시지를 입력하세요...",
|
236 |
scale=4
|
237 |
)
|
238 |
|
239 |
+
clear_button = gr.Button("대화 초기화", scale=1)
|
240 |
|
241 |
+
# 예제 프롬프트 추가 - 파일 업로드 예제 제거. 텍스트 중심 예제 유지.
|
242 |
example_prompts = [
|
243 |
+
["CYP450 효소와 약물 대사 간의 상호 작용을 설명하고, 특히 효소 유도 또는 억제가 와파린과 같은 약물의 치료 효능에 어떻게 영향을 미칠 수 있는지에 중점을 두십시오."],
|
244 |
+
["만성 신장 질환 환자에서 빈혈 치료를 위해 사용하는 에리스로포이에틴 제제의 약동학적 및 약력학적 특성을 상세히 분석하고, 투여 용량 및 투여 간격 결정에 영향을 미치는 요인들을 설명해 주십시오."],
|
245 |
+
["간경변 치료(간 섬유화 해소)를 위한 신약 개발을 위한 '천연 식물'들을 추출하고 이에 대한 구체적인 약리기전과 그 이유, 그리고 어떻게 조합해야 최상의 효과가 있을지 추론하여 한방(한의학)적 관점에서 최적의 답변을 하라"],
|
246 |
+
["알츠하이머병 치료에 효과적인 천연 식물 물질과 약리기전 등을 한방(한의학)적 관점에서 설명하고 알려줘"],
|
247 |
+
["고혈압 치료 및 증상 완화에 효과적인 신약 개발을 위해 가능성이 매우 높은 천연 식물 물질과 약리기전 등을 한방(한의학)적 관점에서 설명하고 알려줘"],
|
248 |
+
["고혈압 관리에서 ACE 억제제와 ARB의 작용 메커니즘을 비교하고 대조하여 레닌-안지오텐신-알도스테론 시스템에 미치는 영향을 고려하십시오."],
|
249 |
+
["제2형 당뇨병의 병태 생리학을 설명하고 메트포르민이 어떻게 혈당 강하 효과를 달성하는지, 신장 장애 환자에 대한 주요 고려 사항을 포함하여 설명하십시오."],
|
250 |
+
["심부전 치료에서 베타 차단제의 작용 메커니즘과 임상적 중요성에 대해 논의하고, 특정 베타 수용체 아형과 심혈관계에 미치는 영향에 대해 참조하십시오."],
|
251 |
["알츠하이머병의 병태생리학적 기전을 설명하고, 현재 사용되는 약물들이 작용하는 주요 타겟을 상세히 기술하십시오. 특히, 아세틸콜린에스테라제 억제제와 NMDA 수용체 길항제의 작용 방식과 임상적 의의를 비교 분석해 주십시오."]
|
252 |
|
253 |
]
|
|
|
255 |
gr.Examples(
|
256 |
examples=example_prompts,
|
257 |
inputs=input_box,
|
258 |
+
label="예제: Gemini의 생각을 보려면 다음 프롬프트를 사용해 보세요!",
|
259 |
+
examples_per_page=3 # 필요에 따라 조정
|
260 |
)
|
261 |
|
262 |
|
263 |
+
# 이벤트 핸들러 설정
|
264 |
+
msg_store = gr.State("") # 사용자 메시지를 보존하기 위한 저장소
|
265 |
|
266 |
input_box.submit(
|
267 |
+
lambda msg: (msg, msg, ""), # 메시지를 저장하고 입력을 지웁니다.
|
268 |
inputs=[input_box],
|
269 |
outputs=[msg_store, input_box, input_box],
|
270 |
queue=False
|
271 |
).then(
|
272 |
+
user_message, # 사용자 메시지를 대화에 추가합니다.
|
273 |
inputs=[msg_store, chatbot],
|
274 |
outputs=[input_box, chatbot],
|
275 |
queue=False
|
276 |
).then(
|
277 |
+
stream_gemini_response, # 응답을 생성하고 스트리밍합니다.
|
278 |
inputs=[msg_store, chatbot],
|
279 |
outputs=chatbot
|
280 |
)
|
|
|
285 |
queue=False
|
286 |
)
|
287 |
|
288 |
+
with gr.TabItem("사용 방법", id="instructions_tab"):
|
289 |
gr.Markdown(
|
290 |
"""
|
291 |
+
## PharmAI: 당신의 전문 약리학 어시스턴트
|
292 |
|
293 |
+
PharmAI에 오신 것을 환영합니다. Google의 Gemini 2.0 Flash 모델로 구동되는 전문 챗봇입니다. PharmAI는 광범위한 약학 지식 데이터 세트("PharmKG")를 활용하여 약리학 주제에 대한 전문가 수준의 정보를 제공하도록 설계되었습니다.
|
294 |
|
295 |
+
**주요 기능:**
|
296 |
|
297 |
+
* **고급 약리학 통찰력**: PharmAI는 광범위한 약리학 지식 그래프를 기반으로 구조화되고 상세한 답변을 제공합니다.
|
298 |
+
* **추론 및 추론**: 챗봇은 복잡하고 다면적인 질문을 처리하여 사용 가능한 정보로부터 추론하고 추론하는 능력을 보여줍니다.
|
299 |
+
* **구조화된 응답**: 응답은 정의, 작용 메커니즘, 적응증, 투여량, 부작용, 약물 상호 작용, 약동학 및 해당되는 경우 참조 문헌을 포함하도록 논리적으로 구성됩니다.
|
300 |
+
* **사고 과정 표시**: 모델이 응답을 생성할 때 모델의 사고 과정을 관찰할 수 있습니다(실험적 기능).
|
301 |
+
* **대화 기록**: PharmAI는 이전 대화 부분을 기억하여 여러 번에 걸쳐 더 정확하고 관련성 있는 정보를 제공합니다.
|
302 |
+
* **스트리밍 출력**: 챗봇은 대화형 경험을 위해 응답을 스트리밍합니다.
|
303 |
|
304 |
+
**PharmAI 사용 방법:**
|
305 |
|
306 |
+
1. **대화 시작**: "대화" 탭 아래의 입력 상자에 약리학 질문을 입력합니다. 챗봇은 특히 복잡한 약리학 질문을 처리하도록 설계되었습니다.
|
307 |
|
308 |
+
2. **예제 프롬프트 사용**: 제공된 예제 질문을 사용하여 모델 작동 방식을 확인할 수 있습니다. 이러한 예제는 챗봇이 전문 지식을 보여주도록 하기 위해 고안되었습니다.
|
309 |
|
310 |
+
3. **예제 프롬프트 지침**:
|
311 |
+
* **작용 메커니즘**: 특정 약물이 분자 수준에서 어떻게 작용하는지 물어보세요. 예: "메트포르민의 작용 메커니즘을 설명하십시오."
|
312 |
+
* **약물 대사**: 신체가 약물을 어떻게 처리하는지 문의하십시오. 예: "CYP450 효소와 약물 대사 간의 상호 작용을 설명하십시오..."
|
313 |
+
* **임상적 의미**: 특정 질병을 치료하는 데 있어 약물의 임상적 사용에 대한 질문을 제기하십시오. 예: "심부전 치료에서 베타 차단제의 작용 메커니즘과 임상적 중요성에 대해 논의하십시오..."
|
314 |
+
* **병태생리학 및 약물 표적**: 질병, 원인 및 약물이 질병을 치료할 수 있는 방법에 대해 문의하십시오. 예: "제2형 당뇨병의 병태 생리학을 설명하고 메트포르민이 어떻게 작용하는지 설명하십시오..."
|
315 |
+
* **복합 다중 약물 상호 작용**: 신체에서 하나의 약물이 다른 약물에 어떻게 영향을 미칠 수 있는지에 대한 질문을 제기하십시오.
|
316 |
+
* **전통 의학 관점**: 질병 및 치료에 대한 전통 의학(한방과 같은) 접근 방식에 대해 문의하십시오. 예: "한방적 관점에서 알츠하이머병 치료에 효과적인 천연 식물 물질과 그 메커니즘을 설명하십시오."
|
317 |
+
|
318 |
|
319 |
+
4. **응답 검토**: 챗봇은 내부 처리 과정을 보여주는 "생각 중" 섹션과 함께 응답을 제시합니다. 그런 다음 정의, 작용 메커니즘, 적응증 등을 포함한 섹션과 함께 보다 구조화된 응답을 제공합니다.
|
320 |
|
321 |
+
5. **대화 초기화**: "대화 초기화" 버튼을 사용하여 새 세션을 시작합니다.
|
322 |
|
323 |
+
**주의 사항:**
|
324 |
|
325 |
+
* '생각 중' 기능은 실험적이지만 응답을 생성할 때 모델이 수행한 단계를 보여줍니다.
|
326 |
+
* 응답의 품질은 사용자 프롬프트에 따라 크게 달라집니다. 최상의 결과를 얻으려면 질문할 때 가능한 한 자세하게 설명하십시오.
|
327 |
+
* 이 모델은 특히 약리학 정보에 초점을 맞추고 있으므로 이 범위를 벗어난 질문에는 관련성 있는 답변을 얻지 못할 수 있습니다.
|
328 |
+
* 이 챗봇은 정보 제공용 리소스로 제공되며 의료 진단 또는 치료 권장 사항에 사용해서는 안 됩니다. 의료 상담이 필요한 경우 항상 의료 전문가와 상담하십시오.
|
329 |
|
330 |
"""
|
331 |
)
|
332 |
|
333 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
334 |
|
335 |
# Launch the interface
|
336 |
if __name__ == "__main__":
|