diff --git a/parameters.pkl b/parameters.pkl deleted file mode 100644 index b051368..0000000 Binary files a/parameters.pkl and /dev/null differ diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index e69de29..0000000 diff --git a/utils/agent.py b/utils/agent.py index ee50462..e42a662 100644 --- a/utils/agent.py +++ b/utils/agent.py @@ -6,31 +6,32 @@ # 列举导入模块 from pathlib import Path from sys import path -from typing import List, Optional, cast +from typing import List, Optional, Union, cast +from typing import TypeVar from uuid import uuid4 +from mistralai.client.models import Op from pydantic_ai import Agent as BaseAgent, AgentRunResult -from pydantic_ai.builtin_tools import AbstractBuiltinTool from pydantic_ai.capabilities import AgentCapability from pydantic_ai.models.openai import OpenAIChatModel +from pydantic_ai.native_tools import AbstractNativeTool from pydantic_ai.output import OutputSpec from pydantic_ai.providers.openai import OpenAIProvider -from pydantic_ai.settings import ModelSettings -from pydantic_core.core_schema import is_subclass_schema from starlette.applications import Starlette from starlette.routing import Mount, Route -from typing_extensions import is_protocol - -from memory import Memory path.append(Path(__file__).resolve().parent.as_posix()) +from memory import Memory + +AgentDepsT = TypeVar("AgentDepsT") +OutputDataT = TypeVar("OutputDataT") class Agent: """ 智能体,支持: - 1)实例智能体 - 2)异步运行 + 1 实例智能体 + 2 异步运行 """ def __init__( @@ -108,23 +109,25 @@ class Agent: def create_web_application( self, - builtin_tools: Optional[List[AbstractBuiltinTool]] = None, + native_tools: Optional[List[AbstractNativeTool]] = None, + html_source: Optional[Union[str, Path]] = None, ) -> Starlette: """ 创建 Starlette 应用,为智能体提供交互式对话界面 - :param builtin_tools: 前端可选工具列表 + :param native_tools: 前端可选工具列表 :return: Starlette 实例 """ from starlette.requests import Request from starlette.responses import JSONResponse, HTMLResponse, Response def api( - self, - builtin_tools: Optional[List[AbstractBuiltinTool]] = None, + agent: BaseAgent[AgentDepsT, OutputDataT], + native_tools: Optional[List[AbstractNativeTool]] = None, ) -> Starlette: """ - 创建 API 应用 - :param builtin_tools: 前端可选工具列表 + 创建处理请求应用 + :param agnet: 智能体 + :param native_tools: 前端可选原生工具列表 :return: Starlette 实例 """ from pydantic_ai.models import Model @@ -136,26 +139,25 @@ class Agent: validate_request_options, ) from pydantic_ai.ui.vercel_ai import VercelAIAdapter - from typing import TypeVar + from pydantic_ai.capabilities import NativeTool - agent_model = cast(Model, self.agent.model) + async def options(request: Request) -> Response: + """处理跨域预检请求""" + return Response() - # 前端可选工具列表 - frontend_builtin_tools = [ + agent_model = cast(Model, agent.model) + # 前端可选原生工具列表 + frontend_native_tools = [ t - for t in (builtin_tools or []) + for t in (native_tools or []) if t.unique_id not in { t.unique_id - for t in self.agent._cap_builtin_tools - if isinstance(t, AbstractBuiltinTool) + for t in agent._cap_native_tools + if isinstance(t, AbstractNativeTool) } ] - async def options_chat(request: Request) -> Response: - """处理跨域预检请求""" - return Response() - async def configurations(request: Request) -> Response: """处理前端模型与工具配置请求""" configurations = ConfigureFrontend( @@ -165,14 +167,14 @@ class Agent: name=agent_model.label, builtin_tools=[ t.unique_id - for t in frontend_builtin_tools - if type(t) in agent_model.supported_builtin_tools() + for t in frontend_native_tools + if type(t) in agent_model.profile.supported_native_tools ], ) - ], # 前端仅可选择智能体配置的模型 + ], # 前端仅可选择智能体已配置的模型 builtin_tools=[ BuiltinToolInfo(id=t.unique_id, name=t.label) - for t in frontend_builtin_tools + for t in frontend_native_tools ], ) return JSONResponse(content=configurations.model_dump(by_alias=True)) @@ -184,14 +186,14 @@ class Agent: TypeVar("AgentDepsT"), TypeVar("OutputDataT") ].from_request(request=request, agent=self.agent) - # 解析请求中额外数据,包括前端选择的模型标识、工具标识和其它配置等 + # 解析请求中额外数据,包括前端选择的模型标识、原生工具标识和其它配置等 extra_data = ChatRequestExtra.model_validate( adapter.run_input.__pydantic_extra__ ) if error := validate_request_options( extra_data=extra_data, - model_ids={agent_model.model_id}, # 前端仅可选择智能体配置的模型 - builtin_tool_ids={t.unique_id for t in frontend_builtin_tools}, + model_ids={agent_model.model_id}, # 前端仅可选择智能体已配置的模型 + builtin_tool_ids={t.unique_id for t in frontend_native_tools}, ): return JSONResponse(content={"error": error}, status_code=400) @@ -200,9 +202,9 @@ class Agent: ].dispatch_request( request=request, agent=self.agent, - builtin_tools=[ - t - for t in frontend_builtin_tools + capabilities=[ + NativeTool(t) + for t in frontend_native_tools if t.unique_id in extra_data.builtin_tools ], ) @@ -214,15 +216,17 @@ class Agent: return Starlette( routes=[ + Route("/chat", options, methods=["OPTIONS"]), Route("/configure", configurations, methods=["GET"]), - Route("/chat", options_chat, methods=["OPTIONS"]), Route("/chat", chat, methods=["POST"]), Route("/health", health, methods=["GET"]), ] ) - async def ui(request: Request) -> Response: - """Serve the chat UI from filesystem cache or CDN.""" + async def index(request: Request) -> Response: + """S处理聊天界面请求""" + from pydantic_ai.ui._web.app import _get_ui_html + content = await _get_ui_html(html_source) return HTMLResponse( @@ -236,14 +240,11 @@ class Agent: routes=[ Mount( "/api", - app=api(self, builtin_tools=builtin_tools), + app=api(agent=self.agent, native_tools=native_tools), ) ] ) - - app.router.add_route("/", ui, methods=["GET"]) - app.router.add_route("/{id}", ui, methods=["GET"]) - - exit() + application.router.add_route("/", index, methods=["GET"]) + application.router.add_route("/{id}", index, methods=["GET"]) return application