|
- #!/usr/bin/env python
-
- import asyncio
- import logging
- import os
- from contextlib import asynccontextmanager # noqa: E402
- from datetime import datetime
- from typing import AsyncIterator, Dict, Iterator, List
-
- import uvicorn # noqa: E402
- from fastapi import FastAPI # noqa: E402
- from fastapi.responses import HTMLResponse # noqa: E402
- from websockets.sync.client import connect as ws_connect
-
- import autogen
- from autogen.io.websockets import IOWebsockets
-
- PORT = 8000
-
- # logger = getLogger(__name__)
- logger = logging.getLogger("uvicorn")
-
-
- def _get_config_list() -> List[Dict[str, str]]:
- """Get a list of config dictionaries with API keys for OpenAI and Azure OpenAI.
-
- Returns:
- List[Dict[str, str]]: A list of config dictionaries with API keys.
-
- Example:
- >>> _get_config_list()
- [
- {
- 'model': 'gpt-35-turbo-16k',
- 'api_key': '0123456789abcdef0123456789abcdef',
- 'base_url': 'https://my-deployment.openai.azure.com/',
- 'api_type': 'azure',
- 'api_version': '2024-02-01',
- },
- {
- 'model': 'gpt-4',
- 'api_key': '0123456789abcdef0123456789abcdef',
- },
- ]
- """
- # can use both OpenAI and Azure OpenAI API keys
- config_list = [
- {
- "model": "gpt-35-turbo-16k",
- "api_key": os.environ.get("AZURE_OPENAI_API_KEY"),
- "base_url": os.environ.get("AZURE_OPENAI_BASE_URL"),
- "api_type": "azure",
- "api_version": os.environ.get("AZURE_OPENAI_API_VERSION"),
- },
- {
- "model": "gpt-4",
- "api_key": os.environ.get("OPENAI_API_KEY"),
- },
- ]
- # filter out configs with no API key
- config_list = [llm_config for llm_config in config_list if llm_config["api_key"] is not None]
-
- if not config_list:
- raise ValueError(
- "No API keys found. Please set either AZURE_OPENAI_API_KEY or OPENAI_API_KEY environment variable."
- )
-
- return config_list
-
-
- def on_connect(iostream: IOWebsockets) -> None:
- logger.info(f"on_connect(): Connected to client using IOWebsockets {iostream}")
-
- logger.info("on_connect(): Receiving message from client.")
-
- # get the initial message from the client
- initial_msg = iostream.input()
-
- # instantiate an agent named "chatbot"
- agent = autogen.ConversableAgent(
- name="chatbot",
- system_message="Complete a task given to you and reply TERMINATE when the task is done. If asked about the weather, use tool weather_forecast(city) to get the weather forecast for a city.",
- llm_config={
- "config_list": _get_config_list(),
- "stream": True,
- },
- )
-
- # create a UserProxyAgent instance named "user_proxy"
- user_proxy = autogen.UserProxyAgent(
- name="user_proxy",
- system_message="A proxy for the user.",
- is_termination_msg=lambda x: x.get("content", "") and x.get("content", "").rstrip().endswith("TERMINATE"),
- human_input_mode="NEVER",
- max_consecutive_auto_reply=10,
- code_execution_config=False,
- )
-
- # register the weather_forecast function
- def weather_forecast(city: str) -> str:
- return f"The weather forecast for {city} at {datetime.now()} is sunny."
-
- autogen.register_function(
- weather_forecast, caller=agent, executor=user_proxy, description="Weather forecast for a city"
- )
-
- # instantiate a chat
- logger.info(
- f"on_connect(): Initiating chat with the agent ({agent.name}) and the user proxy ({user_proxy.name}) using the message '{initial_msg}'",
- )
- user_proxy.initiate_chat( # noqa: F704
- agent,
- message=initial_msg,
- )
-
- logger.info("on_connect(): Finished the task successfully.")
-
-
- html = """
- <!DOCTYPE html>
- <html>
- <head>
- <title>Autogen websocket test</title>
- </head>
- <body>
- <h1>WebSocket Chat</h1>
- <form action="" onsubmit="sendMessage(event)">
- <input type="text" id="messageText" autocomplete="off" value="Write a poem about the current wearther in Paris or London, you choose."/>
- <button>Send</button>
- </form>
- <ul id='messages'>
- </ul>
- <script>
- var ws = new WebSocket("ws://localhost:8080/ws");
- ws.onmessage = function(event) {
- var messages = document.getElementById('messages')
- var message = document.createElement('li')
- var content = document.createTextNode(event.data)
- message.appendChild(content)
- messages.appendChild(message)
- };
- function sendMessage(event) {
- var input = document.getElementById("messageText")
- ws.send(input.value)
- input.value = ''
- event.preventDefault()
- }
- </script>
- </body>
- </html>
- """
-
-
- @asynccontextmanager
- async def run_websocket_server(app: FastAPI) -> AsyncIterator[None]:
- with IOWebsockets.run_server_in_thread(on_connect=on_connect, port=8080) as uri:
- logger.info(f"Websocket server started at {uri}.")
-
- yield
-
-
- app = FastAPI(lifespan=run_websocket_server)
-
-
- @app.get("/")
- async def get() -> HTMLResponse:
- return HTMLResponse(html)
-
-
- async def start_uvicorn() -> None:
- config = uvicorn.Config(app)
- server = uvicorn.Server(config)
- try:
- await server.serve() # noqa: F704
- except KeyboardInterrupt:
- logger.info("Shutting down server")
-
-
- if __name__ == "__main__":
- # set the log level to INFO
- logger.setLevel("INFO")
- asyncio.run(start_uvicorn())
|