nekoniii3 commited on
Commit
5daca38
1 Parent(s): 97118fa
Files changed (2) hide show
  1. app.py +53 -44
  2. bak/app.py +506 -0
app.py CHANGED
@@ -22,12 +22,8 @@ ANT_FOLDER = "sample_data"
22
  IMG_MSG = "(画像ファイルを追加しました。送信ボタンの下に表示されています。)"
23
  ANT_MSG = "(下部の[出力ファイル]にファイルを追加しました。)"
24
 
25
- # 環境変数情報
26
- # os.environ["OPENAI_API_KEY"] = ""
27
- os.environ["ASSIST_ID"] = "asst_KHpzJRBEgONhDf6cIpxr1Avt"
28
-
29
  # 各種設定値
30
- MAX_TRIAL = 15 # メッセージ取得最大試行数
31
  INTER_SEC = 3 # 試行間隔(秒)
32
 
33
  # サンプル用情報
@@ -37,7 +33,6 @@ example_toid = {"東京都年別人口.csv" : "file-GOEk4X4WpU5gBJAuHCMtiJrn"
37
 
38
  # file_id = "file-0Ly64DA2jzE9mOFYayOKJJK0"
39
  # file_id = "file-aVnVcpEVpsy77xQ8SlTp1WoX" # ライ麦
40
-
41
  # file_id = "file-HFCaJbf3k7j0fhBqh1Rwf2VV" # 練馬区
42
 
43
  # コード出力用
@@ -84,11 +79,19 @@ def init(state, text, file):
84
 
85
  return state, text, gr.Image(value=None,type="filepath", interactive=False), file_id, err_msg
86
 
87
- if state["thread_id"] is None:
 
 
 
 
 
88
 
89
- # 初めてなら初期処理をする
90
  client = OpenAI()
91
 
 
 
 
 
92
  # assistant = client.beta.assistants.create(
93
  # name="codeinter_test",
94
  # instructions=state["system_prompt"],
@@ -99,11 +102,13 @@ def init(state, text, file):
99
 
100
  # print(assistant.id)
101
 
 
102
  thread = client.beta.threads.create()
103
 
 
104
  state["client"] = client
105
  # state["assistant_id"] = assistant.id
106
- state["assistant_id"] = os.environ["ASSIST_ID"]
107
  state["thread_id"] = thread.id
108
 
109
  if file:
@@ -147,7 +152,7 @@ def raise_exception(err_msg):
147
  """ エラーの場合例外を起こす関数 """
148
 
149
  if err_msg != "":
150
- raise Exception()
151
 
152
  return
153
 
@@ -236,11 +241,10 @@ def bot(state, history, file_id):
236
  content=history[-1][0],
237
  file_ids=[file_id]
238
  )
239
-
240
- print("run実行前")
241
  print(message)
242
 
243
- # スレッド実行
244
  run = client.beta.threads.runs.create(
245
  thread_id=thread_id,
246
  assistant_id=assistant_id,
@@ -266,8 +270,16 @@ def bot(state, history, file_id):
266
  order="asc"
267
  )
268
 
269
- print(msg_id)
270
- print(messages.data)
 
 
 
 
 
 
 
 
271
 
272
  # messageを取り出す
273
  for msg in messages:
@@ -318,12 +330,12 @@ def bot(state, history, file_id):
318
 
319
  if ct_ant[0].get("file_path") is not None:
320
 
 
321
  ant_file_id = ct_ant[0].get("file_path").get("file_id")
322
 
323
-
324
  if ct_ant[0].get("text") is not None:
325
 
326
- # 拡張子取得
327
  ext = "." + ct_ant[0].get("text")[ct_ant[0].get("text").rfind('.') + 1:]
328
 
329
  # ファイルダウンロード
@@ -364,25 +376,26 @@ def bot(state, history, file_id):
364
  break
365
  else:
366
 
367
- # コードモードがONでコードがあれば取得
368
  run_steps = client.beta.threads.runs.steps.list(
369
  thread_id=thread_id, run_id=run.id
370
  )
371
 
 
372
  input_code = get_code(run_steps)
373
 
374
- if input_code != "":
375
 
376
- input_code = "[input_code]\n\n" + input_code
377
 
378
- print(input_code)
379
 
380
- # コードを追加
381
- history = history + [[None, input_code]]
382
 
383
- yield history, image_file, ant_file, err_msg
384
 
385
- break
386
 
387
  if run.status == "failed":
388
 
@@ -396,21 +409,22 @@ def bot(state, history, file_id):
396
  err_msg = "※メッセージ取得の際にタイムアウトしました。"
397
  return history, image_file, ant_file, err_msg
398
 
 
399
  def get_code(run_steps):
400
 
401
- input_code = ""
402
- print("run_steps")
403
- print(run_steps)
404
 
405
  for data in run_steps.data:
406
 
407
  if isinstance(data.step_details, ToolCallsStepDetails):
408
 
409
- # print(data.step_details)
410
- input_code = data.step_details.tool_calls[0].code_interpreter.input
 
411
 
412
  return input_code
413
 
 
414
  def file_download(client, file_id, folder, ext):
415
  """ OpenAIからファイルをダウンロードしてパスを返す """
416
  api_response = client.files.with_raw_response.retrieve_content(file_id)
@@ -431,10 +445,8 @@ def file_download(client, file_id, folder, ext):
431
 
432
 
433
  def finally_proc():
 
434
 
435
- # os.environ["OPENAI_API_KEY"] = ""
436
-
437
- # new_text = gr.Textbox(value="", interactive=True)
438
  new_up_file = gr.File(value=None, interactive = True)
439
  new_file_id = gr.Textbox(value="")
440
 
@@ -443,36 +455,35 @@ def finally_proc():
443
 
444
  with gr.Blocks() as demo:
445
 
446
- gr.Markdown("<h2> </h2>")
447
 
448
  # セッションの宣言
449
  state = gr.State({
450
  "system_prompt": SYS_PROMPT_DEFAULT,
451
  "openai_key" : None,
452
- "code_mode" : True, # テスト中
453
  "client" : None,
454
  "assistant_id" : None,
455
  "thread_id" : None,
456
  "last_msg_id" : ""
457
  })
458
 
459
- with gr.Tab("GPT-4V 画像入力対応チャット") as chat:
460
 
461
  # 各コンポーネント定義
462
  chatbot = gr.Chatbot(label="チャット画面")
463
  text_msg = gr.Textbox(label="テキスト")
464
- # image=gr.Image(type="filepath")
465
  up_file = gr.File(label="ファイルアップロード", type="filepath",interactive = True)
466
  gr.Examples(label="サンプルデータ", examples=examples, inputs=[up_file])
467
  with gr.Row():
468
  btn = gr.Button(value="送信")
469
  # btn_download = gr.Button(value="画像のダウンロード") # 保留中
470
  btn_clear = gr.ClearButton(value="リセット", components=[chatbot, text_msg, up_file, state])
471
- sys_msg = gr.Textbox(label="システムメッセージ")
472
  result_image = gr.Image(label="出力画像", type="filepath", interactive = False)
473
  result_file = gr.File(label="出力ファイル", type="filepath",interactive = False)
474
 
475
- # GPT用
476
  file_id = gr.Textbox(visible=False)
477
 
478
  # 送信ボタンクリック時の処理
@@ -483,10 +494,8 @@ with gr.Blocks() as demo:
483
  finally_proc, None, [up_file, file_id], queue=False
484
  )
485
 
486
- # クリア時でもOpenAIKeyとプロンプトは残す
487
- btn_clear.click(lambda:chat.select(set_state, [openai_key, system_prompt, state], state), None, None)
488
-
489
- # up_file.upload(lambda:up_file.value, None, sys_msg)
490
 
491
  # テキスト入力Enter時の処理
492
  # txt_msg = text_msg.submit(respond, inputs=[text_msg, image, chatbot], outputs=[text_msg, image, chatbot])
@@ -503,4 +512,4 @@ with gr.Blocks() as demo:
503
 
504
  demo.queue()
505
 
506
- demo.launch(debug=True)
 
22
  IMG_MSG = "(画像ファイルを追加しました。送信ボタンの下に表示されています。)"
23
  ANT_MSG = "(下部の[出力ファイル]にファイルを追加しました。)"
24
 
 
 
 
 
25
  # 各種設定値
26
+ MAX_TRIAL = 30 # メッセージ取得最大試行数
27
  INTER_SEC = 3 # 試行間隔(秒)
28
 
29
  # サンプル用情報
 
33
 
34
  # file_id = "file-0Ly64DA2jzE9mOFYayOKJJK0"
35
  # file_id = "file-aVnVcpEVpsy77xQ8SlTp1WoX" # ライ麦
 
36
  # file_id = "file-HFCaJbf3k7j0fhBqh1Rwf2VV" # 練馬区
37
 
38
  # コード出力用
 
79
 
80
  return state, text, gr.Image(value=None,type="filepath", interactive=False), file_id, err_msg
81
 
82
+ if state["client"] is None:
83
+
84
+ # 初回起動時は初期処理をする
85
+ os.environ["OPENAI_API_KEY"] = os.environ["TEST_OPENAI_KEY"] # テスト時
86
+
87
+ # os.environ["OPENAI_API_KEY"] = state["openai_key"]
88
 
 
89
  client = OpenAI()
90
 
91
+ # client作成後は消す
92
+ os.environ["OPENAI_API_KEY"] = ""
93
+
94
+ # アシスタント作成
95
  # assistant = client.beta.assistants.create(
96
  # name="codeinter_test",
97
  # instructions=state["system_prompt"],
 
102
 
103
  # print(assistant.id)
104
 
105
+ # スレッド作成
106
  thread = client.beta.threads.create()
107
 
108
+ # セッションにセット
109
  state["client"] = client
110
  # state["assistant_id"] = assistant.id
111
+ state["assistant_id"] = os.environ["ASSIST_ID"] # テスト中アシスタントは固定
112
  state["thread_id"] = thread.id
113
 
114
  if file:
 
152
  """ エラーの場合例外を起こす関数 """
153
 
154
  if err_msg != "":
155
+ raise Exception("これは入力チェックでの例外です。")
156
 
157
  return
158
 
 
241
  content=history[-1][0],
242
  file_ids=[file_id]
243
  )
244
+
 
245
  print(message)
246
 
247
+ # RUNスタート
248
  run = client.beta.threads.runs.create(
249
  thread_id=thread_id,
250
  assistant_id=assistant_id,
 
270
  order="asc"
271
  )
272
 
273
+ # print(msg_id)
274
+ # print(messages.data)
275
+
276
+ msg_log = client.beta.threads.messages.list(
277
+ thread_id=thread_id,
278
+ # after=msg_id,
279
+ order="asc"
280
+ )
281
+
282
+ print(msg_log)
283
 
284
  # messageを取り出す
285
  for msg in messages:
 
330
 
331
  if ct_ant[0].get("file_path") is not None:
332
 
333
+ # 参照ファイルのID取得
334
  ant_file_id = ct_ant[0].get("file_path").get("file_id")
335
 
 
336
  if ct_ant[0].get("text") is not None:
337
 
338
+ # ファイル形式(拡張子)取得
339
  ext = "." + ct_ant[0].get("text")[ct_ant[0].get("text").rfind('.') + 1:]
340
 
341
  # ファイルダウンロード
 
376
  break
377
  else:
378
 
379
+ # コードモードがONの場合
380
  run_steps = client.beta.threads.runs.steps.list(
381
  thread_id=thread_id, run_id=run.id
382
  )
383
 
384
+ # コードを取得
385
  input_code = get_code(run_steps)
386
 
387
+ if len(input_code) > 0:
388
 
389
+ for code in input_code:
390
 
391
+ code = "[input_code]\n\n" + code
392
 
393
+ # コードを追加
394
+ history = history + [[None, code]]
395
 
396
+ yield history, image_file, ant_file, err_msg
397
 
398
+ break
399
 
400
  if run.status == "failed":
401
 
 
409
  err_msg = "※メッセージ取得の際にタイムアウトしました。"
410
  return history, image_file, ant_file, err_msg
411
 
412
+
413
  def get_code(run_steps):
414
 
415
+ input_code = []
 
 
416
 
417
  for data in run_steps.data:
418
 
419
  if isinstance(data.step_details, ToolCallsStepDetails):
420
 
421
+ for tool_call in data.step_details.tool_calls:
422
+
423
+ input_code.append(tool_call.code_interpreter.input)
424
 
425
  return input_code
426
 
427
+
428
  def file_download(client, file_id, folder, ext):
429
  """ OpenAIからファイルをダウンロードしてパスを返す """
430
  api_response = client.files.with_raw_response.retrieve_content(file_id)
 
445
 
446
 
447
  def finally_proc():
448
+ """ 最終処理用関数 """
449
 
 
 
 
450
  new_up_file = gr.File(value=None, interactive = True)
451
  new_file_id = gr.Textbox(value="")
452
 
 
455
 
456
  with gr.Blocks() as demo:
457
 
458
+ gr.Markdown("<h2>GPT Code Interpreter対応チャット</h2>")
459
 
460
  # セッションの宣言
461
  state = gr.State({
462
  "system_prompt": SYS_PROMPT_DEFAULT,
463
  "openai_key" : None,
464
+ "code_mode" : True,
465
  "client" : None,
466
  "assistant_id" : None,
467
  "thread_id" : None,
468
  "last_msg_id" : ""
469
  })
470
 
471
+ with gr.Tab("Chat画面") as chat:
472
 
473
  # 各コンポーネント定義
474
  chatbot = gr.Chatbot(label="チャット画面")
475
  text_msg = gr.Textbox(label="テキスト")
 
476
  up_file = gr.File(label="ファイルアップロード", type="filepath",interactive = True)
477
  gr.Examples(label="サンプルデータ", examples=examples, inputs=[up_file])
478
  with gr.Row():
479
  btn = gr.Button(value="送信")
480
  # btn_download = gr.Button(value="画像のダウンロード") # 保留中
481
  btn_clear = gr.ClearButton(value="リセット", components=[chatbot, text_msg, up_file, state])
482
+ sys_msg = gr.Textbox(label="システムメッセージ", interactive = False)
483
  result_image = gr.Image(label="出力画像", type="filepath", interactive = False)
484
  result_file = gr.File(label="出力ファイル", type="filepath",interactive = False)
485
 
486
+ # ファイルID保存用
487
  file_id = gr.Textbox(visible=False)
488
 
489
  # 送信ボタンクリック時の処理
 
494
  finally_proc, None, [up_file, file_id], queue=False
495
  )
496
 
497
+ # クリア時でもOpenAIKeyなどは再セット
498
+ # btn_clear.click(set_state, [openai_key, system_prompt, code_output, state], state)
 
 
499
 
500
  # テキスト入力Enter時の処理
501
  # txt_msg = text_msg.submit(respond, inputs=[text_msg, image, chatbot], outputs=[text_msg, image, chatbot])
 
512
 
513
  demo.queue()
514
 
515
+ demo.launch(debug=True)
bak/app.py ADDED
@@ -0,0 +1,506 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import time
3
+ import os
4
+ import datetime
5
+ # from zoneinfo import ZoneInfo
6
+ from openai import OpenAI
7
+
8
+ from openai.types.beta.threads.runs import (
9
+ ToolCallsStepDetails,
10
+ )
11
+
12
+ # GPT用設定
13
+ SYS_PROMPT_DEFAULT = "あなたは優秀なアシスタントです。質問をされた場合は、質問に答えるコードを作成して実行します。回答は日本語でお願いします。"
14
+ DUMMY = "********************"
15
+ file_format = {".txt", ".csv", ".pdf"}
16
+
17
+ # 各種出力フォルダ
18
+ IMG_FOLDER = "sample_data"
19
+ ANT_FOLDER = "sample_data"
20
+
21
+ # 各種メッセージ
22
+ IMG_MSG = "(画像ファイルを追加しました。送信ボタンの下に表示されています。)"
23
+ ANT_MSG = "(下部の[出力ファイル]にファイルを追加しました。)"
24
+
25
+ # 環境変数情報
26
+ # os.environ["OPENAI_API_KEY"] = ""
27
+ os.environ["ASSIST_ID"] = "asst_KHpzJRBEgONhDf6cIpxr1Avt"
28
+
29
+ # 各種設定値
30
+ MAX_TRIAL = 15 # メッセージ取得最大試行数
31
+ INTER_SEC = 3 # 試行間隔(秒)
32
+
33
+ # サンプル用情報
34
+ examples = ["sample_data/東京都年別人口.csv", "sample_data/練馬区年齢別人口.csv"]
35
+ example_toid = {"東京都年別人口.csv" : "file-GOEk4X4WpU5gBJAuHCMtiJrn"
36
+ , "練馬区年齢別人口.csv" : "file-YAFPMMqG3Zl5DRx5hTLjCfFa"}
37
+
38
+ # file_id = "file-0Ly64DA2jzE9mOFYayOKJJK0"
39
+ # file_id = "file-aVnVcpEVpsy77xQ8SlTp1WoX" # ライ麦
40
+
41
+ # file_id = "file-HFCaJbf3k7j0fhBqh1Rwf2VV" # 練馬区
42
+
43
+ # コード出力用
44
+ code_mode = {'ON': True, 'OFF': False}
45
+
46
+ def set_state(openai_key, sys_prompt, code_output, state):
47
+ """ 設定タブの情報をセッションに保存する関数 """
48
+
49
+ state["openai_key"] = openai_key
50
+ state["system_prompt"] = sys_prompt
51
+ state["code_mode"] = code_mode[code_output]
52
+
53
+ return state
54
+
55
+
56
+ def init(state, text, file):
57
+ """ 入力チェックを行う関数
58
+ ※ここで例外を起こすと入力できなくなるので次の関数でエラーにする """
59
+
60
+ err_msg = ""
61
+ file_id = None
62
+
63
+ # if state["openai_key"] == "" or state["openai_key"] is None:
64
+
65
+ # # OpenAI API Key未入力
66
+ # err_msg = "OpenAI API Keyを入力してください。(設定タブ)"
67
+
68
+ if not text:
69
+
70
+ # テキスト未入力
71
+ err_msg = "テキストを入力して下さい。"
72
+
73
+ return state, text, file, file_id, err_msg
74
+
75
+ elif file:
76
+
77
+ # 入力画像のファイル形式チェック
78
+ root, ext = os.path.splitext(file)
79
+
80
+ if ext not in file_format:
81
+
82
+ # ファイル形式チェック
83
+ err_msg = "指定した形式のファイルをアップしてください。(注意事項タブに記載)"
84
+
85
+ return state, text, gr.Image(value=None,type="filepath", interactive=False), file_id, err_msg
86
+
87
+ if state["thread_id"] is None:
88
+
89
+ # 初めてなら初期処理をする
90
+ client = OpenAI()
91
+
92
+ # assistant = client.beta.assistants.create(
93
+ # name="codeinter_test",
94
+ # instructions=state["system_prompt"],
95
+ # # model="gpt-4-1106-preview",
96
+ # model="gpt-3.5-turbo-1106",
97
+ # tools=[{"type": "code_interpreter"}]
98
+ # )
99
+
100
+ # print(assistant.id)
101
+
102
+ thread = client.beta.threads.create()
103
+
104
+ state["client"] = client
105
+ # state["assistant_id"] = assistant.id
106
+ state["assistant_id"] = os.environ["ASSIST_ID"]
107
+ state["thread_id"] = thread.id
108
+
109
+ if file:
110
+
111
+ # ファイル名取得
112
+ basename = os.path.basename(file)
113
+
114
+ if example_toid.get(basename):
115
+
116
+ # サンプルの場合は用意したIDをセット
117
+ file_id = example_toid.get(basename)
118
+
119
+ else:
120
+
121
+ # ファイルのアップ
122
+ # file_response = client.files.create(
123
+ # purpose="assistants",
124
+ # file=open(file,"rb"),
125
+ # )
126
+
127
+ # if file_response.status != 'processed':
128
+
129
+ # # 失敗時
130
+ # err_msg = "ファイルのアップロードに失敗しました"
131
+
132
+ # else
133
+ # # ファイルのIDをセット
134
+ # file_id = file_response.id
135
+
136
+ # file_id = "file-0Ly64DA2jzE9mOFYayOKJJK0"
137
+ # file_id = "file-aVnVcpEVpsy77xQ8SlTp1WoX" # ライ麦
138
+
139
+ # file_id = "file-HFCaJbf3k7j0fhBqh1Rwf2VV" # 練馬区
140
+ file_id = ""
141
+
142
+ # print(file_id)
143
+
144
+ return state, text, file, file_id, err_msg
145
+
146
+ def raise_exception(err_msg):
147
+ """ エラーの場合例外を起こす関数 """
148
+
149
+ if err_msg != "":
150
+ raise Exception()
151
+
152
+ return
153
+
154
+
155
+ def add_history(history, text, file_id):
156
+ """ Chat履歴"history"に追加を行う関数 """
157
+
158
+ # print("前:")
159
+ # print(history)
160
+
161
+ err_msg = ""
162
+ new_row_flg = False
163
+
164
+ # 新しい行を追加するか判定
165
+ # if len(history) == 0:
166
+
167
+ # new_row_flg = True
168
+
169
+ # elif history[-1][0] is not None:
170
+
171
+ # # 前回がアシスタントでない場合も追加
172
+ # new_row_flg = True
173
+
174
+ new_row_flg = True
175
+
176
+ if file_id is None or file_id == "":
177
+
178
+ if new_row_flg:
179
+
180
+ # テキストだけの場合そのまま追加
181
+ history = history + [(text, None)]
182
+ else:
183
+ history[-1][0] = text
184
+
185
+ elif file_id is not None:
186
+
187
+ if new_row_flg:
188
+
189
+ # ファイルがあればファイルIDとテキストを追加
190
+ history = history + [("file:" + file_id, DUMMY)]
191
+ history = history + [(text, None)]
192
+
193
+ else:
194
+ history[-1][0] = "file:" + file_id
195
+ history = history + [(text, None)]
196
+
197
+ print(history)
198
+
199
+ # テキストだけ初期化
200
+ new_text = gr.Textbox(value="", interactive=True)
201
+
202
+ return history, new_text, err_msg
203
+
204
+
205
+ def bot(state, history, file_id):
206
+
207
+ err_msg = ""
208
+ image_file = None
209
+ ant_file = None
210
+ # new_row_flg = False
211
+
212
+ # セッション情報取得
213
+ system_prompt = state["system_prompt"]
214
+ client = state["client"]
215
+ assistant_id = state["assistant_id"]
216
+ thread_id = state["thread_id"]
217
+ msg_id = state["last_msg_id"]
218
+ code_mode = state["code_mode"]
219
+
220
+ print("system_prompt")
221
+
222
+ if file_id is None or file_id == "":
223
+
224
+ # ファイルがない場合
225
+ message = client.beta.threads.messages.create(
226
+ thread_id=thread_id,
227
+ role="user",
228
+ content=history[-1][0],
229
+ )
230
+ else:
231
+
232
+ # ファイルがあるときはIDをセット
233
+ message = client.beta.threads.messages.create(
234
+ thread_id=thread_id,
235
+ role="user",
236
+ content=history[-1][0],
237
+ file_ids=[file_id]
238
+ )
239
+
240
+ print("run実行前")
241
+ print(message)
242
+
243
+ # スレッド実行
244
+ run = client.beta.threads.runs.create(
245
+ thread_id=thread_id,
246
+ assistant_id=assistant_id,
247
+ instructions=system_prompt
248
+ )
249
+
250
+ # "completed"となるまで繰り返す(指定秒おき)
251
+ for i in range(0, MAX_TRIAL, 1):
252
+
253
+ if i > 0:
254
+ time.sleep(INTER_SEC)
255
+
256
+ # メッセージ受け取り
257
+ run = client.beta.threads.runs.retrieve(
258
+ thread_id=thread_id,
259
+ run_id=run.id
260
+ )
261
+
262
+ # 前回のメッセージより後を昇順で取り出す
263
+ messages = client.beta.threads.messages.list(
264
+ thread_id=thread_id,
265
+ after=msg_id,
266
+ order="asc"
267
+ )
268
+
269
+ print(msg_id)
270
+ print(messages.data)
271
+
272
+ # messageを取り出す
273
+ for msg in messages:
274
+
275
+ msg_id = msg.id
276
+
277
+ if msg.role == "assistant":
278
+
279
+ for content in msg.content:
280
+
281
+ res_text = ""
282
+ file_id = ""
283
+ ant_file = None
284
+
285
+ cont_dict = content.model_dump() # 辞書型に変換
286
+
287
+ ct_image_file = cont_dict.get("image_file")
288
+
289
+ if ct_image_file:
290
+
291
+ # imageファイルがあるならIDセット
292
+ res_file_id = ct_image_file.get("file_id")
293
+
294
+ # ファイルをダウンロード
295
+ image_file = file_download(client, res_file_id, IMG_FOLDER , ".png")
296
+
297
+ if image_file is None:
298
+
299
+ err_msg = "ファイルのダウンロードに失敗しました。"
300
+
301
+ else:
302
+
303
+ print("画像ファイル追加")
304
+
305
+ res_text = IMG_MSG
306
+
307
+ history = history + [[None, res_text]]
308
+
309
+ else:
310
+
311
+ # 画像がないならテキスト取得
312
+ res_text = cont_dict["text"].get("value")
313
+
314
+ # 注釈(参照ファイル)ががある場合取得
315
+ if len(cont_dict.get("text").get("annotations")) > 0:
316
+
317
+ ct_ant = cont_dict.get("text").get("annotations")
318
+
319
+ if ct_ant[0].get("file_path") is not None:
320
+
321
+ ant_file_id = ct_ant[0].get("file_path").get("file_id")
322
+
323
+
324
+ if ct_ant[0].get("text") is not None:
325
+
326
+ # 拡張子取得
327
+ ext = "." + ct_ant[0].get("text")[ct_ant[0].get("text").rfind('.') + 1:]
328
+
329
+ # ファイルダウンロード
330
+ ant_file = file_download(client, ant_file_id, ANT_FOLDER, ext)
331
+
332
+ if ant_file is None:
333
+
334
+ err_msg = "参照ファイルのダウンロードに失敗しました。"
335
+
336
+ else:
337
+
338
+ # 参照ファイルがある旨のメッセージを追加
339
+ res_text = res_text + "\n\n" + ANT_MSG
340
+
341
+ print(res_text)
342
+
343
+ if res_text != "":
344
+
345
+ # Chat画面更新
346
+ if history[-1][1] is not None:
347
+
348
+ # 新しい行を追加
349
+ history = history + [[None, res_text]]
350
+ else:
351
+
352
+ history[-1][1] = res_text
353
+
354
+ yield history, image_file, ant_file, err_msg
355
+
356
+ print(run.status)
357
+
358
+ state["last_msg_id"] = msg_id
359
+
360
+ # 完了なら終了
361
+ if run.status == "completed":
362
+
363
+ if not code_mode:
364
+ break
365
+ else:
366
+
367
+ # コードモードがONでコードがあれば取得
368
+ run_steps = client.beta.threads.runs.steps.list(
369
+ thread_id=thread_id, run_id=run.id
370
+ )
371
+
372
+ input_code = get_code(run_steps)
373
+
374
+ if input_code != "":
375
+
376
+ input_code = "[input_code]\n\n" + input_code
377
+
378
+ print(input_code)
379
+
380
+ # コードを追加
381
+ history = history + [[None, input_code]]
382
+
383
+ yield history, image_file, ant_file, err_msg
384
+
385
+ break
386
+
387
+ if run.status == "failed":
388
+
389
+ # エラーとして終了
390
+ err_msg = "※メッセージ取得に失敗しました。"
391
+ return history, image_file, ant_file, err_msg
392
+
393
+ if i == MAX_TRIAL:
394
+
395
+ # エラーとして終了
396
+ err_msg = "※メッセージ取得の際にタイムアウトしました。"
397
+ return history, image_file, ant_file, err_msg
398
+
399
+ def get_code(run_steps):
400
+
401
+ input_code = ""
402
+ print("run_steps")
403
+ print(run_steps)
404
+
405
+ for data in run_steps.data:
406
+
407
+ if isinstance(data.step_details, ToolCallsStepDetails):
408
+
409
+ # print(data.step_details)
410
+ input_code = data.step_details.tool_calls[0].code_interpreter.input
411
+
412
+ return input_code
413
+
414
+ def file_download(client, file_id, folder, ext):
415
+ """ OpenAIからファイルをダウンロードしてパスを返す """
416
+ api_response = client.files.with_raw_response.retrieve_content(file_id)
417
+
418
+ if api_response.status_code == 200:
419
+
420
+ content = api_response.content
421
+
422
+ file_path = folder + "/" + file_id + ext
423
+
424
+ with open(file_path, 'wb') as f:
425
+ f.write(content)
426
+
427
+ return file_path
428
+
429
+ else:
430
+ return None
431
+
432
+
433
+ def finally_proc():
434
+
435
+ # os.environ["OPENAI_API_KEY"] = ""
436
+
437
+ # new_text = gr.Textbox(value="", interactive=True)
438
+ new_up_file = gr.File(value=None, interactive = True)
439
+ new_file_id = gr.Textbox(value="")
440
+
441
+ return new_up_file, new_file_id
442
+
443
+
444
+ with gr.Blocks() as demo:
445
+
446
+ gr.Markdown("<h2> </h2>")
447
+
448
+ # セッションの宣言
449
+ state = gr.State({
450
+ "system_prompt": SYS_PROMPT_DEFAULT,
451
+ "openai_key" : None,
452
+ "code_mode" : True, # テスト中
453
+ "client" : None,
454
+ "assistant_id" : None,
455
+ "thread_id" : None,
456
+ "last_msg_id" : ""
457
+ })
458
+
459
+ with gr.Tab("GPT-4V 画像入力対応チャット") as chat:
460
+
461
+ # 各コンポーネント定義
462
+ chatbot = gr.Chatbot(label="チャット画面")
463
+ text_msg = gr.Textbox(label="テキスト")
464
+ # image=gr.Image(type="filepath")
465
+ up_file = gr.File(label="ファイルアップロード", type="filepath",interactive = True)
466
+ gr.Examples(label="サンプルデータ", examples=examples, inputs=[up_file])
467
+ with gr.Row():
468
+ btn = gr.Button(value="送信")
469
+ # btn_download = gr.Button(value="画像のダウンロード") # 保留中
470
+ btn_clear = gr.ClearButton(value="リセット", components=[chatbot, text_msg, up_file, state])
471
+ sys_msg = gr.Textbox(label="システムメッセージ")
472
+ result_image = gr.Image(label="出力画像", type="filepath", interactive = False)
473
+ result_file = gr.File(label="出力ファイル", type="filepath",interactive = False)
474
+
475
+ # GPT用
476
+ file_id = gr.Textbox(visible=False)
477
+
478
+ # 送信ボタンクリック時の処理
479
+ bc = btn.click(init, [state, text_msg, up_file], [state, text_msg, up_file, file_id, sys_msg], queue=False).success(
480
+ raise_exception, sys_msg, None).success(
481
+ add_history, [chatbot, text_msg, file_id], [chatbot, text_msg, sys_msg], queue=False).success(
482
+ bot, [state, chatbot, file_id],[chatbot, result_image, result_file, sys_msg]).then(
483
+ finally_proc, None, [up_file, file_id], queue=False
484
+ )
485
+
486
+ # クリア時でもOpenAIKeyとプロンプトは残す
487
+ btn_clear.click(lambda:chat.select(set_state, [openai_key, system_prompt, state], state), None, None)
488
+
489
+ # up_file.upload(lambda:up_file.value, None, sys_msg)
490
+
491
+ # テキスト入力Enter時の処理
492
+ # txt_msg = text_msg.submit(respond, inputs=[text_msg, image, chatbot], outputs=[text_msg, image, chatbot])
493
+
494
+ with gr.Tab("設定") as set:
495
+ openai_key = gr.Textbox(label="OpenAI API Key")
496
+ # language = gr.Dropdown(choices=["Japanese", "English"], value = "Japanese", label="Language", interactive = True)
497
+ system_prompt = gr.Textbox(value = SYS_PROMPT_DEFAULT,lines = 5, label="Custom instructions", interactive = True)
498
+ # Enter不使用
499
+ code_output = gr.Dropdown(label="コード出力", choices=["OFF", "ON"], value = "ON", interactive = True)
500
+
501
+ # 設定タブからChatタブに戻った時の処理
502
+ chat.select(set_state, [openai_key, system_prompt, code_output, state], state)
503
+
504
+ demo.queue()
505
+
506
+ demo.launch(debug=True)