This commit is contained in:
parent
2502d2f663
commit
a8dc684c20
|
|
@ -370,14 +370,12 @@ def thinking(item: MessageHistoryItem) -> rx.Component:
|
||||||
rx.text(
|
rx.text(
|
||||||
item.title,
|
item.title,
|
||||||
font_size="var(--prismui-font-size-1)",
|
font_size="var(--prismui-font-size-1)",
|
||||||
color="var(--prismui-color-3)",
|
|
||||||
class_name=rx.cond(item.is_running, "is_running", None),
|
class_name=rx.cond(item.is_running, "is_running", None),
|
||||||
),
|
),
|
||||||
rx.icon(
|
rx.icon(
|
||||||
"chevron-right",
|
"chevron-right",
|
||||||
width="14px",
|
width="14px",
|
||||||
height="14px",
|
height="14px",
|
||||||
color="var(--prismui-color-3)",
|
|
||||||
transform=rx.cond(item.is_shown, "rotate(90deg)", "rotate(0deg)"),
|
transform=rx.cond(item.is_shown, "rotate(90deg)", "rotate(0deg)"),
|
||||||
transition="transform 0.18s ease-in-out",
|
transition="transform 0.18s ease-in-out",
|
||||||
),
|
),
|
||||||
|
|
@ -442,57 +440,102 @@ def tool_call(item: MessageHistoryItem) -> rx.Component:
|
||||||
margin_bottom="8px",
|
margin_bottom="8px",
|
||||||
line_height="22px",
|
line_height="22px",
|
||||||
),
|
),
|
||||||
# 内容
|
rx.hstack(
|
||||||
rx.markdown(
|
# 分割线
|
||||||
item.content,
|
rx.box(
|
||||||
width="100%",
|
width="1px",
|
||||||
margin="4px 0",
|
margin="12px 7px",
|
||||||
line_height="1.6",
|
background_color="var(--prismui-background-color-2)",
|
||||||
font_size="var(--prismui-font-size-1)",
|
),
|
||||||
),
|
rx.vstack(
|
||||||
# 审批
|
# 内容
|
||||||
rx.cond(
|
rx.markdown(
|
||||||
item.has_approval,
|
item.content,
|
||||||
rx.hstack(
|
width="100%",
|
||||||
rx.text_area(
|
margin="4px 0",
|
||||||
placeholder="请输入",
|
line_height="1.6",
|
||||||
# 值绑定审批用户提示词
|
font_size="var(--prismui-font-size-1)",
|
||||||
value=item.approval_user_prompt,
|
|
||||||
# 值变化事件:设置审批用户提示词
|
|
||||||
on_change=lambda user_prompt: ConversationState.set_approval_user_prompt(
|
|
||||||
item.id, user_prompt
|
|
||||||
),
|
|
||||||
flex=1,
|
|
||||||
height="100%",
|
|
||||||
padding="4px",
|
|
||||||
border_radius="var(--prismui-border-radius-4)",
|
|
||||||
line_height="16px",
|
|
||||||
border="none !important",
|
|
||||||
),
|
),
|
||||||
rx.button(
|
# 审批
|
||||||
"发送",
|
rx.cond(
|
||||||
# 点击事件:审批
|
item.has_approval,
|
||||||
on_click=lambda: ConversationState.approve(item.id, True),
|
rx.vstack(
|
||||||
# 是否禁用绑定验证码发送禁用状态
|
rx.text_area(
|
||||||
margin="0 8px",
|
# 值绑定审批用户提示词
|
||||||
background_color="var(--prismui-background-color-1)",
|
value=item.approval_user_prompt,
|
||||||
line_height="16px",
|
# 值变化事件:设置审批用户提示词
|
||||||
# 若验证码发送禁用状态为是则颜色设置为 color-4,否则设置为 color-5(主题色)
|
on_change=lambda user_prompt: ConversationState.set_approval_user_prompt(
|
||||||
color=rx.cond(
|
item.id, user_prompt
|
||||||
AuthState.is_captcha_code_sending_button_disabled,
|
),
|
||||||
"var(--prismui-color-4)",
|
disabled=item.is_approval_user_prompt_input_disabled,
|
||||||
"var(--prismui-color-5)",
|
placeholder="请输入",
|
||||||
|
vertical_align="middle",
|
||||||
|
width="100%",
|
||||||
|
height="auto",
|
||||||
|
padding="4px 0",
|
||||||
|
outline="none !important",
|
||||||
|
box_shadow="none !important",
|
||||||
|
style={
|
||||||
|
".rt-TextAreaInput": {
|
||||||
|
"font-size": "var(--prismui-font-size-1) !important",
|
||||||
|
"border": "none !important",
|
||||||
|
"overflow-y": "hidden !important",
|
||||||
|
},
|
||||||
|
".rt-TextAreaInput:disabled": {
|
||||||
|
"background-color": "var(--prismui-background-color-1) !important",
|
||||||
|
"font-size": "var(--prismui-font-size-1) !important",
|
||||||
|
"cursor": "not-allowed !important",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
rx.hstack(
|
||||||
|
rx.button(
|
||||||
|
rx.cond(
|
||||||
|
item.is_approval_user_prompt_input_disabled,
|
||||||
|
"已提交",
|
||||||
|
"提交",
|
||||||
|
),
|
||||||
|
# 点击事件:审批
|
||||||
|
on_click=lambda: ConversationState.approve(item.id),
|
||||||
|
disabled=item.is_approval_user_prompt_input_disabled,
|
||||||
|
padding="0 12px",
|
||||||
|
# 是否禁用绑定审批用户提示词不可输出状态
|
||||||
|
background_color=rx.cond(
|
||||||
|
item.is_approval_user_prompt_input_disabled,
|
||||||
|
"var(--prismui-background-color-8)",
|
||||||
|
"var(--prismui-background-color-7)",
|
||||||
|
),
|
||||||
|
border_radius="var(--prismui-border-radius-3)",
|
||||||
|
line_height="18px",
|
||||||
|
font_size="var(--prismui-font-size-1)",
|
||||||
|
color="var(--prismui-color-9)",
|
||||||
|
cursor=rx.cond(
|
||||||
|
item.is_approval_user_prompt_input_disabled,
|
||||||
|
"not-allowed",
|
||||||
|
"pointer",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
justify_content="flex-end",
|
||||||
|
width="100%",
|
||||||
|
),
|
||||||
|
width="100%",
|
||||||
|
padding="12px 16px",
|
||||||
|
background_color="var(--prismui-background-color-1)",
|
||||||
|
border="var(--prismui-border-1)",
|
||||||
|
border_radius="var(--prismui-border-radius-4)",
|
||||||
),
|
),
|
||||||
|
rx.fragment(),
|
||||||
),
|
),
|
||||||
width="100%",
|
width="100%",
|
||||||
height="45px",
|
gap="4px",
|
||||||
align_items="center",
|
|
||||||
border="var(--prismui-border-1)",
|
|
||||||
border_radius="var(--prismui-border-radius-4)",
|
|
||||||
),
|
),
|
||||||
rx.fragment(),
|
align_items="stretch",
|
||||||
|
width="100%",
|
||||||
|
margin_bottom="8px",
|
||||||
|
gap="4px",
|
||||||
),
|
),
|
||||||
width="100%",
|
width="100%",
|
||||||
|
margin_bottom="8px",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -828,17 +871,16 @@ def user_prompt_sending() -> rx.Component:
|
||||||
inline_height="1.5",
|
inline_height="1.5",
|
||||||
font_size="var(--prismui-font-size-2)",
|
font_size="var(--prismui-font-size-2)",
|
||||||
white_space="nowrap",
|
white_space="nowrap",
|
||||||
overflow="hidden",
|
|
||||||
cursor=rx.cond(
|
cursor=rx.cond(
|
||||||
ConversationState.is_user_prompt_sending_button_disabled,
|
ConversationState.is_user_prompt_sending_button_disabled,
|
||||||
"not-allowed",
|
"not-allowed",
|
||||||
"pointer",
|
"pointer",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
width="100%",
|
|
||||||
justify_content="flex-end",
|
justify_content="flex-end",
|
||||||
align_items="center",
|
align_items="center",
|
||||||
height="32px",
|
height="32px",
|
||||||
|
width="100%",
|
||||||
),
|
),
|
||||||
width="100%",
|
width="100%",
|
||||||
padding="12px 16px",
|
padding="12px 16px",
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,9 @@
|
||||||
会话状态
|
会话状态
|
||||||
"""
|
"""
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import AsyncGenerator, cast
|
from typing import AsyncGenerator
|
||||||
|
|
||||||
from pydantic_ai import (
|
from pydantic_ai import DeferredToolRequests, DeferredToolResults, ToolApproved
|
||||||
DeferredToolRequests,
|
|
||||||
DeferredToolResults,
|
|
||||||
ToolApproved,
|
|
||||||
ToolDenied,
|
|
||||||
)
|
|
||||||
from pydantic_ai.messages import (
|
from pydantic_ai.messages import (
|
||||||
FunctionToolResultEvent,
|
FunctionToolResultEvent,
|
||||||
PartDeltaEvent,
|
PartDeltaEvent,
|
||||||
|
|
@ -110,6 +105,7 @@ class ConversationState(rx.State):
|
||||||
)
|
)
|
||||||
# 将最后一个会话的唯一标识作为激活会话唯一标识
|
# 将最后一个会话的唯一标识作为激活会话唯一标识
|
||||||
self.actived_conversation_id = next(reversed(self.conversations.keys()))
|
self.actived_conversation_id = next(reversed(self.conversations.keys()))
|
||||||
|
print(self.conversations[self.actived_conversation_id])
|
||||||
|
|
||||||
@rx.event
|
@rx.event
|
||||||
def toggle_conversation_history_shown(self) -> None:
|
def toggle_conversation_history_shown(self) -> None:
|
||||||
|
|
@ -193,6 +189,11 @@ class ConversationState(rx.State):
|
||||||
**message.model_dump(),
|
**message.model_dump(),
|
||||||
has_approval=isinstance(approval := message.approval, Approval),
|
has_approval=isinstance(approval := message.approval, Approval),
|
||||||
approval_user_prompt=getattr(approval, "user_prompt", ""),
|
approval_user_prompt=getattr(approval, "user_prompt", ""),
|
||||||
|
is_approval_user_prompt_input_disabled=(
|
||||||
|
False
|
||||||
|
if (isinstance(approval, Approval) and approval.result is None)
|
||||||
|
else True
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return message_history
|
return message_history
|
||||||
|
|
@ -273,10 +274,6 @@ class ConversationState(rx.State):
|
||||||
if not (user_prompt := approval.user_prompt):
|
if not (user_prompt := approval.user_prompt):
|
||||||
return
|
return
|
||||||
|
|
||||||
# 将等待流式输出设置为是
|
|
||||||
conversation.awaiting_stream = True
|
|
||||||
yield # 通知前端更新渲染
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# 若用户提示词为空则直接返回
|
# 若用户提示词为空则直接返回
|
||||||
if not (user_prompt := conversation.user_prompt):
|
if not (user_prompt := conversation.user_prompt):
|
||||||
|
|
@ -368,19 +365,23 @@ class ConversationState(rx.State):
|
||||||
case ToolCallPart(
|
case ToolCallPart(
|
||||||
tool_call_id=tool_call_id, tool_name=tool_name
|
tool_call_id=tool_call_id, tool_name=tool_name
|
||||||
):
|
):
|
||||||
# 构建消息实例
|
if (
|
||||||
message = Message(
|
|
||||||
type=MessageType.TOOL_CALL,
|
|
||||||
title=f"正在{tool_name}",
|
|
||||||
is_running=True,
|
|
||||||
)
|
|
||||||
# 添加至消息字典
|
|
||||||
conversation.messages[message.id] = message
|
|
||||||
# 将消息实例唯一标识与工具调用唯一标识映射
|
|
||||||
conversation.workflow.tool_call_id_map_to_message_id[
|
|
||||||
tool_call_id
|
tool_call_id
|
||||||
] = message.id
|
not in conversation.workflow.tool_call_id_map_to_message_id
|
||||||
yield # 通知前端更新渲染
|
):
|
||||||
|
# 构建消息实例
|
||||||
|
message = Message(
|
||||||
|
type=MessageType.TOOL_CALL,
|
||||||
|
title=f"正在{tool_name}",
|
||||||
|
is_running=True,
|
||||||
|
)
|
||||||
|
# 添加至消息字典
|
||||||
|
conversation.messages[message.id] = message
|
||||||
|
# 将消息实例唯一标识与工具调用唯一标识映射
|
||||||
|
conversation.workflow.tool_call_id_map_to_message_id[
|
||||||
|
tool_call_id
|
||||||
|
] = message.id
|
||||||
|
yield # 通知前端更新渲染
|
||||||
|
|
||||||
# 文本分片
|
# 文本分片
|
||||||
case TextPart(content=content):
|
case TextPart(content=content):
|
||||||
|
|
@ -458,8 +459,7 @@ class ConversationState(rx.State):
|
||||||
]
|
]
|
||||||
message.is_running = False
|
message.is_running = False
|
||||||
message.title = f"{tool_name}已完成"
|
message.title = f"{tool_name}已完成"
|
||||||
# 若内容非空字符串则更新
|
if isinstance(content, str) and content:
|
||||||
if content := message.content:
|
|
||||||
message.content = content
|
message.content = content
|
||||||
yield # 通知前端更新渲染
|
yield # 通知前端更新渲染
|
||||||
messages.append(message)
|
messages.append(message)
|
||||||
|
|
@ -510,6 +510,7 @@ class ConversationState(rx.State):
|
||||||
conversation_id=conversation.id,
|
conversation_id=conversation.id,
|
||||||
new_messages=result.new_messages(),
|
new_messages=result.new_messages(),
|
||||||
)
|
)
|
||||||
|
|
||||||
# 批量创建消息记录
|
# 批量创建消息记录
|
||||||
await db_state.create_message_records(
|
await db_state.create_message_records(
|
||||||
conversation_id=conversation.id,
|
conversation_id=conversation.id,
|
||||||
|
|
@ -569,11 +570,10 @@ class ConversationState(rx.State):
|
||||||
message.approval.user_prompt = user_prompt
|
message.approval.user_prompt = user_prompt
|
||||||
|
|
||||||
@rx.event
|
@rx.event
|
||||||
async def approve(self, item_id: str, result: bool) -> None:
|
async def approve(self, item_id: str) -> AsyncGenerator[None, None]:
|
||||||
"""
|
"""
|
||||||
审批消息历史项
|
审批消息历史项
|
||||||
:param item_id: 消息历史项唯一标识
|
:param item_id: 消息历史项唯一标识
|
||||||
:param result: 审批结果(True 表示审批通过,False 表示审批拒绝)
|
|
||||||
"""
|
"""
|
||||||
# 当前会话
|
# 当前会话
|
||||||
conversation = self.conversations.get(self.actived_conversation_id)
|
conversation = self.conversations.get(self.actived_conversation_id)
|
||||||
|
|
@ -585,16 +585,19 @@ class ConversationState(rx.State):
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
# 更新审批结果
|
# 若会话未正在运行则将正在运行设置为是
|
||||||
approval.result = result
|
if not conversation.is_running:
|
||||||
|
conversation.is_running = True
|
||||||
|
# 将等待流式输出设置为是
|
||||||
|
conversation.awaiting_stream = True
|
||||||
|
# 更新审批结果为审批通过
|
||||||
|
approval.result = True
|
||||||
|
yield # 通知前端更新渲染
|
||||||
|
|
||||||
# 运行
|
# 运行
|
||||||
async for _ in self.run(
|
async for _ in self.run(
|
||||||
approval,
|
approval,
|
||||||
DeferredToolResults(
|
DeferredToolResults(approvals={approval.tool_call_id: ToolApproved()}),
|
||||||
approvals={
|
|
||||||
approval.tool_call_id: ToolApproved() if result else ToolDenied()
|
|
||||||
}
|
|
||||||
),
|
|
||||||
):
|
):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,9 @@ class MessageHistoryItem(Message):
|
||||||
|
|
||||||
has_approval: bool = Field(default=False, description="包含审批实例")
|
has_approval: bool = Field(default=False, description="包含审批实例")
|
||||||
approval_user_prompt: str = Field(default="", description="审批用户提示词")
|
approval_user_prompt: str = Field(default="", description="审批用户提示词")
|
||||||
|
is_approval_user_prompt_input_disabled: bool = Field(
|
||||||
|
default=False, description="审批用户提示词不可输出状态"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# 工作流适配器
|
# 工作流适配器
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ from typing import Any, AsyncGenerator, cast
|
||||||
from pydantic import BaseModel, Field, field_validator
|
from pydantic import BaseModel, Field, field_validator
|
||||||
from pydantic_ai import (
|
from pydantic_ai import (
|
||||||
Agent,
|
Agent,
|
||||||
|
AgentRunResult,
|
||||||
ApprovalRequired,
|
ApprovalRequired,
|
||||||
DeferredToolRequests,
|
DeferredToolRequests,
|
||||||
DeferredToolResults,
|
DeferredToolResults,
|
||||||
|
|
@ -16,11 +17,8 @@ from pydantic_ai import (
|
||||||
RunContext,
|
RunContext,
|
||||||
RunUsage,
|
RunUsage,
|
||||||
UsageLimits,
|
UsageLimits,
|
||||||
AgentRunResult,
|
|
||||||
)
|
)
|
||||||
from pydantic_ai.messages import (
|
from pydantic_ai.messages import (
|
||||||
PartDeltaEvent,
|
|
||||||
TextPart,
|
|
||||||
AgentStreamEvent,
|
AgentStreamEvent,
|
||||||
FunctionToolResultEvent,
|
FunctionToolResultEvent,
|
||||||
PartStartEvent,
|
PartStartEvent,
|
||||||
|
|
@ -29,12 +27,11 @@ from pydantic_ai.messages import (
|
||||||
)
|
)
|
||||||
from pydantic_ai.run import AgentRunResultEvent
|
from pydantic_ai.run import AgentRunResultEvent
|
||||||
|
|
||||||
from application.states.models import NoResult
|
from application.workshop.events import AgentPromptEvent
|
||||||
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,
|
||||||
)
|
)
|
||||||
from application.workshop.events import AgentPromptEvent
|
|
||||||
|
|
||||||
|
|
||||||
class Flight(BaseModel):
|
class Flight(BaseModel):
|
||||||
|
|
@ -76,15 +73,15 @@ class Deps(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
# 主智能体
|
# 主智能体
|
||||||
agent = Agent[Deps, Flight | NoResult | DeferredToolRequests](
|
agent = Agent[Deps, Flight | DeferredToolRequests](
|
||||||
model=DEEPSEEK_V4_FLASH_MODEL,
|
model=DEEPSEEK_V4_FLASH_MODEL,
|
||||||
model_settings=DEEPSEEK_V4_FLASH_MODEL_SETTINGS,
|
model_settings=DEEPSEEK_V4_FLASH_MODEL_SETTINGS,
|
||||||
deps_type=Deps,
|
deps_type=Deps,
|
||||||
output_type=Flight | NoResult | DeferredToolRequests,
|
output_type=Flight | DeferredToolRequests,
|
||||||
system_prompt=(
|
system_prompt=(
|
||||||
"你的任务是帮助用户查询并预定航班,**必须按照下述步骤执行**:",
|
"你的任务是帮助用户查询并预定航班,**必须按照下述步骤执行**:",
|
||||||
"1. 使用 search_flights 查询满足用户需求的航班;",
|
"1. 使用 search_flights 查询满足用户需求的航班;",
|
||||||
"2. 使用 book_flight 预定航班。若未选择到航班则返回 NoSelectedFlight;",
|
"2. 使用 book_flight 预定航班。当返回航班信息(Flight)时表示预定航班完成。",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -209,11 +206,11 @@ async def search_flights(ctx: RunContext[Deps]) -> list[Flight]:
|
||||||
|
|
||||||
|
|
||||||
@agent.tool(name="预定航班")
|
@agent.tool(name="预定航班")
|
||||||
async def book_flight(ctx: RunContext[Deps]) -> Flight | NoResult:
|
async def book_flight(ctx: RunContext[Deps]) -> Flight:
|
||||||
"""
|
"""
|
||||||
预定航班
|
预定航班
|
||||||
"""
|
"""
|
||||||
if ctx.deps.booked_flight:
|
if ctx.deps.booked_flight is not None:
|
||||||
return ctx.deps.booked_flight
|
return ctx.deps.booked_flight
|
||||||
|
|
||||||
if (searched_flights := ctx.deps.searched_flights) is None:
|
if (searched_flights := ctx.deps.searched_flights) is None:
|
||||||
|
|
@ -232,12 +229,16 @@ async def book_flight(ctx: RunContext[Deps]) -> Flight | NoResult:
|
||||||
)
|
)
|
||||||
).output
|
).output
|
||||||
if not extracted_flight_number:
|
if not extracted_flight_number:
|
||||||
return NoResult()
|
raise ApprovalRequired(
|
||||||
|
metadata={
|
||||||
|
"content": f"未提取到航班号。请确认后重新输入。",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if extracted_flight_number not in flight_numbers:
|
if extracted_flight_number not in flight_numbers:
|
||||||
raise ApprovalRequired(
|
raise ApprovalRequired(
|
||||||
metadata={
|
metadata={
|
||||||
"content": f"提取到的航班号 {extracted_flight_number} 不在查询到的航班中。请确认后重新输入。"
|
"content": f"提取到的航班号 {extracted_flight_number} 不在查询到的航班中。请确认后重新输入。",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
# 预定到的航班
|
# 预定到的航班
|
||||||
|
|
@ -252,12 +253,12 @@ async def book_flight(ctx: RunContext[Deps]) -> Flight | NoResult:
|
||||||
@agent.output_validator
|
@agent.output_validator
|
||||||
async def validate_output(
|
async def validate_output(
|
||||||
ctx: RunContext[Deps],
|
ctx: RunContext[Deps],
|
||||||
output: Flight | NoResult | DeferredToolRequests,
|
output: Flight | DeferredToolRequests,
|
||||||
) -> Flight | NoResult | DeferredToolRequests:
|
) -> Flight | DeferredToolRequests:
|
||||||
"""
|
"""
|
||||||
输出校验
|
输出校验
|
||||||
"""
|
"""
|
||||||
if isinstance(output, (NoResult, DeferredToolRequests)):
|
if isinstance(output, DeferredToolRequests):
|
||||||
return output
|
return output
|
||||||
|
|
||||||
errors = []
|
errors = []
|
||||||
|
|
@ -291,13 +292,14 @@ async def run_stream_events(
|
||||||
usage_limits: UsageLimits | None = None,
|
usage_limits: UsageLimits | None = None,
|
||||||
deferred_tool_results: DeferredToolResults | None = None,
|
deferred_tool_results: DeferredToolResults | None = None,
|
||||||
) -> AsyncGenerator[
|
) -> AsyncGenerator[
|
||||||
AgentStreamEvent
|
AgentStreamEvent | AgentRunResultEvent[Flight | DeferredToolRequests] | None,
|
||||||
| AgentRunResultEvent[Flight | NoResult | DeferredToolRequests]
|
|
||||||
| None,
|
|
||||||
]:
|
]:
|
||||||
"""
|
"""
|
||||||
运行并流式输出事件
|
运行并流式输出事件
|
||||||
"""
|
"""
|
||||||
|
if not isinstance(deps, Deps):
|
||||||
|
deps = Deps.model_validate(deps)
|
||||||
|
|
||||||
async with agent.run_stream_events(
|
async with agent.run_stream_events(
|
||||||
user_prompt=user_prompt,
|
user_prompt=user_prompt,
|
||||||
deps=deps,
|
deps=deps,
|
||||||
|
|
@ -330,12 +332,14 @@ async def run_stream_events(
|
||||||
searched_flights = cast(list[Flight], content)
|
searched_flights = cast(list[Flight], content)
|
||||||
event.part.content = f"已查询到 **{len(searched_flights)}** 班航班:\n\n"
|
event.part.content = f"已查询到 **{len(searched_flights)}** 班航班:\n\n"
|
||||||
for searched_flight in searched_flights:
|
for searched_flight in searched_flights:
|
||||||
event.part.content += f"{searched_flight.number} {searched_flight.airfare}$ 于 {searched_flight.date.strftime('%Y-%m-%d')} 从 {searched_flight.origin_airport_code} 到 {searched_flight.destination_airport_code}\n\n"
|
event.part.content += f"**{searched_flight.number}** | 💰 {searched_flight.airfare} | {searched_flight.date.strftime('%Y-%m-%d')} | {searched_flight.origin_airport_code} ✈️ {searched_flight.destination_airport_code}\n\n"
|
||||||
yield event
|
yield event
|
||||||
|
|
||||||
case "预定航班":
|
case "预定航班":
|
||||||
if isinstance(deps.booked_flight, Flight):
|
if isinstance(deps.booked_flight, Flight):
|
||||||
event.part.content = ""
|
event.part.content = (
|
||||||
|
"请输入航班号:\n\n" # 成功预定内容维持提示
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
event.part.content = (
|
event.part.content = (
|
||||||
"未提取到航班号,请检查后重试\n\n"
|
"未提取到航班号,请检查后重试\n\n"
|
||||||
|
|
@ -348,10 +352,6 @@ async def run_stream_events(
|
||||||
match output:
|
match output:
|
||||||
case Flight():
|
case Flight():
|
||||||
yield AgentPromptEvent(
|
yield AgentPromptEvent(
|
||||||
content=f"已成功预定:\n\n{output.number} {output.airfare}$ 于 {output.date.strftime('%Y-%m-%d')} 从 {output.origin_airport_code} 到 {output.destination_airport_code}\n\n本次会话结束。"
|
content=f"---\n\n✅ 预定机票成功:\n\n{output.number} | 💰 {output.airfare} | {output.date.strftime('%Y-%m-%d')} | {output.origin_airport_code} ✈️ {output.destination_airport_code}\n\n本次会话结束。"
|
||||||
)
|
|
||||||
case NoResult():
|
|
||||||
yield AgentPromptEvent(
|
|
||||||
content="预定失败\n\n本次会话结束。"
|
|
||||||
)
|
)
|
||||||
yield event
|
yield event
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
--prismui-background-color-5: #ffffff33;
|
--prismui-background-color-5: #ffffff33;
|
||||||
--prismui-background-color-6: #f2f2f3;
|
--prismui-background-color-6: #f2f2f3;
|
||||||
--prismui-background-color-7: #5e7ce0;
|
--prismui-background-color-7: #5e7ce0;
|
||||||
|
--prismui-background-color-8: #beccfa;
|
||||||
--prismui-background-1: linear-gradient(to bottom, #D0C9FF 0%, #E6D6F0 8%, #F1DBEA 12%, #C8DCFB 40%, #ABC6F6 60%, #87AEFE 90%);
|
--prismui-background-1: linear-gradient(to bottom, #D0C9FF 0%, #E6D6F0 8%, #F1DBEA 12%, #C8DCFB 40%, #ABC6F6 60%, #87AEFE 90%);
|
||||||
--prismui-background-2: linear-gradient(180deg, #fffffff2, #f8fafff2 99%);
|
--prismui-background-2: linear-gradient(180deg, #fffffff2, #f8fafff2 99%);
|
||||||
--prismui-background-3: linear-gradient(to right, #f3efff, #f3efff33, #e2f1fd33, #e2f1fd);
|
--prismui-background-3: linear-gradient(to right, #f3efff, #f3efff33, #e2f1fd33, #e2f1fd);
|
||||||
|
|
@ -90,11 +91,11 @@ pre, pre code {
|
||||||
/* 使用主题变量:普通文字色 --prismui-color-3,高光使用主题蓝色 --prismui-color-5 */
|
/* 使用主题变量:普通文字色 --prismui-color-3,高光使用主题蓝色 --prismui-color-5 */
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
90deg,
|
90deg,
|
||||||
var(--prismui-color-3) 0%,
|
var(--prismui-color-1) 0%,
|
||||||
var(--prismui-color-3) 35%,
|
var(--prismui-color-1) 35%,
|
||||||
var(--prismui-color-7) 50%,
|
var(--prismui-color-3) 50%,
|
||||||
var(--prismui-color-3) 65%,
|
var(--prismui-color-1) 65%,
|
||||||
var(--prismui-color-3) 100%
|
var(--prismui-color-1) 100%
|
||||||
);
|
);
|
||||||
background-size: 200% 100%;
|
background-size: 200% 100%;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue