|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | +"""The server that holds agent service.""" |
| 3 | +import json |
| 4 | +import os |
| 5 | +from typing import AsyncGenerator |
| 6 | + |
| 7 | +from quart import Quart, Response, request |
| 8 | + |
| 9 | +from tool import create_worker |
| 10 | + |
| 11 | +from agentscope.pipeline import stream_printing_messages |
| 12 | +from agentscope.session import JSONSession |
| 13 | +from agentscope.agent import ReActAgent |
| 14 | +from agentscope.formatter import DashScopeChatFormatter |
| 15 | +from agentscope.message import Msg |
| 16 | +from agentscope.model import DashScopeChatModel |
| 17 | +from agentscope.tool import Toolkit |
| 18 | + |
| 19 | +app = Quart(__name__) |
| 20 | + |
| 21 | + |
| 22 | +async def handle_input( |
| 23 | + msg: Msg, |
| 24 | + user_id: str, |
| 25 | + session_id: str, |
| 26 | +) -> AsyncGenerator[str, None]: |
| 27 | + """Handle the input message and yield response chunks. |
| 28 | +
|
| 29 | + Args: |
| 30 | + msg (`Msg`): |
| 31 | + The input message from the user. |
| 32 | + user_id (`str`): |
| 33 | + The user ID. |
| 34 | + session_id (`str`): |
| 35 | + The session ID. |
| 36 | +
|
| 37 | + Yields: |
| 38 | + `str`: |
| 39 | + A response message in dict format by `Msg().to_dict()`. |
| 40 | + """ |
| 41 | + toolkit = Toolkit() |
| 42 | + toolkit.register_tool_function( |
| 43 | + create_worker, |
| 44 | + ) |
| 45 | + |
| 46 | + # Init JSONSession to save and load the state |
| 47 | + session = JSONSession(save_dir="./sessions") |
| 48 | + |
| 49 | + agent = ReActAgent( |
| 50 | + name="Friday", |
| 51 | + # pylint: disable=line-too-long |
| 52 | + sys_prompt="""You are Friday, a multifunctional agent that can help people solving different complex tasks. You act like a meta planner to solve complicated tasks by decomposing the task and building/orchestrating different worker agents to finish the sub-tasks. |
| 53 | +
|
| 54 | +## Core Mission |
| 55 | +Your primary purpose is to break down complicated tasks into manageable subtasks (a plan), create worker agents to finish the subtask, and coordinate their execution to achieve the user's goal efficiently. |
| 56 | +
|
| 57 | +### Important Constraints |
| 58 | +1. DO NOT TRY TO SOLVE THE SUBTASKS DIRECTLY yourself. |
| 59 | +2. Always follow the plan sequence. |
| 60 | +3. DO NOT finish the plan until all subtasks are finished. |
| 61 | +""", # noqa: E501 |
| 62 | + model=DashScopeChatModel( |
| 63 | + model_name="qwen3-max", |
| 64 | + api_key=os.environ.get("DASHSCOPE_API_KEY"), |
| 65 | + ), |
| 66 | + formatter=DashScopeChatFormatter(), |
| 67 | + toolkit=toolkit, |
| 68 | + ) |
| 69 | + |
| 70 | + # Load the session state if exists |
| 71 | + await session.load_session_state( |
| 72 | + session_id=f"{user_id}-{session_id}", |
| 73 | + agent=agent, |
| 74 | + ) |
| 75 | + |
| 76 | + async for msg, _ in stream_printing_messages( |
| 77 | + agents=[agent], |
| 78 | + coroutine_task=agent(msg), |
| 79 | + ): |
| 80 | + # Transform the message into a dict string and yield it |
| 81 | + data = json.dumps(msg.to_dict(), ensure_ascii=False) |
| 82 | + yield f"data: {data}\n\n" |
| 83 | + |
| 84 | + # Save the session state |
| 85 | + await session.save_session_state( |
| 86 | + session_id=f"{user_id}-{session_id}", |
| 87 | + agent=agent, |
| 88 | + ) |
| 89 | + |
| 90 | + |
| 91 | +@app.route("/chat_endpoint", methods=["POST"]) |
| 92 | +async def chat_endpoint() -> Response: |
| 93 | + """A simple chat endpoint that streams responses.""" |
| 94 | + # Parse the user_id, session_id and user message from the request body |
| 95 | + data = await request.get_json() |
| 96 | + |
| 97 | + user_id = data.get("user_id") |
| 98 | + session_id = data.get("session_id") |
| 99 | + |
| 100 | + # We use textual input here, you can extend it to support other types |
| 101 | + user_input = data.get("user_input") |
| 102 | + |
| 103 | + # If the user_id or session_id is missing, return 400 |
| 104 | + if not user_id or not session_id: |
| 105 | + return Response( |
| 106 | + f"user_id and session_id are required, got user_id: {user_id}, " |
| 107 | + f"session_id: {session_id}", |
| 108 | + status=400, |
| 109 | + ) |
| 110 | + |
| 111 | + return Response( |
| 112 | + handle_input( |
| 113 | + Msg( |
| 114 | + "user", |
| 115 | + user_input, |
| 116 | + "user", |
| 117 | + ), |
| 118 | + user_id, |
| 119 | + session_id, |
| 120 | + ), |
| 121 | + mimetype="text/event-stream", |
| 122 | + ) |
| 123 | + |
| 124 | + |
| 125 | +if __name__ == "__main__": |
| 126 | + app.run( |
| 127 | + port=5000, |
| 128 | + debug=True, |
| 129 | + ) |
0 commit comments