This commit is contained in:
parent
f9b91d45c1
commit
7b89324981
|
|
@ -46,31 +46,7 @@ class Conversation(BaseModel):
|
||||||
default=False, description="正在运行,True 表示正在运行,False 表示未正在运行"
|
default=False, description="正在运行,True 表示正在运行,False 表示未正在运行"
|
||||||
)
|
)
|
||||||
dialogs: Dict[str, Dialog] = Field(default_factory=dict, description="对话列表")
|
dialogs: Dict[str, Dialog] = Field(default_factory=dict, description="对话列表")
|
||||||
created_at: datetime = Field(default_factory=datetime.now, description="创建时间")
|
created_at: str = Field(
|
||||||
|
...,
|
||||||
|
description="创建时间",
|
||||||
class ConversationHistoryItem(BaseModel):
|
|
||||||
"""
|
|
||||||
会话历史项领域模型
|
|
||||||
"""
|
|
||||||
|
|
||||||
id: str = Field(..., description="会话唯一标识")
|
|
||||||
description: str = Field(..., description="会话描述")
|
|
||||||
created_at: str = Field(..., description="会话创建时间")
|
|
||||||
|
|
||||||
|
|
||||||
class DialogItem(BaseModel):
|
|
||||||
"""
|
|
||||||
对话项领域模型
|
|
||||||
"""
|
|
||||||
|
|
||||||
id: str = Field(..., description="对话唯一标识")
|
|
||||||
user_prompt: str = Field(..., description="用户提示词")
|
|
||||||
thoughts: List[Thought] = Field(default_factory=list, description="思考列表")
|
|
||||||
result_output: str = Field(default="", description="结果输出")
|
|
||||||
is_thinking: bool = Field(
|
|
||||||
default=False, description="正在思考,True 表示正在思考,False 表示未正在思考"
|
|
||||||
)
|
|
||||||
is_expanded: bool = Field(
|
|
||||||
default=False, description="思考折叠面板展开状态,True 表示展开,False 表示折叠"
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -3,37 +3,37 @@
|
||||||
会话页面
|
会话页面
|
||||||
"""
|
"""
|
||||||
import reflex as rx
|
import reflex as rx
|
||||||
from typing import Dict
|
from typing import Tuple
|
||||||
|
|
||||||
from application.domain_models import (
|
from application.domain_models import (
|
||||||
Conversation,
|
Conversation,
|
||||||
DialogItem,
|
Dialog,
|
||||||
Thought,
|
Thought,
|
||||||
ConversationHistoryItem,
|
|
||||||
)
|
)
|
||||||
from application.states import ConversationState, AuthState
|
from application.states import ConversationState, AuthState
|
||||||
|
|
||||||
|
|
||||||
def conversation_history_item_showing(
|
def conversation_history_item_showing(
|
||||||
item: ConversationHistoryItem,
|
item: Tuple[str, Conversation],
|
||||||
) -> rx.Component:
|
) -> rx.Component:
|
||||||
"""
|
"""
|
||||||
会话历史项展示
|
会话历史项展示
|
||||||
:param conversation: 会话历史项
|
:param item: 会话历史项
|
||||||
:return: Component
|
:return: Component
|
||||||
"""
|
"""
|
||||||
|
conversation = item[1]
|
||||||
|
|
||||||
# 高亮:若为当前会话或显示更多则高亮
|
# 高亮:若为当前会话或显示更多则高亮
|
||||||
highlight: bool = (item.id == ConversationState.shown_more_conversation_id) | (
|
highlight: bool = (
|
||||||
item.id == ConversationState.conversation_id
|
conversation.id == ConversationState.shown_more_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(
|
||||||
item.description,
|
conversation.description,
|
||||||
flex=1,
|
flex=1,
|
||||||
height="22px",
|
height="22px",
|
||||||
line_height="22px",
|
line_height="22px",
|
||||||
|
|
@ -52,7 +52,7 @@ def conversation_history_item_showing(
|
||||||
rx.spacer(),
|
rx.spacer(),
|
||||||
# 创建时间
|
# 创建时间
|
||||||
rx.text(
|
rx.text(
|
||||||
item.created_at,
|
conversation.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,7 +64,7 @@ def conversation_history_item_showing(
|
||||||
margin_bottom="8px",
|
margin_bottom="8px",
|
||||||
),
|
),
|
||||||
# 点击事件:切换会话
|
# 点击事件:切换会话
|
||||||
on_click=lambda: ConversationState.switch_conversation(item.id),
|
on_click=lambda: ConversationState.switch_conversation(conversation.id),
|
||||||
width="100%",
|
width="100%",
|
||||||
),
|
),
|
||||||
# 更多按钮:点击更多按钮显示气泡卡片,可删除会话
|
# 更多按钮:点击更多按钮显示气泡卡片,可删除会话
|
||||||
|
|
@ -97,7 +97,7 @@ def conversation_history_item_showing(
|
||||||
"删除",
|
"删除",
|
||||||
# 点击事件:删除对话
|
# 点击事件:删除对话
|
||||||
on_click=lambda: ConversationState.delete_conversation(
|
on_click=lambda: ConversationState.delete_conversation(
|
||||||
item.id
|
conversation.id
|
||||||
),
|
),
|
||||||
display="flex",
|
display="flex",
|
||||||
align_items="center",
|
align_items="center",
|
||||||
|
|
@ -130,7 +130,7 @@ def conversation_history_item_showing(
|
||||||
overflow="visible",
|
overflow="visible",
|
||||||
),
|
),
|
||||||
on_open_change=lambda is_shown: ConversationState.set_shown_more_conversation_id(
|
on_open_change=lambda is_shown: ConversationState.set_shown_more_conversation_id(
|
||||||
item.id, is_shown
|
conversation.id, is_shown
|
||||||
),
|
),
|
||||||
open_delay=0,
|
open_delay=0,
|
||||||
),
|
),
|
||||||
|
|
@ -195,7 +195,7 @@ def conversation_history_items_showing(
|
||||||
),
|
),
|
||||||
rx.auto_scroll(
|
rx.auto_scroll(
|
||||||
rx.foreach(
|
rx.foreach(
|
||||||
ConversationState.conversation_history_items,
|
ConversationState.conversations,
|
||||||
conversation_history_item_showing,
|
conversation_history_item_showing,
|
||||||
),
|
),
|
||||||
flex="1",
|
flex="1",
|
||||||
|
|
@ -331,19 +331,21 @@ def greeting_showing() -> rx.Component:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def thought_showing(item: Thought):
|
def thought_showing(item: Tuple[int, Thought]):
|
||||||
"""
|
"""
|
||||||
思考展示
|
思考展示
|
||||||
:param item: 思考实例
|
:param item: 思考实例
|
||||||
:return: Component
|
:return: Component
|
||||||
"""
|
"""
|
||||||
|
# 思考实例
|
||||||
|
thought = item[1]
|
||||||
return rx.vstack(
|
return rx.vstack(
|
||||||
rx.match(
|
rx.match(
|
||||||
item.type,
|
thought.type,
|
||||||
(
|
(
|
||||||
"thinking",
|
"thinking",
|
||||||
rx.text(
|
rx.text(
|
||||||
item.content,
|
thought.content,
|
||||||
line_height="22px",
|
line_height="22px",
|
||||||
font_size="var(--prismui-font-size-2)",
|
font_size="var(--prismui-font-size-2)",
|
||||||
color="var(--prismui-color-3)",
|
color="var(--prismui-color-3)",
|
||||||
|
|
@ -356,16 +358,18 @@ def thought_showing(item: Thought):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def dialog_item_showing(item: DialogItem) -> rx.Component:
|
def dialog_showing(item: Tuple[str, Dialog]) -> rx.Component:
|
||||||
"""
|
"""
|
||||||
对话项展示
|
对话展示
|
||||||
:param item: 对话项实例
|
:param item: 对话实例
|
||||||
:return: Component
|
:return: Component
|
||||||
"""
|
"""
|
||||||
|
# 对话实例
|
||||||
|
dialog = item[1]
|
||||||
# 推理状态
|
# 推理状态
|
||||||
is_thinking = item.is_thinking
|
is_thinking = dialog.is_thinking
|
||||||
# 思考折叠面板展开状态
|
# 思考折叠面板展开状态
|
||||||
is_expanded = item.is_expanded
|
is_expanded = dialog.is_expanded
|
||||||
|
|
||||||
return rx.vstack(
|
return rx.vstack(
|
||||||
rx.hstack(
|
rx.hstack(
|
||||||
|
|
@ -373,7 +377,7 @@ def dialog_item_showing(item: DialogItem) -> rx.Component:
|
||||||
rx.vstack(
|
rx.vstack(
|
||||||
# 用户提示词
|
# 用户提示词
|
||||||
rx.text(
|
rx.text(
|
||||||
item.user_prompt,
|
dialog.user_prompt,
|
||||||
max_width="600px",
|
max_width="600px",
|
||||||
padding="12px 16px",
|
padding="12px 16px",
|
||||||
background_color="var(--prismui-background-color-3)",
|
background_color="var(--prismui-background-color-3)",
|
||||||
|
|
@ -439,13 +443,13 @@ def dialog_item_showing(item: DialogItem) -> rx.Component:
|
||||||
),
|
),
|
||||||
cursor="pointer",
|
cursor="pointer",
|
||||||
# 点击事件,展开/折叠思考折叠面板
|
# 点击事件,展开/折叠思考折叠面板
|
||||||
on_click=lambda: ConversationState.toggle_collapse(item.id),
|
on_click=lambda: ConversationState.toggle_collapse(dialog.id),
|
||||||
),
|
),
|
||||||
rx.box(
|
rx.box(
|
||||||
rx.box(
|
rx.box(
|
||||||
rx.auto_scroll(
|
rx.auto_scroll(
|
||||||
rx.foreach(
|
rx.foreach(
|
||||||
item.thoughts,
|
dialog.thoughts,
|
||||||
thought_showing,
|
thought_showing,
|
||||||
),
|
),
|
||||||
width="100%",
|
width="100%",
|
||||||
|
|
@ -467,7 +471,7 @@ def dialog_item_showing(item: DialogItem) -> rx.Component:
|
||||||
),
|
),
|
||||||
# 结果输出
|
# 结果输出
|
||||||
rx.markdown(
|
rx.markdown(
|
||||||
item.result_output,
|
dialog.result_output,
|
||||||
component_map={
|
component_map={
|
||||||
"p": lambda text: rx.text(
|
"p": lambda text: rx.text(
|
||||||
text,
|
text,
|
||||||
|
|
@ -545,14 +549,42 @@ def dialog_item_showing(item: DialogItem) -> rx.Component:
|
||||||
"hr": lambda _: rx.divider(
|
"hr": lambda _: rx.divider(
|
||||||
height="1px",
|
height="1px",
|
||||||
margin="12px 0",
|
margin="12px 0",
|
||||||
background_color="var(--prismui-background-color-6)",
|
background_color="transparent",
|
||||||
|
),
|
||||||
|
"table": lambda children: rx.el.table(
|
||||||
|
children,
|
||||||
|
style={
|
||||||
|
"margin": "12px 0",
|
||||||
|
"width": "100%",
|
||||||
|
"border-collapse": "collapse",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"thead": lambda children: rx.el.thead(children),
|
||||||
|
"tbody": lambda children: rx.el.tbody(children),
|
||||||
|
"tr": lambda children: rx.el.tr(children),
|
||||||
|
"th": lambda text: rx.el.th(
|
||||||
|
text,
|
||||||
|
style={
|
||||||
|
"padding": "10px 12px",
|
||||||
|
"background": "var(--prismui-background-color-3)",
|
||||||
|
"border": "1px solid var(--prismui-background-color-6)",
|
||||||
|
"text-align": "left",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"td": lambda text: rx.el.td(
|
||||||
|
text,
|
||||||
|
style={
|
||||||
|
"padding": "10px 12px",
|
||||||
|
"border": "1px solid var(--prismui-background-color-6)",
|
||||||
|
"vertical-align": "top",
|
||||||
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
width="100%",
|
width="100%",
|
||||||
),
|
),
|
||||||
padding="0 16px",
|
padding="0 16px",
|
||||||
width="100%",
|
width="100%",
|
||||||
key=item.id,
|
key=dialog.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -563,21 +595,26 @@ def dialog_items_showing() -> rx.Component:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# 当前会话的对话列表
|
# 当前会话的对话列表
|
||||||
dialog_items = ConversationState.dialog_items
|
dialogs = ConversationState.dialogs
|
||||||
# 若对话列表为空则显示欢迎,否则显示对话列表
|
# 若对话列表为空则显示欢迎,否则显示对话列表
|
||||||
return rx.cond(
|
return rx.cond(
|
||||||
dialog_items.length() == 0,
|
dialogs.length() == 0,
|
||||||
# 欢迎展示
|
# 欢迎展示
|
||||||
greeting_showing(),
|
greeting_showing(),
|
||||||
rx.vstack(
|
rx.vstack(
|
||||||
rx.auto_scroll(
|
rx.auto_scroll(
|
||||||
rx.foreach(
|
rx.foreach(
|
||||||
dialog_items,
|
dialogs,
|
||||||
dialog_item_showing,
|
dialog_showing,
|
||||||
),
|
),
|
||||||
width="100%",
|
width="100%",
|
||||||
padding="0 12px",
|
padding="0 12px",
|
||||||
padding_bottom="180px",
|
padding_bottom="180px",
|
||||||
|
style={
|
||||||
|
"&::-webkit-scrollbar": {
|
||||||
|
"display": "none",
|
||||||
|
},
|
||||||
|
},
|
||||||
),
|
),
|
||||||
flex="1",
|
flex="1",
|
||||||
width="100%",
|
width="100%",
|
||||||
|
|
@ -778,12 +815,14 @@ def user_prompt_sending() -> rx.Component:
|
||||||
position="absolute",
|
position="absolute",
|
||||||
bottom="0",
|
bottom="0",
|
||||||
left="0",
|
left="0",
|
||||||
|
right="0",
|
||||||
z_index="99",
|
z_index="99",
|
||||||
display="flex",
|
display="flex",
|
||||||
flex_direction="column",
|
flex_direction="column",
|
||||||
width="100%",
|
width="100%",
|
||||||
max_width="1200px",
|
max_width="1200px",
|
||||||
padding="0 12px 12px",
|
padding="0 12px 12px",
|
||||||
|
margin_x="auto",
|
||||||
border="none",
|
border="none",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,8 @@ import reflex as rx
|
||||||
from application.states.database import DatabaseState
|
from application.states.database import DatabaseState
|
||||||
from application.domain_models import (
|
from application.domain_models import (
|
||||||
Conversation,
|
Conversation,
|
||||||
DialogItem,
|
Dialog,
|
||||||
Thought,
|
Thought,
|
||||||
ConversationHistoryItem,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
instructions: str = """
|
instructions: str = """
|
||||||
|
|
@ -117,34 +116,6 @@ class ConversationState(rx.State):
|
||||||
"""
|
"""
|
||||||
self.is_conversation_history_shown = not self.is_conversation_history_shown
|
self.is_conversation_history_shown = not self.is_conversation_history_shown
|
||||||
|
|
||||||
@rx.var
|
|
||||||
def conversation_history_items(self) -> List[ConversationHistoryItem]:
|
|
||||||
"""
|
|
||||||
获取会话历史项列表,用于前端渲染会话历史
|
|
||||||
:return: 会话历史项列表
|
|
||||||
"""
|
|
||||||
items: List[ConversationHistoryItem] = []
|
|
||||||
for conversation in reversed(
|
|
||||||
self.conversations.values()
|
|
||||||
): # 按照会话唯一标识倒序排序
|
|
||||||
# 格式化会话创建时间
|
|
||||||
match (datetime.now().date() - conversation.created_at.date()).days:
|
|
||||||
case 0:
|
|
||||||
created_at = f"{conversation.created_at.strftime('%H:%M')}"
|
|
||||||
case 1:
|
|
||||||
created_at = f"昨天 {conversation.created_at.strftime('%H:%M')}"
|
|
||||||
case _:
|
|
||||||
created_at = conversation.created_at.strftime("%Y-%m-%d %H:%M")
|
|
||||||
|
|
||||||
items.append(
|
|
||||||
ConversationHistoryItem(
|
|
||||||
id=conversation.id,
|
|
||||||
description=conversation.description,
|
|
||||||
created_at=created_at,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return items
|
|
||||||
|
|
||||||
@rx.event
|
@rx.event
|
||||||
def set_shown_more_conversation_id(
|
def set_shown_more_conversation_id(
|
||||||
self, conversation_id: str, is_shown: bool
|
self, conversation_id: str, is_shown: bool
|
||||||
|
|
@ -252,29 +223,16 @@ class ConversationState(rx.State):
|
||||||
return conversation.is_running
|
return conversation.is_running
|
||||||
|
|
||||||
@rx.var
|
@rx.var
|
||||||
def dialog_items(self) -> List[DialogItem]:
|
def dialogs(self) -> Dict[str, Dialog]:
|
||||||
"""
|
"""
|
||||||
当前会话的对话项列表
|
当前会话的对话字典
|
||||||
:return: 当前会话的对话项列表
|
:return: 当前会话的对话字典
|
||||||
"""
|
"""
|
||||||
# 当前会话
|
# 当前会话
|
||||||
conversation = self.conversations.get(self.conversation_id)
|
conversation = self.conversations.get(self.conversation_id)
|
||||||
if not conversation:
|
if not conversation:
|
||||||
return []
|
return {}
|
||||||
|
return conversation.dialogs
|
||||||
items: List[DialogItem] = []
|
|
||||||
for dialog in conversation.dialogs.values():
|
|
||||||
items.append(
|
|
||||||
DialogItem(
|
|
||||||
id=dialog.id,
|
|
||||||
user_prompt=dialog.user_prompt,
|
|
||||||
thoughts=list(dialog.thoughts.values()),
|
|
||||||
result_output=dialog.result_output,
|
|
||||||
is_thinking=dialog.is_thinking,
|
|
||||||
is_expanded=dialog.is_expanded,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return items
|
|
||||||
|
|
||||||
@rx.event
|
@rx.event
|
||||||
async def handle_user_prompt(self) -> AsyncGenerator[None]:
|
async def handle_user_prompt(self) -> AsyncGenerator[None]:
|
||||||
|
|
@ -293,7 +251,6 @@ class ConversationState(rx.State):
|
||||||
conversation = self.conversations[self.conversation_id]
|
conversation = self.conversations[self.conversation_id]
|
||||||
# 将运行状态设置为正在运行
|
# 将运行状态设置为正在运行
|
||||||
conversation.is_running = True
|
conversation.is_running = True
|
||||||
yield
|
|
||||||
|
|
||||||
database_state = await self.get_state(DatabaseState)
|
database_state = await self.get_state(DatabaseState)
|
||||||
|
|
||||||
|
|
@ -303,20 +260,20 @@ class ConversationState(rx.State):
|
||||||
conversation_id=self.conversation_id, user_prompt=user_prompt
|
conversation_id=self.conversation_id, user_prompt=user_prompt
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
# 强制更新会话并推送前端
|
||||||
|
self.conversations[self.conversation_id] = conversation
|
||||||
|
yield
|
||||||
|
|
||||||
# 将最后一个对话作为当前对话
|
# 将最后一个对话作为当前对话
|
||||||
dialog = next(reversed(conversation.dialogs.values()))
|
dialog = next(reversed(conversation.dialogs.values()))
|
||||||
|
|
||||||
# 获取消息历史
|
|
||||||
message_history = await database_state.get_message_history(
|
|
||||||
conversation_id=self.conversation_id
|
|
||||||
)
|
|
||||||
|
|
||||||
# 初始化工具调用唯一标识和片段索引映射字典
|
# 初始化工具调用唯一标识和片段索引映射字典
|
||||||
tool_call_ids: Dict[str, int] = {}
|
tool_call_ids: Dict[str, int] = {}
|
||||||
async with agent.run_stream_events(
|
async with agent.run_stream_events(
|
||||||
conversation_id=self.conversation_id,
|
conversation_id=self.conversation_id,
|
||||||
user_prompt=user_prompt,
|
user_prompt=user_prompt,
|
||||||
message_history=message_history,
|
message_history=await database_state.get_message_history(
|
||||||
|
conversation_id=self.conversation_id
|
||||||
|
),
|
||||||
) as events:
|
) as events:
|
||||||
async for event in events:
|
async for event in events:
|
||||||
match event:
|
match event:
|
||||||
|
|
@ -336,7 +293,6 @@ class ConversationState(rx.State):
|
||||||
dialog.thoughts[index] = Thought(
|
dialog.thoughts[index] = Thought(
|
||||||
type="thinking", content=content
|
type="thinking", content=content
|
||||||
)
|
)
|
||||||
yield
|
|
||||||
|
|
||||||
# 工具检索分片开始事件
|
# 工具检索分片开始事件
|
||||||
case ToolSearchCallPart(tool_call_id=tool_call_id):
|
case ToolSearchCallPart(tool_call_id=tool_call_id):
|
||||||
|
|
@ -347,7 +303,6 @@ class ConversationState(rx.State):
|
||||||
type="tool_search",
|
type="tool_search",
|
||||||
content="正在生成检索关键词",
|
content="正在生成检索关键词",
|
||||||
)
|
)
|
||||||
yield
|
|
||||||
|
|
||||||
# 能力加载分片开始事件
|
# 能力加载分片开始事件
|
||||||
case LoadCapabilityCallPart(tool_call_id=tool_call_id):
|
case LoadCapabilityCallPart(tool_call_id=tool_call_id):
|
||||||
|
|
@ -357,7 +312,6 @@ class ConversationState(rx.State):
|
||||||
type="capability_load",
|
type="capability_load",
|
||||||
content="正在生成加载参数",
|
content="正在生成加载参数",
|
||||||
)
|
)
|
||||||
yield
|
|
||||||
|
|
||||||
# 工具调用分片开始事件
|
# 工具调用分片开始事件
|
||||||
case ToolCallPart(tool_call_id=tool_call_id):
|
case ToolCallPart(tool_call_id=tool_call_id):
|
||||||
|
|
@ -367,12 +321,10 @@ class ConversationState(rx.State):
|
||||||
type="tool_call",
|
type="tool_call",
|
||||||
content="正在生成调用参数",
|
content="正在生成调用参数",
|
||||||
)
|
)
|
||||||
yield
|
|
||||||
|
|
||||||
# 文本分片开始事件
|
# 文本分片开始事件
|
||||||
case TextPart(content=content):
|
case TextPart(content=content):
|
||||||
dialog.result_output = content
|
dialog.result_output = content
|
||||||
yield
|
|
||||||
|
|
||||||
# ========== 增量事件 ==========
|
# ========== 增量事件 ==========
|
||||||
case PartDeltaEvent(index=index, delta=delta):
|
case PartDeltaEvent(index=index, delta=delta):
|
||||||
|
|
@ -382,14 +334,12 @@ class ConversationState(rx.State):
|
||||||
content_delta=content_delta,
|
content_delta=content_delta,
|
||||||
):
|
):
|
||||||
dialog.thoughts[index].content += content_delta or ""
|
dialog.thoughts[index].content += content_delta or ""
|
||||||
yield
|
|
||||||
|
|
||||||
# 文本分片增量事件
|
# 文本分片增量事件
|
||||||
case TextPartDelta(
|
case TextPartDelta(
|
||||||
content_delta=content_delta,
|
content_delta=content_delta,
|
||||||
):
|
):
|
||||||
dialog.result_output += content_delta
|
dialog.result_output += content_delta
|
||||||
yield
|
|
||||||
|
|
||||||
# ========== 结束事件 ==========
|
# ========== 结束事件 ==========
|
||||||
case PartEndEvent(
|
case PartEndEvent(
|
||||||
|
|
@ -399,12 +349,11 @@ class ConversationState(rx.State):
|
||||||
):
|
):
|
||||||
match part:
|
match part:
|
||||||
# 思考分片结束事件
|
# 思考分片结束事件
|
||||||
case ThinkingPart(part_kind=part_kind, content=content):
|
case ThinkingPart(content=content):
|
||||||
# 若下一分片种类为文本则将思考状态设置为思考完成、思考面板展开状态设置为折叠
|
# 若下一分片种类为文本则将思考状态设置为思考完成、思考面板展开状态设置为折叠
|
||||||
if next_part_kind == "text":
|
if next_part_kind == "text":
|
||||||
dialog.is_thinking = False
|
dialog.is_thinking = False
|
||||||
dialog.is_expanded = False
|
dialog.is_expanded = False
|
||||||
yield
|
|
||||||
|
|
||||||
# ========== 函数工具调用事件 ==========
|
# ========== 函数工具调用事件 ==========
|
||||||
case FunctionToolCallEvent(tool_call_id=tool_call_id, part=part):
|
case FunctionToolCallEvent(tool_call_id=tool_call_id, part=part):
|
||||||
|
|
@ -414,21 +363,18 @@ class ConversationState(rx.State):
|
||||||
# 工具检索
|
# 工具检索
|
||||||
case "tool_search":
|
case "tool_search":
|
||||||
dialog.thoughts[index].content = "正在检索"
|
dialog.thoughts[index].content = "正在检索"
|
||||||
yield
|
|
||||||
|
|
||||||
# 能力加载
|
# 能力加载
|
||||||
case "capability_load":
|
case "capability_load":
|
||||||
dialog.thoughts[index].content = (
|
dialog.thoughts[index].content = (
|
||||||
f"正在加载能力 {part.tool_name}"
|
f"正在加载能力 {part.tool_name}"
|
||||||
)
|
)
|
||||||
yield
|
|
||||||
|
|
||||||
# 工具调用
|
# 工具调用
|
||||||
case "tool_call":
|
case "tool_call":
|
||||||
dialog.thoughts[index].content = (
|
dialog.thoughts[index].content = (
|
||||||
f"正在调用工具 {part.tool_name}"
|
f"正在调用工具 {part.tool_name}"
|
||||||
)
|
)
|
||||||
yield
|
|
||||||
|
|
||||||
# ========== 函数工具结果事件 ==========
|
# ========== 函数工具结果事件 ==========
|
||||||
case FunctionToolResultEvent(
|
case FunctionToolResultEvent(
|
||||||
|
|
@ -442,17 +388,14 @@ class ConversationState(rx.State):
|
||||||
dialog.thoughts[index].content = (
|
dialog.thoughts[index].content = (
|
||||||
content if isinstance(content, str) else ""
|
content if isinstance(content, str) else ""
|
||||||
) # 暂仅考虑文本内容
|
) # 暂仅考虑文本内容
|
||||||
yield
|
|
||||||
|
|
||||||
# 能力加载
|
# 能力加载
|
||||||
case "capability_load":
|
case "capability_load":
|
||||||
dialog.thoughts[index].content = "已加载"
|
dialog.thoughts[index].content = "已加载"
|
||||||
yield
|
|
||||||
|
|
||||||
# 工具调用
|
# 工具调用
|
||||||
case "tool_call":
|
case "tool_call":
|
||||||
dialog.thoughts[index].content = f"已调用"
|
dialog.thoughts[index].content = f"已调用"
|
||||||
yield
|
|
||||||
|
|
||||||
# ========== 智能体运行结果事件 ==========
|
# ========== 智能体运行结果事件 ==========
|
||||||
case AgentRunResultEvent(result=result):
|
case AgentRunResultEvent(result=result):
|
||||||
|
|
@ -470,7 +413,10 @@ class ConversationState(rx.State):
|
||||||
)
|
)
|
||||||
# 将当前会话的运行状态设置为运行完成
|
# 将当前会话的运行状态设置为运行完成
|
||||||
conversation.is_running = False
|
conversation.is_running = False
|
||||||
yield
|
|
||||||
|
# 强制更新会话并推送前端
|
||||||
|
self.conversations[self.conversation_id] = conversation
|
||||||
|
yield
|
||||||
|
|
||||||
@rx.event
|
@rx.event
|
||||||
def toggle_collapse(self, dialog_id: str) -> None:
|
def toggle_collapse(self, dialog_id: str) -> None:
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,22 @@ class ResultRecord(SQLModel, table=True):
|
||||||
new_messages: str = Field(description="新增消息")
|
new_messages: str = Field(description="新增消息")
|
||||||
|
|
||||||
|
|
||||||
|
def format_at(at: datetime) -> str:
|
||||||
|
"""
|
||||||
|
格式化日期时间
|
||||||
|
:param at: 日期时间
|
||||||
|
:return: 格式化后的日期时间字符串
|
||||||
|
"""
|
||||||
|
match (datetime.now().date() - at.date()).days:
|
||||||
|
case 0:
|
||||||
|
formatted_at = f"{at.strftime('%H:%M')}"
|
||||||
|
case 1:
|
||||||
|
formatted_at = f"昨天 {at.strftime('%H:%M')}"
|
||||||
|
case _:
|
||||||
|
formatted_at = at.strftime("%Y-%m-%d %H:%M")
|
||||||
|
return formatted_at
|
||||||
|
|
||||||
|
|
||||||
# 思考领域模型类型适配器
|
# 思考领域模型类型适配器
|
||||||
ThoughtTypeAdapter = TypeAdapter(Dict[int, Thought])
|
ThoughtTypeAdapter = TypeAdapter(Dict[int, Thought])
|
||||||
|
|
||||||
|
|
@ -221,12 +237,13 @@ class DatabaseState(rx.State):
|
||||||
.order_by(ConversationRecord.id, DialogRecord.id)
|
.order_by(ConversationRecord.id, DialogRecord.id)
|
||||||
)
|
)
|
||||||
for conversation_record, dialog_record in result.all():
|
for conversation_record, dialog_record in result.all():
|
||||||
|
|
||||||
record = records.setdefault(
|
record = records.setdefault(
|
||||||
conversation_record.id,
|
conversation_record.id,
|
||||||
Conversation(
|
Conversation(
|
||||||
id=conversation_record.id,
|
id=conversation_record.id,
|
||||||
description=conversation_record.description,
|
description=conversation_record.description,
|
||||||
created_at=conversation_record.created_at,
|
created_at=format_at(conversation_record.created_at),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
if not dialog_record:
|
if not dialog_record:
|
||||||
|
|
@ -263,7 +280,7 @@ class DatabaseState(rx.State):
|
||||||
record.id: Conversation(
|
record.id: Conversation(
|
||||||
id=record.id,
|
id=record.id,
|
||||||
description=record.description,
|
description=record.description,
|
||||||
created_at=record.created_at,
|
created_at=format_at(record.created_at),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue