diff --git a/agent/application/workshop/bank_customer_service.py b/agent/application/workshop/bank_customer_service.py index a4dc955..6ff2c04 100644 --- a/agent/application/workshop/bank_customer_service.py +++ b/agent/application/workshop/bank_customer_service.py @@ -4,6 +4,7 @@ """ from typing import Any, AsyncGenerator +from asyncpg import Pool from pydantic import BaseModel, Field from pydantic_ai import ( Agent, @@ -14,21 +15,13 @@ from pydantic_ai import ( RunUsage, UsageLimits, ) -from pydantic_ai.messages import ( - AgentStreamEvent, - PartStartEvent, - ToolCallPart, - FunctionToolResultEvent, - ToolReturnPart, -) -from pydantic_ai.run import AgentRunResultEvent, AgentRunResult +from pydantic_ai.messages import AgentStreamEvent +from pydantic_ai.run import AgentRunResultEvent from application.workshop.models import ( DEEPSEEK_V4_FLASH_MODEL, DEEPSEEK_V4_FLASH_MODEL_SETTINGS, ) -from asyncpg import Pool -from application.workshop.events import AgentRuntimeEvent class Deps(BaseModel): @@ -42,14 +35,6 @@ class Deps(BaseModel): connection_pool: Pool = Field(..., description="连接池") -class Output(BaseModel): - """ - 输出类 - """ - - response: str = Field(..., description="客服应答") - - # 账户上下文能力 account_context = Capability[Deps]( id="account-context", @@ -89,15 +74,61 @@ async def query_account_balance(ctx: RunContext[Deps]) -> str: # 智能体 -agent = Agent[Deps, Output]( +agent = Agent[Deps, str]( model=DEEPSEEK_V4_FLASH_MODEL, model_settings=DEEPSEEK_V4_FLASH_MODEL_SETTINGS, deps_type=Deps, - output_type=Output, - instructions="你是我方银行的客服智能体,为客户提供客服应答。", + output_type=str, # 若输出类型为 str,则智能体输出结果时不进行输出类型校验。若定义输出类型,需考虑处理相应事件 + instructions="你是我方银行的客服智能体,为客户提供客服应答。", # 优先使用 instructions capabilities=[account_context], ) +""" +此为设置输出类型为 Output,智能体输出结果时需校验输出类型,同工具调用: +PartStartEvent(index=0, part=ToolCallPart(tool_name='final_result', args='', tool_call_id='call_3ab0ed20b1114fa0be726723')) +FinalResultEvent(tool_name='final_result', tool_call_id='call_3ab0ed20b1114fa0be726723') +PartDeltaEvent(index=0, delta=ToolCallPartDelta(args_delta='', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent(index=0, delta=ToolCallPartDelta(args_delta='{', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent (index=0, delta=ToolCallPartDelta (args_delta='"response": " 您好 ', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent (index=0, delta=ToolCallPartDelta (args_delta=',刘 ', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent (index=0, delta=ToolCallPartDelta (args_delta=' 弼仁 ', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent (index=0, delta=ToolCallPartDelta (args_delta=' 先生。', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent (index=0, delta=ToolCallPartDelta (args_delta=' 您账户 ', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent (index=0, delta=ToolCallPartDelta (args_delta=' 的 ', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent (index=0, delta=ToolCallPartDelta (args_delta=' 当前余额 ', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent (index=0, delta=ToolCallPartDelta (args_delta=' 为 **', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent(index=0, delta=ToolCallPartDelta(args_delta='9.', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent (index=0, delta=ToolCallPartDelta (args_delta='99 元 ', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent(index=0, delta=ToolCallPartDelta(args_delta='**。', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent (index=0, delta=ToolCallPartDelta (args_delta=' 请问还有什么 ', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent (index=0, delta=ToolCallPartDelta (args_delta=' 可以帮 ', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent (index=0, delta=ToolCallPartDelta (args_delta=' 您的 ', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartDeltaEvent (index=0, delta=ToolCallPartDelta (args_delta=' 吗?"}', tool_call_id='call_3ab0ed20b1114fa0be726723')) +PartEndEvent (index=0, part=ToolCallPart (tool_name='final_result', args='{"response": " 您好,刘弼仁先生。您账户的当前余额为 **9.99 元**。请问还有什么可以帮您的吗?"}', tool_call_id='call_3ab0ed20b1114fa0be726723')) +OutputToolCallEvent (part=ToolCallPart (tool_name='final_result', args='{"response": " 您好,刘弼仁先生。您账户的当前余额为 **9.99 元**。请问还有什么可以帮您的吗?"}', tool_call_id='call_3ab0ed20b1114fa0be726723'), args_valid=True) +OutputToolResultEvent(part=ToolReturnPart(tool_name='final_result', content='Final result processed.', tool_call_id='call_3ab0ed20b1114fa0be726723', timestamp=datetime.datetime(2026, 9, 17, 10, 34, 0, 799329, tzinfo=datetime.timezone.utc))) + +此为设置输出类型为 str,智能体输出结果时不进行输出类型校验: +PartStartEvent(index=0, part=TextPart(content='您好')) +FinalResultEvent(tool_name=None, tool_call_id=None) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta=',刘')) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='弼仁')) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='先生。')) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='您账户')) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='的')) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='当前余额')) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='为 **')) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='9.')) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='99')) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='元**')) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='。请问')) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='还有什么')) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='可以帮')) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='您的吗')) +PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='?')) +PartEndEvent(index=0, part=TextPart(content='您好,刘弼仁先生。您账户的当前余额为 **9.99元**。请问还有什么可以帮您的吗?')) +""" + async def run_stream_events( deps: Any, @@ -106,7 +137,7 @@ async def run_stream_events( usage: RunUsage, usage_limits: UsageLimits | None = None, deferred_tool_results: DeferredToolResults | None = None, -) -> AsyncGenerator[AgentStreamEvent | AgentRunResultEvent[Output] | None,]: +) -> AsyncGenerator[AgentStreamEvent | AgentRunResultEvent[str] | None,]: """ 运行并流式输出事件 """ @@ -122,28 +153,5 @@ async def run_stream_events( deferred_tool_results=deferred_tool_results, ) as events: async for event in events: - match event: - case PartStartEvent( - part=part, - ): - match part: - case ToolCallPart(tool_name=tool_name): - if tool_name.startswith("final_result"): - continue - - case FunctionToolResultEvent(part): - match part: - case ToolReturnPart( - tool_name=tool_name, - ): - if tool_name.startswith("final_result"): - continue - - case AgentRunResultEvent(result=result): - match result: - case AgentRunResult(output=output): - match output: - case Output(response=response): - yield AgentRuntimeEvent(content=response) - + print(event) yield event diff --git a/agent/database.db b/agent/database.db index c83cc25..4df905a 100644 Binary files a/agent/database.db and b/agent/database.db differ