Skip to content

Instantly share code, notes, and snippets.

@zerebom
Last active February 12, 2024 01:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zerebom/bc9dce376a9a8f28a32e5c73b425a239 to your computer and use it in GitHub Desktop.
Save zerebom/bc9dce376a9a8f28a32e5c73b425a239 to your computer and use it in GitHub Desktop.
Async-open-ai-call-app-w-gradio
from typing import AsyncIterator
import gradio as gr
from openai import AsyncOpenAI
client = AsyncOpenAI()
async def fetch_gpt_response(
prompt: str, model: str = "gpt-3.5-turbo"
) -> AsyncIterator[str]:
"""
GPTからのレスポンスを非同期で取得し、内容を連結して返す。
ex) こん→こんにちは→こんにちは、元気ですか?
"""
stream = await client.chat.completions.create(
model=model,
messages=[
{"role": "user", "content": prompt},
],
stream=True,
)
all_content = ""
async for chunk in stream:
chunk_content = chunk.choices[0].delta.content
if chunk_content is not None:
all_content += chunk_content
yield all_content
async def merge_async_iterators(*iterables: AsyncIterator) -> AsyncIterator[tuple[str]]:
"""
複数のAyncIteratorを受け取り、それぞれの最新の値をタプルにまとめて返す。
いずれかのAsyncIteratorが終了した場合は、その値を最後の値として返す。
すべてのAsyncIteratorが終了した場合は、処理を終了する。
"""
iterators = [iterable.__aiter__() for iterable in iterables]
last_values = [None] * len(iterators)
done_flags = [False] * len(iterators)
while not all(done_flags):
results = []
for idx, it in enumerate(iterators):
if done_flags[idx]:
results.append(last_values[idx])
continue
try:
next_item = await it.__anext__()
last_values[idx] = next_item
results.append(next_item)
except StopAsyncIteration:
done_flags[idx] = True
results.append(last_values[idx])
yield tuple(results)
def build_whole_prompt(user_prompt: str, detail_prompt: str) -> str:
return f"""
課題の解像度を上げるために、対象に「{user_prompt}」ついて、アクション:{detail_prompt}を行ってください。
会話形式や補足情報は不要です。
各項目には、対象「{user_prompt}」に直接関連する情報を、簡潔に記述してください。
具体性を持たせるため、実際のデータや事実に基づいた内容を想定しています。
下記に続くように回答してください。
会話形式や補足情報は不要です。アクションだけ行ってください。
---
課題:「{user_prompt}」に「{detail_prompt}」を行う、
"""
async def main(user_prompt: str) -> AsyncIterator[str]:
detail_prompts = [
"深く考え直す。なぜ?を9回繰り返し問う。",
"広く考え直す。異なるアプローチや視点を検討する。",
"構造を見直す。原因や要因の関係性を把握する。",
"時間軸について考える。時間的な変化を捉えて洞察につなげる。",
]
gpt_responses = [
fetch_gpt_response(build_whole_prompt(user_prompt, detail_prompt))
for detail_prompt in detail_prompts
]
async for merged_responses in merge_async_iterators(*gpt_responses):
yield merged_responses
if __name__ == "__main__":
with gr.Blocks(theme=gr.themes.Soft()) as demo:
greet_btn = gr.Textbox(
label="課題", placeholder="解像度を上げたい課題を入力してください。"
)
btn = gr.Button("Start")
with gr.Row():
with gr.Column():
t1 = gr.Textbox(label="深さ")
with gr.Column():
t2 = gr.Textbox(label="広さ")
with gr.Row():
with gr.Column():
t3 = gr.Textbox(label="構造")
with gr.Column():
t4 = gr.Textbox(label="時間")
outputs = [t1, t2, t3, t4]
btn.click(
fn=main,
inputs=greet_btn,
outputs=outputs,
)
demo.launch()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment