nekoniii3 commited on
Commit
ea3522f
·
1 Parent(s): 32e4665
Files changed (2) hide show
  1. app.py +591 -0
  2. requirements.txt +2 -0
app.py ADDED
@@ -0,0 +1,591 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import datetime
4
+ import gradio as gr
5
+ from openai.types.beta.threads.runs import ToolCallsStepDetails
6
+ from openai import (
7
+ OpenAI, AuthenticationError, NotFoundError, BadRequestError
8
+ )
9
+
10
+ # GPT用設定
11
+ SYS_PROMPT_DEFAULT = "あなたは優秀なアシスタントです。質問をされた場合は、質問に答えるコードを作成して実行します。回答は日本語でお願いします。"
12
+
13
+ # アシスタント用設定
14
+ DF_MODEL = "gpt-3.5-turbo-1106"
15
+ ASSIST_NAME = "Code Interpreter Assistant for O3"
16
+ AST_SYS_PROMPT = "あなたは優秀なアシスタントです。質問をされた場合は、質問に答えるコードを作成して実行します。回答は日本語でお願いします。"
17
+
18
+ # DUMMY = "********************"
19
+ # file_format = {".txt", ".csv", ".pdf"}
20
+ file_format = {".txt", ".csv", ".jpg", ".jpeg", ".png", ".xlsx", ".pdf"}
21
+
22
+ # 各種出力フォルダ
23
+ # IMG_FOLDER = "images"
24
+ # ANT_FOLDER = "annotations"
25
+
26
+ # 各種メッセージ
27
+ PLACEHOLDER = "これは東京都の年別人口データです、折れ線グラフでデータの可視化をお願いします… など"
28
+ IMG_MSG = "(画像ファイルを追加しました。リセットボタンの上に表示されています。)"
29
+ ANT_MSG = "(下部の[出力ファイル]にファイルを追加しました。)"
30
+
31
+ # 各種設定値
32
+ MAX_TRIAL = int(os.environ["MAX_TRIAL"]) # メッセージ取得最大試行数
33
+ INTER_SEC = int(os.environ["INTER_SEC"]) # 試行間隔(秒)
34
+
35
+ # サンプル用情報
36
+ examples = ["sample_data/東京都年別人口.csv", "sample_data/世界の人口2023年.csv", "sample_data/練馬区年齢別人口.csv", "sample_data/桃太郎あらすじ.txt"]
37
+
38
+ example_toid = {"東京都年別人口.csv" : "file-TMLJxwdTy1oaaoo2l712r1Os"
39
+ ,"世界の人口2023年.csv" : "file-rafHPSkmMciOjKovah0u5oug"
40
+ , "練馬区年齢別人口.csv" : "file-B5VqVSqgh8dB70ygHwt0LVIH"
41
+ , "桃太郎あらすじ.txt" : "file-ylcNO5LShDYgDk5wiuSiyTMA"}
42
+ # ,"South Africa-2023.csv" : "file-6aarxpoX4TISJjqPH2Pi3QMV"}
43
+
44
+ # コード出力用
45
+ code_mode = {'ON': True, 'OFF': False}
46
+
47
+
48
+ # 各関数
49
+ def set_state(openai_key, sys_prompt, code_output, state):
50
+ """ 設定タブの情報をセッションに保存する関数 """
51
+
52
+ state["openai_key"] = openai_key
53
+ state["system_prompt"] = sys_prompt
54
+ state["code_mode"] = code_mode[code_output]
55
+
56
+ return state
57
+
58
+
59
+ def init(state, text, file):
60
+ """ 入力チェックを行う関数
61
+ ※ここで例外を起こすと入力できなくなるので次の関数でエラーにする """
62
+
63
+ err_msg = ""
64
+ file_id = None
65
+
66
+ if state["openai_key"] == "" is None:
67
+
68
+ # OpenAI API Key未入力
69
+ err_msg = "OpenAI API Keyを入力してください。(設定タブ)"
70
+
71
+ return state, file_id, err_msg
72
+
73
+ if not text:
74
+
75
+ # テキスト未入力
76
+ err_msg = "テキストを入力して下さい。"
77
+
78
+ return state, file_id, err_msg
79
+
80
+ elif file:
81
+
82
+ # 入力ファイルの形式チェック
83
+ root, ext = os.path.splitext(file)
84
+
85
+ if ext not in file_format:
86
+
87
+ # ファイル形式チェック
88
+ err_msg = "指定した形式のファイルをアップしてください。(注意事項タブに記載)"
89
+
90
+ return state, file_id, err_msg
91
+
92
+ try:
93
+
94
+ if state["client"] is None:
95
+
96
+ # 初回起動時は初期処理をする
97
+ # os.environ["OPENAI_API_KEY"] = os.environ["TEST_OPENAI_KEY"] # テスト時
98
+ os.environ["OPENAI_API_KEY"] = state["openai_key"]
99
+
100
+ # クライアント新規作成
101
+ client = OpenAI()
102
+
103
+ # client作成後は消す
104
+ os.environ["OPENAI_API_KEY"] = ""
105
+
106
+ # セッションにセット
107
+ state["client"] = client
108
+
109
+ else:
110
+
111
+ # 既存のクライアントをセット
112
+ client = state["client"]
113
+
114
+ if state["thread_id"] == "":
115
+
116
+ # スレッド作成
117
+ thread = client.beta.threads.create()
118
+
119
+ state["thread_id"] = thread.id
120
+
121
+
122
+ if state["assistant_id"] == "":
123
+
124
+ assistant_id = get_assist_id(client, ASSIST_NAME)
125
+
126
+ if assistant_id == "":
127
+
128
+ # アシスタント新規作成
129
+ assistant = client.beta.assistants.create(
130
+ name=ASSIST_NAME,
131
+ instructions=AST_SYS_PROMPT,
132
+ model=DF_MODEL,
133
+ tools=[{"type": "code_interpreter"}] # テスト中はオフ
134
+ )
135
+
136
+ assistant_id = assistant.id
137
+
138
+ state["assistant_id"] = assistant_id
139
+
140
+ # アシスタントIDでフォルダ作成
141
+ os.makedirs(state["assistant_id"], exist_ok=True)
142
+
143
+ if file:
144
+
145
+ # ファイル名取得
146
+ basename = os.path.basename(file)
147
+
148
+ if example_toid.get(basename):
149
+
150
+ # サンプルの場合は用意したIDをセット
151
+ file_id = example_toid.get(basename)
152
+
153
+ else:
154
+
155
+ # ファイルのアップ
156
+ file_response = client.files.create(
157
+ purpose="assistants",
158
+ file=open(file,"rb"),
159
+ )
160
+
161
+ if file_response.status != "processed":
162
+
163
+ # 失敗時
164
+ err_msg = "ファイルのアップロードに失敗しました"
165
+
166
+ else:
167
+ # ファイルのIDをセット
168
+ file_id = file_response.id
169
+
170
+
171
+ except NotFoundError as e:
172
+ err_msg = "アシスタントIDが間違っています。新しく作成する場合はアシスタントIDを空欄にして下さい。"
173
+ except AuthenticationError as e:
174
+ err_msg = "認証エラーとなりました。OpenAPIKeyが正しいか、支払い方法などが設定されているか確認して下さい。"
175
+ except Exception as e:
176
+ err_msg = "その他のエラーが発生しました。"
177
+ print(e)
178
+ finally:
179
+ return state, file_id, err_msg
180
+
181
+ def get_assist_id(client, assist_name):
182
+
183
+ assist_id = ""
184
+
185
+ assist_list = client.beta.assistants.list()
186
+
187
+ if len(assist_list.data) == 0:
188
+
189
+ return assist_id
190
+
191
+ for assist in assist_list:
192
+
193
+ if assist.name == assist_name:
194
+
195
+ assist_id = assist.id
196
+
197
+ break
198
+
199
+ return assist_id
200
+
201
+ def raise_exception(err_msg):
202
+ """ エラーの場合例外を起こす関数 """
203
+
204
+ if err_msg != "":
205
+ raise Exception("これは入力チェックでの例外です。")
206
+
207
+ return
208
+
209
+
210
+ def add_history(history, text, file_id):
211
+ """ Chat履歴"history"に追加を行う関数 """
212
+
213
+ err_msg = ""
214
+
215
+ # 入力テキスト追加
216
+ history = history + [(text, None)]
217
+
218
+ # テキスト・ファイルを初期化し利用不可に
219
+ update_text = gr.update(value="", placeholder = "",interactive=False)
220
+ update_file = gr.update(value=None, interactive=False)
221
+
222
+ return history, update_text, update_file, err_msg
223
+
224
+
225
+ def bot(state, history, file_id):
226
+
227
+ err_msg = ""
228
+ image_file = None
229
+ ant_file = None
230
+
231
+ # セッション情報取得
232
+ system_prompt = state["system_prompt"]
233
+ client = state["client"]
234
+ assistant_id = state["assistant_id"]
235
+ thread_id = state["thread_id"]
236
+ last_msg_id = state["last_msg_id"]
237
+ code_mode = state["code_mode"]
238
+
239
+ if file_id is None or file_id == "":
240
+
241
+ # ファイルがない場合
242
+ message = client.beta.threads.messages.create(
243
+ thread_id=thread_id,
244
+ role="user",
245
+ content=history[-1][0],
246
+ )
247
+ else:
248
+
249
+ # ファイルがあるときはIDをセット
250
+ message = client.beta.threads.messages.create(
251
+ thread_id=thread_id,
252
+ role="user",
253
+ content=history[-1][0],
254
+ file_ids=[file_id]
255
+ )
256
+
257
+ print(message)
258
+
259
+ # RUNスタート
260
+ run = client.beta.threads.runs.create(
261
+ thread_id=thread_id,
262
+ assistant_id=assistant_id,
263
+ instructions=system_prompt
264
+ )
265
+
266
+ # "completed"となるまで繰り返す
267
+ for i in range(0, MAX_TRIAL, 1):
268
+
269
+ if i > 0:
270
+ time.sleep(INTER_SEC) # 指定秒待つ
271
+
272
+ # メッセージ受け取り
273
+ run = client.beta.threads.runs.retrieve(
274
+ thread_id=thread_id,
275
+ run_id=run.id
276
+ )
277
+
278
+ # 前回のメッセージより後を昇順で取り出す
279
+ messages = client.beta.threads.messages.list(
280
+ thread_id=thread_id,
281
+ after=last_msg_id,
282
+ order="asc"
283
+ )
284
+
285
+ # デバッグ用
286
+ print(run.status)
287
+ print(messages)
288
+
289
+ # messageを取り出す
290
+ for msg in messages:
291
+
292
+ if msg.role == "assistant":
293
+
294
+ for content in msg.content:
295
+
296
+ res_text = ""
297
+ file_id = ""
298
+ ant_file = None
299
+
300
+ cont_dict = content.model_dump() # 辞書型に変換
301
+
302
+ ct_image_file = cont_dict.get("image_file")
303
+
304
+ if ct_image_file:
305
+
306
+ # imageファイルがあるならIDセット
307
+ res_file_id = ct_image_file.get("file_id")
308
+
309
+ # ファイルをダウンロード
310
+ image_file = file_download(client, res_file_id, assistant_id, ".png")
311
+
312
+ if image_file is None:
313
+
314
+ err_msg = "ファイルのダウンロードに失敗しました。"
315
+
316
+ else:
317
+
318
+ res_text = IMG_MSG
319
+
320
+ history = history + [[None, res_text]]
321
+
322
+ # 最終メッセージID更新
323
+ last_msg_id = msg.id
324
+
325
+ else:
326
+
327
+ # 返答テキスト取得
328
+ res_text = cont_dict["text"].get("value")
329
+
330
+ # 注釈(参照ファイル)ががある場合取得
331
+ if len(cont_dict.get("text").get("annotations")) > 0:
332
+
333
+ ct_ant = cont_dict.get("text").get("annotations")
334
+
335
+ if ct_ant[0].get("file_path") is not None:
336
+
337
+ # 参照ファイルのID取得
338
+ ant_file_id = ct_ant[0].get("file_path").get("file_id")
339
+
340
+ if ct_ant[0].get("text") is not None:
341
+
342
+ # ファイル形式(拡張子)取得
343
+ ext = "." + ct_ant[0].get("text")[ct_ant[0].get("text").rfind('.') + 1:]
344
+
345
+ # ファイルダウンロード
346
+ ant_file = file_download(client, ant_file_id, assistant_id, ext)
347
+
348
+ if ant_file is None:
349
+
350
+ err_msg = "参照ファイルのダウンロードに失敗しました。"
351
+
352
+ else:
353
+
354
+ # 参照ファイルがある旨のメッセージを追加
355
+ res_text = res_text + "\n\n" + ANT_MSG
356
+
357
+ if res_text != "":
358
+
359
+ # Chat画面更新
360
+ if history[-1][1] is not None:
361
+
362
+ # 新しい行を追加
363
+ history = history + [[None, res_text]]
364
+ else:
365
+
366
+ history[-1][1] = res_text
367
+
368
+ # 最終メッセージID更新
369
+ last_msg_id = msg.id
370
+
371
+ # Chatbotを返す(labelとhistoryを更新)
372
+ yield gr.Chatbot(label=run.status, value=history), image_file, ant_file, err_msg
373
+
374
+ # メッセージIDを保存
375
+ state["last_msg_id"] = last_msg_id
376
+
377
+ # 完了なら終了
378
+ if run.status == "completed":
379
+
380
+ if not code_mode:
381
+
382
+ # yield gr.Chatbot(label=run.status ,value=history), image_file, ant_file, err_msg
383
+
384
+ break
385
+ else:
386
+
387
+ # コードモードがONの場合
388
+ run_steps = client.beta.threads.runs.steps.list(
389
+ thread_id=thread_id, run_id=run.id
390
+ )
391
+
392
+ # コードを取得
393
+ input_code = get_code(run_steps)
394
+
395
+ if len(input_code) > 0:
396
+
397
+ for code in input_code:
398
+
399
+ code = "[input_code]\n\n" + code
400
+
401
+ # コードを追加
402
+ history = history + [[None, code]]
403
+
404
+ yield gr.Chatbot(label=run.status ,value=history), image_file, ant_file, err_msg
405
+
406
+ break
407
+
408
+ elif run.status == "failed":
409
+
410
+ # エラーとして終了
411
+ err_msg = "※メッセージ取得に失敗しました。"
412
+ yield gr.Chatbot(label=run.status ,value=history), image_file, ant_file, err_msg
413
+ break
414
+
415
+ elif i == MAX_TRIAL:
416
+
417
+ # エラーとして終了
418
+ err_msg = "※メッセージ取得の際にタイムアウトしました。"
419
+ yield gr.Chatbot(label=run.status ,value=history), image_file, ant_file, err_msg
420
+ break
421
+
422
+ # else:
423
+ # if i > 3:
424
+
425
+ # # 作業中とわかるようにする
426
+ # yield gr.Chatbot(label=run.status + " (Request:" + str(i) + ")" ,value=history), image_file, ant_file, err_msg
427
+
428
+
429
+ def get_code(run_steps):
430
+ """ 生成過程のコードを全てを返す """
431
+
432
+ input_code = []
433
+
434
+ for data in run_steps.data:
435
+
436
+ if isinstance(data.step_details, ToolCallsStepDetails):
437
+
438
+ # コードが存在するときだけ取得
439
+ for tool_call in data.step_details.tool_calls:
440
+
441
+ input_code.append(tool_call.code_interpreter.input)
442
+
443
+ return input_code
444
+
445
+
446
+ def file_download(client, file_id, folder, ext):
447
+ """ OpenAIからファイルをダウンロードしてパスを返す """
448
+
449
+ api_response = client.files.with_raw_response.retrieve_content(file_id)
450
+
451
+ if api_response.status_code == 200:
452
+
453
+ content = api_response.content
454
+
455
+ file_path = folder + "/" + file_id + ext
456
+
457
+ with open(file_path, 'wb') as f:
458
+ f.write(content)
459
+
460
+ return file_path
461
+
462
+ else:
463
+ return None
464
+
465
+
466
+ def finally_proc():
467
+ """ 最終処理用関数 """
468
+
469
+ # テキスト・ファイルを使えるように
470
+ interactive = gr.update(interactive = True)
471
+
472
+ # ファイルIDはリセット
473
+ new_file_id = gr.Textbox(value="")
474
+
475
+ return interactive, interactive, new_file_id
476
+
477
+
478
+ def clear_click(state):
479
+ """ クリアボタンクリック時 """
480
+
481
+ # セッションの一部をリセット()
482
+ # state["assistant_id"] = ""
483
+ state["thread_id"] = ""
484
+ state["last_msg_id"] = ""
485
+
486
+ return state
487
+
488
+ # 画面構���
489
+ with gr.Blocks() as demo:
490
+
491
+ # title = "<h2>GPT Code Interpreter対応チャット</h2>"
492
+ # message = "・テスト中でAPIKEY無しで動きます ※機密ファイルはアップしないでください<br>"
493
+ # message += "・こういうときにエラーになるなどフィードバックあればお待ちしています。<br>"
494
+ # message += "・コードインタープリターAPIの解説動画はこちらです→"
495
+ # message += "https://www.youtube.com/watch?v=tFmedAM1FM8<br>"
496
+ # message += '※動いているかわかりづらいですが、左上の"in_progress(Request:XX)"が止まっていなければ回答の生成中となります。<br>'
497
+ # message += "※グラフの日本語文字化けの対応方法を注意事項に記載しました。<br>"
498
+
499
+ title = "<h2>Code Interpreterデモアプリ</h2>"
500
+ message = "<h3>最初に[設定]タブからOpenAIキーを入力してください。"
501
+ message += "</h3>"
502
+
503
+ gr.Markdown(title + "<h3>" + message + "</h3>")
504
+
505
+ # セッションの宣言
506
+ state = gr.State({
507
+ "system_prompt": SYS_PROMPT_DEFAULT,
508
+ "openai_key" : "",
509
+ "code_mode" : False,
510
+ "client" : None,
511
+ "assistant_id" : "",
512
+ "thread_id" : "",
513
+ "last_msg_id" : ""
514
+ })
515
+
516
+ with gr.Tab("Chat画面") as chat:
517
+
518
+ # 各コンポーネント定義
519
+ chatbot = gr.Chatbot(label="チャット画面")
520
+ text_msg = gr.Textbox(label="テキスト", placeholder = PLACEHOLDER)
521
+ with gr.Row():
522
+ up_file = gr.File(label="ファイルアップロード", type="filepath",interactive = True)
523
+ result_image = gr.Image(label="出力画像", type="filepath", interactive = False)
524
+ # gr.Examples(label="サンプルデータ", examples=examples, inputs=[up_file])
525
+ with gr.Row():
526
+ btn = gr.Button(value="送信")
527
+ # btn_download = gr.Button(value="画像のダウンロード") # 保留中
528
+ # btn_clear = gr.ClearButton(value="リセット", components=[chatbot, text_msg, up_file, file_id, result_image, sys_msg, result_file])
529
+ btn_clear = gr.ClearButton(value="リセット", components=[chatbot, text_msg, up_file])
530
+ sys_msg = gr.Textbox(label="システムメッセージ", interactive = False)
531
+ result_file = gr.File(label="出力ファイル", type="filepath",interactive = False)
532
+
533
+ # ファイルID保存用
534
+ file_id = gr.Textbox(visible=False)
535
+
536
+ # 送信ボタンクリック時の処理
537
+ bc = btn.click(init, [state, text_msg, up_file], [state, file_id, sys_msg], queue=False).success(
538
+ raise_exception, sys_msg, None).success(
539
+ add_history, [chatbot, text_msg, file_id], [chatbot, text_msg, up_file, sys_msg], queue=False).success(
540
+ bot, [state, chatbot, file_id],[chatbot, result_image, result_file, sys_msg]).then(
541
+ finally_proc, None, [text_msg, up_file, file_id], queue=False
542
+ )
543
+
544
+ # クリア時でもセッションの設定(OpenAIKeyなどは残す)
545
+ btn_clear.click(clear_click, state, state)
546
+
547
+ # テキスト入力Enter時の処理
548
+ # txt_msg = text_msg.submit(respond, inputs=[text_msg, image, chatbot], outputs=[text_msg, image, chatbot])
549
+
550
+ with gr.Tab("設定") as set:
551
+ openai_key = gr.Textbox(label="OpenAI API Key", visible=True)
552
+ # language = gr.Dropdown(choices=["Japanese", "English"], value = "Japanese", label="Language", interactive = True)
553
+ system_prompt = gr.Textbox(value = SYS_PROMPT_DEFAULT,lines = 5, label="Custom instructions", interactive = True)
554
+ code_output = gr.Dropdown(label="コード出力", choices=["OFF", "ON"], value = "OFF", interactive = True)
555
+
556
+ # 設定タブからChatタブに戻った時の処理
557
+ chat.select(set_state, [openai_key, system_prompt, code_output, state], state)
558
+
559
+ with gr.Tab("注意事項") as notes:
560
+ caution = "現在Assistant APIはβ版でのリリースとなっています。<br>"
561
+ caution += "そのためか一部のファイルのアップロードが上手くいかないため、制限をかけています。<br>"
562
+ caution += "(現在アップできるファイル形式は.txtと.csvのみ)<br>"
563
+ caution += "本来はPDFなども利用できるはずなので、今後更新したいと思います。<br>"
564
+ caution += "文字化けする場合「NotoSansJP-Bold.zipを解凍してフォントを取得して下さい。」と指示し<br>"
565
+ caution += "グラフ作成時に「フォントはNotoSansJP-Boldを使用して下さい。」と指示して下さい。<br>"
566
+ caution += "※NotoSansJP-Bold.zipをアップする必要はありません。<br>"
567
+ caution += "詳細はこちら→https://github.com/nekoniii3/openai_multi_chat/tree/main/Code_Interpreter/docs/%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%83%95%E3%82%A9%E3%83%B3%E3%83%88%E5%88%A9%E7%94%A8"
568
+ gr.Markdown("<h3>" + caution + "</h3>")
569
+
570
+
571
+ if __name__ == "__main__":
572
+
573
+ demo.queue()
574
+ demo.launch(debug=True)
575
+
576
+ import os
577
+
578
+ os.environ["TEST_OPENAI_KEY"] = "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"
579
+
580
+ # 初回起動時は初期処理をする
581
+ os.environ["OPENAI_API_KEY"] = os.environ["TEST_OPENAI_KEY"] # テスト時
582
+ # os.environ["OPENAI_API_KEY"] = state["openai_key"]
583
+
584
+ # クライアント新規作成
585
+ client = OpenAI()
586
+
587
+ api_response = client.files.with_raw_response.retrieve_content("file-UzuIIi5kk5FBnvffcAekvWzV")
588
+
589
+ # api_response = client.files.list()
590
+
591
+ # api_response
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ # gradio==4.0.2
2
+ openai==1.6.1