stardust-coder commited on
Commit
fbb0032
·
1 Parent(s): bd3907e

Add application file

Browse files
Files changed (2) hide show
  1. app.py +112 -0
  2. requirements.txt +6 -0
app.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import re
3
+ import uuid
4
+ from vllm import AsyncLLMEngine, AsyncEngineArgs, SamplingParams
5
+ import gradio as gr
6
+
7
+ # モジュールレベルで一度だけイベントループを作成
8
+ _loop = asyncio.new_event_loop()
9
+ asyncio.set_event_loop(_loop)
10
+
11
+ # 非同期エンジンの初期化
12
+ en_args = AsyncEngineArgs(
13
+ model="EQUES/JPharmatron-7B-chat",
14
+ enforce_eager=True
15
+ )
16
+ model = AsyncLLMEngine.from_engine_args(en_args)
17
+
18
+ # 非同期でトークン生成をストリーミングするジェネレータ
19
+ # 生成を止めたいラベル(全角コロンも含める)
20
+ STOP_STRINGS = [
21
+ "\nUser:", "\nユーザ:", "\nユーザー:",
22
+ "\nAssistant:", "\nアシスタント:",
23
+ "\nHuman:", "\nHuman:"
24
+ ]
25
+ # 念のための後処理(行頭の User/ユーザ/Assistant ラベル以降を削る)
26
+ STOP_RE = re.compile(r"(?:^|\n)(?:User|ユーザ|ユーザー|Assistant|アシスタント)[::].*", re.MULTILINE)
27
+
28
+ async def astream_generate(prompt: str):
29
+ previous_text = ""
30
+ params = SamplingParams(
31
+ temperature=0.0,
32
+ max_tokens=4096,
33
+ stop=STOP_STRINGS, # ★ここがポイント
34
+ )
35
+
36
+ async for out in model.generate(prompt, params, request_id=str(uuid.uuid4())):
37
+ full_text = out.outputs[0].text
38
+
39
+ # 保険:もし stop が漏れても、ラベルが出たところで切る
40
+ m = STOP_RE.search(full_text)
41
+ if m:
42
+ cut = m.start()
43
+ # 直近差分だけ出す
44
+ chunk = full_text[len(previous_text):cut]
45
+ if chunk:
46
+ yield chunk
47
+ break
48
+
49
+ # 通常は差分だけストリーム
50
+ chunk = full_text[len(previous_text):]
51
+ previous_text = full_text
52
+ if chunk:
53
+ yield chunk
54
+
55
+ # Gradio 用の応答関数(同期ジェネレータ)
56
+ def respond(user_input, history):
57
+ history = history or []
58
+ # システムプロンプトと過去履歴を組み立て
59
+ base_prompt = "以下は親切で何でも答えてくれるAIアシスタントとの会話です。\n"
60
+ for u, b in history:
61
+ base_prompt += f"ユーザー: {u}\nアシスタント: {b}\n"
62
+ base_prompt += f"ユーザー: {user_input}\nアシスタント:"
63
+
64
+ # ユーザー発話と空応答を履歴に追加
65
+ history.append((user_input, ""))
66
+
67
+ # 単一のイベントループを使ってストリーミング
68
+ agen = astream_generate(base_prompt)
69
+ try:
70
+ while True:
71
+ chunk = _loop.run_until_complete(agen.__anext__())
72
+ # 最新の履歴にトークンを追加
73
+ history[-1] = (user_input, history[-1][1] + chunk)
74
+ yield history, history
75
+ except StopAsyncIteration:
76
+ return
77
+
78
+ # Gradio UI 定義
79
+ with gr.Blocks() as demo:
80
+ gr.Markdown("# 💊 製薬に関する質問をしてみてください。")
81
+ gr.Markdown("※ ストリーミングデモ用コードです。")
82
+
83
+ chatbot = gr.Chatbot()
84
+ msg = gr.Textbox(label="あなたのメッセージ (Enterで送信)")
85
+ send = gr.Button("チャットを送信")
86
+ clear = gr.Button("チャット履歴をクリア")
87
+ state = gr.State([])
88
+
89
+ # ▼ プリセット(クリックでテキストボックスに反映)
90
+ gr.Markdown("### 🔧 すぐ使えるプリセット")
91
+ preset_list = [
92
+ "グレープフルーツと薬を一緒に飲んじゃだめなんですか?",
93
+ "新薬の臨床試験(Phase I〜III)の概要を、具体例つきで簡単に教えて。",
94
+ "ジェネリック医薬品が承認されるまでの流れを、タイムラインで解説して。"
95
+ ]
96
+ gr.Examples(
97
+ examples=preset_list,
98
+ inputs=msg,
99
+ label="プリセット(クリックで入力欄に反映)"
100
+ )
101
+
102
+ # 既存の送信/クリア動作
103
+ msg.submit(respond, [msg, state], [chatbot, state]).then(lambda: "", None, msg)
104
+ send.click(respond, [msg, state], [chatbot, state]).then(lambda: "", None, msg)
105
+ clear.click(lambda: ([], []), None, [chatbot, state])
106
+
107
+ # エントリポイント
108
+ def main():
109
+ demo.launch()
110
+
111
+ if __name__ == "__main__":
112
+ main()
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ transformers
2
+ accelerate
3
+ matplotlib
4
+ streamlit
5
+ gradio
6
+ vllm