From 55aa7e30e921b1f670d583b29734cad7590c402c Mon Sep 17 00:00:00 2001 From: liubiren Date: Mon, 10 Aug 2026 19:33:08 +0800 Subject: [PATCH] 1 --- agent/application/pages/__init__.py | 6 +- agent/application/pages/conversation.py | 105 +++++++++++----------- agent/application/pages/index.py | 8 +- agent/application/pages/knowledge_base.py | 2 +- agent/application/states/conversation.py | 44 ++++++--- agent/application/states/models.py | 8 +- agent/application/workshop/book_flight.py | 11 +-- 7 files changed, 102 insertions(+), 82 deletions(-) diff --git a/agent/application/pages/__init__.py b/agent/application/pages/__init__.py index a7471d0..2c3cd2c 100644 --- a/agent/application/pages/__init__.py +++ b/agent/application/pages/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from application.pages.conversation import conversation -from application.pages.knowledge_base import knowledge_base +from application.pages.conversation import conversation_page +from application.pages.knowledge_base import knowledge_base_page -__all__ = ["conversation", "knowledge_base"] +__all__ = ["conversation_page", "knowledge_base_page"] diff --git a/agent/application/pages/conversation.py b/agent/application/pages/conversation.py index 47d1023..7f0fddc 100644 --- a/agent/application/pages/conversation.py +++ b/agent/application/pages/conversation.py @@ -9,32 +9,32 @@ from application.states.models import ( Conversation, Dialog, Thought, + ConversationHistoryItem, ) from application.states import ConversationState, AuthState def conversation_history_item( - item: Tuple[str, Conversation], + item: ConversationHistoryItem, ) -> rx.Component: """ 会话历史项 :param item: 会话历史项 :return: Component """ - conversation = item[1] - # 高亮:若为当前会话或显示更多则高亮 - highlight: bool = ( - conversation.id - == ConversationState.is_conversation_history_item_more_button_shown - ) | (conversation.id == ConversationState.conversation_id) + # 高亮 + is_highlight = item.id in ( + ConversationState.is_conversation_history_item_popover_shown, + ConversationState.actived_conversation_id, + ) return rx.list.item( rx.vstack( rx.hstack( # 对话描述 rx.text( - conversation.description, + item.description, flex=1, height="22px", line_height="22px", @@ -53,7 +53,7 @@ def conversation_history_item( rx.spacer(), # 创建时间 rx.text( - conversation.created_at, + item.created_at, line_height="20px", font_size="var(--prismui-font-size-1)", color="var(--prismui-color-8)", @@ -64,8 +64,8 @@ def conversation_history_item( height="20px", margin_bottom="8px", ), - # 点击事件:切换会话 - on_click=lambda: ConversationState.switch_conversation(conversation.id), + # 点击事件:设置激活会话 + on_click=lambda: ConversationState.set_actived_conversation(item.id), width="100%", ), # 更多按钮:点击更多按钮显示气泡卡片,可删除会话 @@ -98,7 +98,7 @@ def conversation_history_item( "删除", # 点击事件:删除对话 on_click=lambda: ConversationState.delete_conversation( - conversation.id + item.id ), display="flex", align_items="center", @@ -130,8 +130,9 @@ def conversation_history_item( box_shadow="var(--prismui-box-shadow-6)", overflow="visible", ), - on_open_change=lambda is_shown: ConversationState.set_shown_more_conversation_id( - conversation.id, is_shown + # 悬停气泡显示 / 隐藏变化事件:设置会话历史项悬停气泡显示 / 隐藏 + on_open_change=lambda is_shown: ConversationState.set_conversation_history_item_popover_shown( + item.id, is_shown ), open_delay=0, ), @@ -227,9 +228,9 @@ def conversation_history( ) -def greeting_showing() -> rx.Component: +def guidance() -> rx.Component: """ - 欢迎展示 + 引导 :return: Component """ return rx.vstack( @@ -360,9 +361,9 @@ def thought_showing(item: Tuple[int, Thought]): ) -def dialog_showing(item: Tuple[str, Dialog]) -> rx.Component: +def message_history_item(item: Tuple[str, Dialog]) -> rx.Component: """ - 对话展示 + 消息历史项 :param item: 对话实例 :return: Component """ @@ -612,42 +613,42 @@ def dialog_showing(item: Tuple[str, Dialog]) -> rx.Component: ) -def dialog_items_showing() -> rx.Component: +def message_history() -> rx.Component: """ - 对话项列表展示 + 消息历史 :return: Component """ - - # 当前会话的对话列表 - dialogs = ConversationState.dialogs - # 若对话列表为空则显示欢迎,否则显示对话列表 - return rx.cond( - dialogs.length() == 0, - # 欢迎展示 - greeting_showing(), - rx.vstack( - rx.auto_scroll( - rx.foreach( - dialogs, - dialog_showing, - ), - width="100%", - padding="0 12px", - padding_bottom="180px", - style={ - "&::-webkit-scrollbar": { - "display": "none", + # 消息历史 + message_history = ConversationState.message_history + return rx.box( + # 若消息历史为空则显示引导,否则渲染消息历史项 + rx.cond( + message_history.length() == 0, + guidance(), + rx.vstack( + rx.auto_scroll( + rx.foreach( + message_history, + message_history_item, + ), + width="100%", + padding="0 12px", + padding_bottom="180px", + style={ + "&::-webkit-scrollbar": { + "display": "none", + }, }, - }, + ), + flex="1", + width="100%", + max_width="1200px", + margin_x="auto", + padding_top="20px", + justify_content="flex-start", + overflow_x="hidden", + overflow_y="auto", ), - flex="1", - width="100%", - max_width="1200px", - margin_x="auto", - padding_top="20px", - justify_content="flex-start", - overflow_x="hidden", - overflow_y="auto", ), ) @@ -723,7 +724,7 @@ def user_prompt_sending() -> rx.Component: conversation_creating(), rx.vstack( rx.text_area( - # 值绑定用户提示词 + # 值绑定:用户提示词 value=ConversationState.user_prompt, # 输入事件:设置用户提示词 on_change=ConversationState.set_user_prompt, @@ -867,7 +868,7 @@ def conversation_history_collapse_button( def conversation_page() -> rx.Component: """ - 会话页面:布局参考 MetaChat,从左到右分别为会话历史和工作区。其中,工作区从上到下分别为对话历史和用户提示词输入框。 + 会话页面:布局参考 MetaChat,从左到右分别为会话历史和工作区。其中,工作区从上到下分别为消息历史和用户提示词输入框。 """ # 会话历史展示状态 is_shown = ConversationState.is_conversation_history_shown @@ -880,7 +881,7 @@ def conversation_page() -> rx.Component: rx.box( # 对话历史 rx.vstack( - dialog_history(), + message_history(), width="100%", height="100%", gap="8px", diff --git a/agent/application/pages/index.py b/agent/application/pages/index.py index ef3d29f..b54c86f 100644 --- a/agent/application/pages/index.py +++ b/agent/application/pages/index.py @@ -4,7 +4,7 @@ """ import reflex as rx -from application.pages import conversation, knowledge_base +from application.pages import conversation_page, knowledge_base_page from application.states import AuthState @@ -434,13 +434,13 @@ def index() -> rx.Component: rx.hstack( # 侧边栏 sidebar(), - # 根据侧边栏状态中激活的导航按钮相应页面(本项目采用卡片布局) + # 根据侧边栏状态中激活的导航按钮相应页面 rx.match( AuthState.activated_nav_button, # 知识库页面 - ("knowledge_base", knowledge_base()), + ("knowledge_base", knowledge_base_page()), # 会话页面 - conversation(), + conversation_page(), ), width="100%", height="100vh", diff --git a/agent/application/pages/knowledge_base.py b/agent/application/pages/knowledge_base.py index f5c74db..7322271 100644 --- a/agent/application/pages/knowledge_base.py +++ b/agent/application/pages/knowledge_base.py @@ -5,7 +5,7 @@ import reflex as rx -def knowledge_base() -> rx.Component: +def knowledge_base_page() -> rx.Component: """ 知识库页面 """ diff --git a/agent/application/states/conversation.py b/agent/application/states/conversation.py index ef1379a..b1f2545 100644 --- a/agent/application/states/conversation.py +++ b/agent/application/states/conversation.py @@ -66,8 +66,8 @@ class ConversationState(rx.State): # 显示会话历史,True 表示显示,False 表示隐藏 is_conversation_history_shown: bool = False - # 会话历史项显示悬停气泡,True 表示显示,False 表示隐藏 - is_conversation_history_item_popover_shown: bool = False + # 会话历史项显示悬停气泡 + is_conversation_history_item_popover_shown: str = "" # 当前数据库状态(私有变量) # 私有变量:reflex 约定以 _ 开头的变量为私有变量,后端不序列化,前端不可使用 @@ -121,6 +121,7 @@ class ConversationState(rx.State): """ return [ ConversationHistoryItem( + id=conversation.id, description=conversation.description, created_at=format_conversation_created_at(conversation.created_at), ) @@ -128,12 +129,16 @@ class ConversationState(rx.State): ] @rx.event - def set_conversation_history_item_popover_shown(self, is_shown: bool) -> None: + def set_conversation_history_item_popover_shown( + self, conversation_id: str, is_shown: bool + ) -> None: """ 设置会话历史项悬停气泡显示 / 隐藏 :return: None """ - self.is_conversation_history_item_popover_shown = is_shown + self.is_conversation_history_item_popover_shown = ( + conversation_id if is_shown else "" + ) @rx.event async def delete_conversation(self, conversation_id: str) -> None: @@ -166,6 +171,18 @@ class ConversationState(rx.State): """ self.actived_conversation_id = conversation_id + @rx.var + def message_history(self) -> list[Message]: + """ + 获取当前会话的消息历史 + :return: 当前会话的消息历史 + """ + # 当前会话 + conversation = self.conversations.get(self.actived_conversation_id) + if not conversation: + return [] + return list(conversation.messages.values()) + @rx.event async def create_conversation(self) -> None: """ @@ -181,6 +198,18 @@ class ConversationState(rx.State): # 将最后一个会话的唯一标识作为激活会话唯一标识 self.actived_conversation_id = next(reversed(self.conversations.keys())) + @rx.var + def user_prompt(self) -> str: + """ + 用户提示词 + :return: 用户提示词 + """ + # 当前会话 + conversation = self.conversations.get(self.actived_conversation_id) + if not conversation: + return "" + return conversation.user_prompt + @rx.event def set_user_prompt(self, user_prompt: str) -> None: """ @@ -276,7 +305,7 @@ class ConversationState(rx.State): from application.workshop.unstructured_dialogue import ( run_stream_events, ) - + # 运行并流式输出事件 stream_events = run_stream_events( user_prompt=user_prompt, message_history=message_history, @@ -415,11 +444,6 @@ class ConversationState(rx.State): case "tool_call": dialog.thoughts[index].content = f"已调用 {content}" - case TaskNodeResultEvent(task=task, content=content): - # 更新任务 - conversation.task = task - dialog.result_output += content - # ========== 智能体运行结果事件 ========== case AgentRunResultEvent(result=result): # 创建对话记录 diff --git a/agent/application/states/models.py b/agent/application/states/models.py index d167c49..1c81a56 100644 --- a/agent/application/states/models.py +++ b/agent/application/states/models.py @@ -21,7 +21,6 @@ class MessageType(StrEnum): THINKING = "thinking" TOOL_CALL = "tool_call" RESULT_OUTPUT = "result_output" - class Message(BaseModel): @@ -73,12 +72,6 @@ class WorkType(StrEnum): BOOK_FLIGHT = "预定航班" -class TaskStatus(StrEnum): - """ - 任务状态枚举 - """ - - NONE = "none" class Deps(BaseModel): @@ -126,6 +119,7 @@ class ConversationHistoryItem(BaseModel): 会话历史项类 """ + id: str = Field(..., description="会话唯一标识") description: str = Field(..., description="会话描述") created_at: str = Field(..., description="会话创建日期时间") diff --git a/agent/application/workshop/book_flight.py b/agent/application/workshop/book_flight.py index 4b696a1..05b1c21 100644 --- a/agent/application/workshop/book_flight.py +++ b/agent/application/workshop/book_flight.py @@ -17,7 +17,7 @@ from application.states.models import ( usage_to_dict, usage_to_object, ) -from application.tasks.models import DEEPSEEK_V4_FLASH_MODEL, MODEL_SETTINGS +from application.workshop.models import DEEPSEEK_V4_FLASH_MODEL, MODEL_SETTINGS class Deps(BaseModel): @@ -67,7 +67,7 @@ flight_details_extraction_agent = Agent( ) -@flight_search_agent.tool(name="提取所有航班详情") +@flight_search_agent.tool async def extract_flight_details(ctx: RunContext[Deps]) -> list[FlightDetail]: """ 工具:提取所有航班详情 @@ -168,15 +168,16 @@ flight_info = """ def init_task() -> Task: - return Task( - type=TaskType.BOOK_FLIGHT, - node="flight_search", + return WorkFlow( + type=WorkType.BOOK_FLIGHT, + tools={"extract_flight_details": {"": ""}}, deps=Deps( flight_info=flight_info, date=datetime.date(2025, 1, 10), origin="SFO", destination="ANC", ), + usage_limits={}, )