123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 |
- #!/usr/bin/env python3
- from openai import AsyncOpenAI
- from openai.types.beta.assistant_stream_event import ThreadMessageInProgress
- from openai.types.beta.threads import MessageDeltaEvent, TextDeltaBlock
- from nicegui import ui
- client = AsyncOpenAI(api_key='provide your OpenAI API key here')
- @ui.page('/')
- async def main():
- assistant = await client.beta.assistants.create(
- name='NiceGUI Assistant',
- instructions='''
- You are a personal assistant for NiceGUI developers.
- Your sole focus is to help with questions about the NiceGUI framework.
- You are precise and concise.
- Stay on the topic.
- Very short answers are preferred, but always be friendly and polite.
- ''',
- tools=[{'type': 'code_interpreter'}],
- model='gpt-4o-mini',
- )
- thread = await client.beta.threads.create()
- async def send() -> None:
- response.content = ''
- spinner = ui.spinner(size='5em', type='comment').classes('mx-auto')
- await client.beta.threads.messages.create(
- thread_id=thread.id,
- role='user',
- content=question.value,
- )
- stream = await client.beta.threads.runs.create(
- assistant_id=assistant.id,
- thread_id=thread.id,
- stream=True,
- )
- async for chunk in stream:
- if isinstance(chunk, ThreadMessageInProgress):
- spinner.delete()
- # NOTE: the stream contains a lot of different types so we need to filter out the ones we don't need
- if not isinstance(chunk.data, MessageDeltaEvent) or not chunk.data.delta.content:
- continue
- content = chunk.data.delta.content[0]
- if not isinstance(content, TextDeltaBlock) or content.text is None or content.text.value is None:
- continue
- response.content += content.text.value
- with ui.column().classes('mx-auto w-full max-w-xl my-16'):
- ui.label('NiceGUI Assistant').classes('text-2xl font-bold mx-auto')
- question = ui.input(value='Why does NiceGUI use async/await?') \
- .classes('w-full self-center mt-4').props('hint="Ask your question" dense') \
- .on('keydown.enter', send)
- response = ui.markdown().classes('mx-4 mt-2')
- ui.timer(0, send, once=True) # NOTE: we send the prepared demo question immediately
- ui.run()
|