更新会话状态、模型定义、订票工作流

This commit is contained in:
liubiren 2026-09-08 20:54:04 +08:00
parent d9622ab6b3
commit f4a26b74e6
3 changed files with 54 additions and 23 deletions

View File

@ -25,7 +25,7 @@ import reflex as rx
from application.states.database import DatabaseState from application.states.database import DatabaseState
from application.states.models import ( from application.states.models import (
AgentRunEvent, AgentRunOutputEvent,
Conversation, Conversation,
ConversationHistoryItem, ConversationHistoryItem,
Message, Message,
@ -461,8 +461,8 @@ class ConversationState(rx.State):
yield # 通知前端更新渲染 yield # 通知前端更新渲染
messages.append(message) messages.append(message)
# ========== 智能体运行事件 ========== # ========== 智能体运行输出事件 ==========
case AgentRunEvent(content=content): case AgentRunOutputEvent(content=content):
# 构建消息实例 # 构建消息实例
message = Message( message = Message(
type=MessageType.TEXT, type=MessageType.TEXT,

View File

@ -11,7 +11,6 @@ from pydantic_ai import RunUsage
from pydantic_ai._uuid import uuid7 from pydantic_ai._uuid import uuid7
class NoResult(BaseModel): class NoResult(BaseModel):
""" """
无结果类 无结果类
@ -19,15 +18,35 @@ class NoResult(BaseModel):
... ...
class AgentRunEvent(BaseModel):
class InteractionType(StrEnum):
""" """
智能体运行事件类 交互类型枚举
"""
INPUT = "input"
class Approval(BaseModel):
"""
审批类
"""
tool_call_id: str = Field(..., description="工具调用唯一标识")
tool_name: str = Field(..., description="工具名称")
interaction_type: InteractionType = Field(..., description="交互类型")
class AgentRunOutputEvent(BaseModel):
"""
智能体运行输出事件类
""" """
content: str = Field( content: str = Field(
default="", default="",
description="智能体运行内容", description="智能体运行内容",
) )
approvals: list[Approval] = Field(default_factory=list, description="审批列表")
class MessageType(StrEnum): class MessageType(StrEnum):

View File

@ -3,9 +3,8 @@
预定航班工作流范式 预定航班工作流范式
""" """
import datetime import datetime
from re import I from typing import Any, AsyncGenerator, cast
from typing import AsyncGenerator, cast, Any
from dataclasses import replace
from pydantic import BaseModel, Field, field_validator from pydantic import BaseModel, Field, field_validator
from pydantic_ai import ( from pydantic_ai import (
Agent, Agent,
@ -18,7 +17,6 @@ from pydantic_ai import (
RunUsage, RunUsage,
UsageLimits, UsageLimits,
) )
from pydantic_ai.agent.abstract import S
from pydantic_ai.messages import ( from pydantic_ai.messages import (
AgentStreamEvent, AgentStreamEvent,
FunctionToolResultEvent, FunctionToolResultEvent,
@ -27,9 +25,13 @@ from pydantic_ai.messages import (
ToolReturnPart, ToolReturnPart,
) )
from pydantic_ai.run import AgentRunResult, AgentRunResultEvent from pydantic_ai.run import AgentRunResult, AgentRunResultEvent
from reflex.event import T
from application.states.models import AgentRunEvent, NoResult from application.states.models import (
AgentRunOutputEvent,
NoResult,
InteractionType,
Approval,
)
from application.workshop.models import ( from application.workshop.models import (
DEEPSEEK_V4_FLASH_MODEL, DEEPSEEK_V4_FLASH_MODEL,
DEEPSEEK_V4_FLASH_MODEL_SETTINGS, DEEPSEEK_V4_FLASH_MODEL_SETTINGS,
@ -204,7 +206,10 @@ async def search_flights(ctx: RunContext[Deps]) -> list[Flight]:
return searched_flights return searched_flights
@agent.tool(name="预定航班") @agent.tool(
name="预定航班",
requires_approval=True,
)
async def book_flight(ctx: RunContext[Deps]) -> Flight | NoResult: async def book_flight(ctx: RunContext[Deps]) -> Flight | NoResult:
""" """
预定航班 预定航班
@ -212,9 +217,6 @@ async def book_flight(ctx: RunContext[Deps]) -> Flight | NoResult:
if (searched_flights := ctx.deps.searched_flights) is None: if (searched_flights := ctx.deps.searched_flights) is None:
raise ModelRetry("必须先使用 search_flights 查询航班") raise ModelRetry("必须先使用 search_flights 查询航班")
if not ctx.tool_call_approved:
raise ApprovalRequired(metadata={"content": "您要预定哪班航班?"})
# 提取到的航班号 # 提取到的航班号
extracted_flight_number = ( extracted_flight_number = (
await extraction_flight_number_agent.run( await extraction_flight_number_agent.run(
@ -282,7 +284,7 @@ async def run_stream_events(
) -> AsyncGenerator[ ) -> AsyncGenerator[
AgentStreamEvent AgentStreamEvent
| AgentRunResultEvent[Flight | NoResult | DeferredToolRequests] | AgentRunResultEvent[Flight | NoResult | DeferredToolRequests]
| AgentRunEvent | AgentRunOutputEvent
| None, | None,
]: ]:
""" """
@ -330,7 +332,6 @@ async def run_stream_events(
event.part.content = ( event.part.content = (
"未提取到航班号,请检查后重试" "未提取到航班号,请检查后重试"
) )
if isinstance(content, Flight): if isinstance(content, Flight):
event.part.content = f"已预定航班:\n{content.number} {content.airfare}$ 于 {content.date.strftime('%Y-%m-%d')}{content.origin_airport_code}{content.destination_airport_code}\n" event.part.content = f"已预定航班:\n{content.number} {content.airfare}$ 于 {content.date.strftime('%Y-%m-%d')}{content.origin_airport_code}{content.destination_airport_code}\n"
yield event yield event
@ -341,9 +342,20 @@ async def run_stream_events(
match result: match result:
case AgentRunResult(output=output): case AgentRunResult(output=output):
match output: match output:
case Flight(): case Flight() | NoResult():
yield AgentRunEvent(content="预定成功") yield event
case DeferredToolRequests(approvals=approvals) as t: case DeferredToolRequests(approvals=approvals):
t.metadata = {"1": {"Success": "1"}} yield AgentRunOutputEvent(
content="请输入航班号",
approvals=[
Approval(
tool_call_id=approval.tool_call_id,
tool_name=approval.tool_name,
interaction_type=InteractionType.INPUT,
)
for approval in approvals
if approval.tool_name == "预定航班"
],
)
yield event yield event