This commit is contained in:
parent
8c8fda3da6
commit
55aa7e30e9
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from application.pages.conversation import conversation
|
from application.pages.conversation import conversation_page
|
||||||
from application.pages.knowledge_base import knowledge_base
|
from application.pages.knowledge_base import knowledge_base_page
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["conversation", "knowledge_base"]
|
__all__ = ["conversation_page", "knowledge_base_page"]
|
||||||
|
|
|
||||||
|
|
@ -9,32 +9,32 @@ from application.states.models import (
|
||||||
Conversation,
|
Conversation,
|
||||||
Dialog,
|
Dialog,
|
||||||
Thought,
|
Thought,
|
||||||
|
ConversationHistoryItem,
|
||||||
)
|
)
|
||||||
from application.states import ConversationState, AuthState
|
from application.states import ConversationState, AuthState
|
||||||
|
|
||||||
|
|
||||||
def conversation_history_item(
|
def conversation_history_item(
|
||||||
item: Tuple[str, Conversation],
|
item: ConversationHistoryItem,
|
||||||
) -> rx.Component:
|
) -> rx.Component:
|
||||||
"""
|
"""
|
||||||
会话历史项
|
会话历史项
|
||||||
:param item: 会话历史项
|
:param item: 会话历史项
|
||||||
:return: Component
|
:return: Component
|
||||||
"""
|
"""
|
||||||
conversation = item[1]
|
|
||||||
|
|
||||||
# 高亮:若为当前会话或显示更多则高亮
|
# 高亮
|
||||||
highlight: bool = (
|
is_highlight = item.id in (
|
||||||
conversation.id
|
ConversationState.is_conversation_history_item_popover_shown,
|
||||||
== ConversationState.is_conversation_history_item_more_button_shown
|
ConversationState.actived_conversation_id,
|
||||||
) | (conversation.id == ConversationState.conversation_id)
|
)
|
||||||
|
|
||||||
return rx.list.item(
|
return rx.list.item(
|
||||||
rx.vstack(
|
rx.vstack(
|
||||||
rx.hstack(
|
rx.hstack(
|
||||||
# 对话描述
|
# 对话描述
|
||||||
rx.text(
|
rx.text(
|
||||||
conversation.description,
|
item.description,
|
||||||
flex=1,
|
flex=1,
|
||||||
height="22px",
|
height="22px",
|
||||||
line_height="22px",
|
line_height="22px",
|
||||||
|
|
@ -53,7 +53,7 @@ def conversation_history_item(
|
||||||
rx.spacer(),
|
rx.spacer(),
|
||||||
# 创建时间
|
# 创建时间
|
||||||
rx.text(
|
rx.text(
|
||||||
conversation.created_at,
|
item.created_at,
|
||||||
line_height="20px",
|
line_height="20px",
|
||||||
font_size="var(--prismui-font-size-1)",
|
font_size="var(--prismui-font-size-1)",
|
||||||
color="var(--prismui-color-8)",
|
color="var(--prismui-color-8)",
|
||||||
|
|
@ -64,8 +64,8 @@ def conversation_history_item(
|
||||||
height="20px",
|
height="20px",
|
||||||
margin_bottom="8px",
|
margin_bottom="8px",
|
||||||
),
|
),
|
||||||
# 点击事件:切换会话
|
# 点击事件:设置激活会话
|
||||||
on_click=lambda: ConversationState.switch_conversation(conversation.id),
|
on_click=lambda: ConversationState.set_actived_conversation(item.id),
|
||||||
width="100%",
|
width="100%",
|
||||||
),
|
),
|
||||||
# 更多按钮:点击更多按钮显示气泡卡片,可删除会话
|
# 更多按钮:点击更多按钮显示气泡卡片,可删除会话
|
||||||
|
|
@ -98,7 +98,7 @@ def conversation_history_item(
|
||||||
"删除",
|
"删除",
|
||||||
# 点击事件:删除对话
|
# 点击事件:删除对话
|
||||||
on_click=lambda: ConversationState.delete_conversation(
|
on_click=lambda: ConversationState.delete_conversation(
|
||||||
conversation.id
|
item.id
|
||||||
),
|
),
|
||||||
display="flex",
|
display="flex",
|
||||||
align_items="center",
|
align_items="center",
|
||||||
|
|
@ -130,8 +130,9 @@ def conversation_history_item(
|
||||||
box_shadow="var(--prismui-box-shadow-6)",
|
box_shadow="var(--prismui-box-shadow-6)",
|
||||||
overflow="visible",
|
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,
|
open_delay=0,
|
||||||
),
|
),
|
||||||
|
|
@ -227,9 +228,9 @@ def conversation_history(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def greeting_showing() -> rx.Component:
|
def guidance() -> rx.Component:
|
||||||
"""
|
"""
|
||||||
欢迎展示
|
引导
|
||||||
:return: Component
|
:return: Component
|
||||||
"""
|
"""
|
||||||
return rx.vstack(
|
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: 对话实例
|
:param item: 对话实例
|
||||||
:return: Component
|
:return: Component
|
||||||
"""
|
"""
|
||||||
|
|
@ -612,24 +613,23 @@ def dialog_showing(item: Tuple[str, Dialog]) -> rx.Component:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def dialog_items_showing() -> rx.Component:
|
def message_history() -> rx.Component:
|
||||||
"""
|
"""
|
||||||
对话项列表展示
|
消息历史
|
||||||
:return: Component
|
:return: Component
|
||||||
"""
|
"""
|
||||||
|
# 消息历史
|
||||||
# 当前会话的对话列表
|
message_history = ConversationState.message_history
|
||||||
dialogs = ConversationState.dialogs
|
return rx.box(
|
||||||
# 若对话列表为空则显示欢迎,否则显示对话列表
|
# 若消息历史为空则显示引导,否则渲染消息历史项
|
||||||
return rx.cond(
|
rx.cond(
|
||||||
dialogs.length() == 0,
|
message_history.length() == 0,
|
||||||
# 欢迎展示
|
guidance(),
|
||||||
greeting_showing(),
|
|
||||||
rx.vstack(
|
rx.vstack(
|
||||||
rx.auto_scroll(
|
rx.auto_scroll(
|
||||||
rx.foreach(
|
rx.foreach(
|
||||||
dialogs,
|
message_history,
|
||||||
dialog_showing,
|
message_history_item,
|
||||||
),
|
),
|
||||||
width="100%",
|
width="100%",
|
||||||
padding="0 12px",
|
padding="0 12px",
|
||||||
|
|
@ -649,6 +649,7 @@ def dialog_items_showing() -> rx.Component:
|
||||||
overflow_x="hidden",
|
overflow_x="hidden",
|
||||||
overflow_y="auto",
|
overflow_y="auto",
|
||||||
),
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -723,7 +724,7 @@ def user_prompt_sending() -> rx.Component:
|
||||||
conversation_creating(),
|
conversation_creating(),
|
||||||
rx.vstack(
|
rx.vstack(
|
||||||
rx.text_area(
|
rx.text_area(
|
||||||
# 值绑定用户提示词
|
# 值绑定:用户提示词
|
||||||
value=ConversationState.user_prompt,
|
value=ConversationState.user_prompt,
|
||||||
# 输入事件:设置用户提示词
|
# 输入事件:设置用户提示词
|
||||||
on_change=ConversationState.set_user_prompt,
|
on_change=ConversationState.set_user_prompt,
|
||||||
|
|
@ -867,7 +868,7 @@ def conversation_history_collapse_button(
|
||||||
|
|
||||||
def conversation_page() -> rx.Component:
|
def conversation_page() -> rx.Component:
|
||||||
"""
|
"""
|
||||||
会话页面:布局参考 MetaChat,从左到右分别为会话历史和工作区。其中,工作区从上到下分别为对话历史和用户提示词输入框。
|
会话页面:布局参考 MetaChat,从左到右分别为会话历史和工作区。其中,工作区从上到下分别为消息历史和用户提示词输入框。
|
||||||
"""
|
"""
|
||||||
# 会话历史展示状态
|
# 会话历史展示状态
|
||||||
is_shown = ConversationState.is_conversation_history_shown
|
is_shown = ConversationState.is_conversation_history_shown
|
||||||
|
|
@ -880,7 +881,7 @@ def conversation_page() -> rx.Component:
|
||||||
rx.box(
|
rx.box(
|
||||||
# 对话历史
|
# 对话历史
|
||||||
rx.vstack(
|
rx.vstack(
|
||||||
dialog_history(),
|
message_history(),
|
||||||
width="100%",
|
width="100%",
|
||||||
height="100%",
|
height="100%",
|
||||||
gap="8px",
|
gap="8px",
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
"""
|
"""
|
||||||
import reflex as rx
|
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
|
from application.states import AuthState
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -434,13 +434,13 @@ def index() -> rx.Component:
|
||||||
rx.hstack(
|
rx.hstack(
|
||||||
# 侧边栏
|
# 侧边栏
|
||||||
sidebar(),
|
sidebar(),
|
||||||
# 根据侧边栏状态中激活的导航按钮相应页面(本项目采用卡片布局)
|
# 根据侧边栏状态中激活的导航按钮相应页面
|
||||||
rx.match(
|
rx.match(
|
||||||
AuthState.activated_nav_button,
|
AuthState.activated_nav_button,
|
||||||
# 知识库页面
|
# 知识库页面
|
||||||
("knowledge_base", knowledge_base()),
|
("knowledge_base", knowledge_base_page()),
|
||||||
# 会话页面
|
# 会话页面
|
||||||
conversation(),
|
conversation_page(),
|
||||||
),
|
),
|
||||||
width="100%",
|
width="100%",
|
||||||
height="100vh",
|
height="100vh",
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
import reflex as rx
|
import reflex as rx
|
||||||
|
|
||||||
|
|
||||||
def knowledge_base() -> rx.Component:
|
def knowledge_base_page() -> rx.Component:
|
||||||
"""
|
"""
|
||||||
知识库页面
|
知识库页面
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,8 @@ class ConversationState(rx.State):
|
||||||
|
|
||||||
# 显示会话历史,True 表示显示,False 表示隐藏
|
# 显示会话历史,True 表示显示,False 表示隐藏
|
||||||
is_conversation_history_shown: bool = 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 约定以 _ 开头的变量为私有变量,后端不序列化,前端不可使用
|
# 私有变量:reflex 约定以 _ 开头的变量为私有变量,后端不序列化,前端不可使用
|
||||||
|
|
@ -121,6 +121,7 @@ class ConversationState(rx.State):
|
||||||
"""
|
"""
|
||||||
return [
|
return [
|
||||||
ConversationHistoryItem(
|
ConversationHistoryItem(
|
||||||
|
id=conversation.id,
|
||||||
description=conversation.description,
|
description=conversation.description,
|
||||||
created_at=format_conversation_created_at(conversation.created_at),
|
created_at=format_conversation_created_at(conversation.created_at),
|
||||||
)
|
)
|
||||||
|
|
@ -128,12 +129,16 @@ class ConversationState(rx.State):
|
||||||
]
|
]
|
||||||
|
|
||||||
@rx.event
|
@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
|
: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
|
@rx.event
|
||||||
async def delete_conversation(self, conversation_id: str) -> None:
|
async def delete_conversation(self, conversation_id: str) -> None:
|
||||||
|
|
@ -166,6 +171,18 @@ class ConversationState(rx.State):
|
||||||
"""
|
"""
|
||||||
self.actived_conversation_id = conversation_id
|
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
|
@rx.event
|
||||||
async def create_conversation(self) -> None:
|
async def create_conversation(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
@ -181,6 +198,18 @@ class ConversationState(rx.State):
|
||||||
# 将最后一个会话的唯一标识作为激活会话唯一标识
|
# 将最后一个会话的唯一标识作为激活会话唯一标识
|
||||||
self.actived_conversation_id = next(reversed(self.conversations.keys()))
|
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
|
@rx.event
|
||||||
def set_user_prompt(self, user_prompt: str) -> None:
|
def set_user_prompt(self, user_prompt: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
@ -276,7 +305,7 @@ class ConversationState(rx.State):
|
||||||
from application.workshop.unstructured_dialogue import (
|
from application.workshop.unstructured_dialogue import (
|
||||||
run_stream_events,
|
run_stream_events,
|
||||||
)
|
)
|
||||||
|
# 运行并流式输出事件
|
||||||
stream_events = run_stream_events(
|
stream_events = run_stream_events(
|
||||||
user_prompt=user_prompt,
|
user_prompt=user_prompt,
|
||||||
message_history=message_history,
|
message_history=message_history,
|
||||||
|
|
@ -415,11 +444,6 @@ class ConversationState(rx.State):
|
||||||
case "tool_call":
|
case "tool_call":
|
||||||
dialog.thoughts[index].content = f"已调用 {content}"
|
dialog.thoughts[index].content = f"已调用 {content}"
|
||||||
|
|
||||||
case TaskNodeResultEvent(task=task, content=content):
|
|
||||||
# 更新任务
|
|
||||||
conversation.task = task
|
|
||||||
dialog.result_output += content
|
|
||||||
|
|
||||||
# ========== 智能体运行结果事件 ==========
|
# ========== 智能体运行结果事件 ==========
|
||||||
case AgentRunResultEvent(result=result):
|
case AgentRunResultEvent(result=result):
|
||||||
# 创建对话记录
|
# 创建对话记录
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ class MessageType(StrEnum):
|
||||||
RESULT_OUTPUT = "result_output"
|
RESULT_OUTPUT = "result_output"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Message(BaseModel):
|
class Message(BaseModel):
|
||||||
"""
|
"""
|
||||||
消息类
|
消息类
|
||||||
|
|
@ -73,12 +72,6 @@ class WorkType(StrEnum):
|
||||||
BOOK_FLIGHT = "预定航班"
|
BOOK_FLIGHT = "预定航班"
|
||||||
|
|
||||||
|
|
||||||
class TaskStatus(StrEnum):
|
|
||||||
"""
|
|
||||||
任务状态枚举
|
|
||||||
"""
|
|
||||||
|
|
||||||
NONE = "none"
|
|
||||||
|
|
||||||
|
|
||||||
class Deps(BaseModel):
|
class Deps(BaseModel):
|
||||||
|
|
@ -126,6 +119,7 @@ class ConversationHistoryItem(BaseModel):
|
||||||
会话历史项类
|
会话历史项类
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
id: str = Field(..., description="会话唯一标识")
|
||||||
description: str = Field(..., description="会话描述")
|
description: str = Field(..., description="会话描述")
|
||||||
created_at: str = Field(..., description="会话创建日期时间")
|
created_at: str = Field(..., description="会话创建日期时间")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ from application.states.models import (
|
||||||
usage_to_dict,
|
usage_to_dict,
|
||||||
usage_to_object,
|
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):
|
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]:
|
async def extract_flight_details(ctx: RunContext[Deps]) -> list[FlightDetail]:
|
||||||
"""
|
"""
|
||||||
工具:提取所有航班详情
|
工具:提取所有航班详情
|
||||||
|
|
@ -168,15 +168,16 @@ flight_info = """
|
||||||
|
|
||||||
|
|
||||||
def init_task() -> Task:
|
def init_task() -> Task:
|
||||||
return Task(
|
return WorkFlow(
|
||||||
type=TaskType.BOOK_FLIGHT,
|
type=WorkType.BOOK_FLIGHT,
|
||||||
node="flight_search",
|
tools={"extract_flight_details": {"": ""}},
|
||||||
deps=Deps(
|
deps=Deps(
|
||||||
flight_info=flight_info,
|
flight_info=flight_info,
|
||||||
date=datetime.date(2025, 1, 10),
|
date=datetime.date(2025, 1, 10),
|
||||||
origin="SFO",
|
origin="SFO",
|
||||||
destination="ANC",
|
destination="ANC",
|
||||||
),
|
),
|
||||||
|
usage_limits={},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue