This commit is contained in:
liubiren 2026-07-15 19:59:42 +08:00
parent 7d6d1d64a8
commit d1aac8762a
6 changed files with 124 additions and 66 deletions

View File

@ -1,8 +1,8 @@
"""empty message
Revision ID: 6cd382f48060
Revision ID: 51f049b860bb
Revises:
Create Date: 2026-07-13 17:24:40.090382
Create Date: 2026-07-13 22:23:49.155469
"""
from typing import Sequence, Union
@ -12,7 +12,7 @@ import sqlalchemy as sa
import sqlmodel
# revision identifiers, used by Alembic.
revision: str = '6cd382f48060'
revision: str = '51f049b860bb'
down_revision: Union[str, Sequence[str], None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None

View File

@ -20,7 +20,9 @@ app = rx.App(
"*::before, *::after": {
"box_sizing": "border-box",
},
"--prismui-background-color": "#ffffff",
"--prismui-background-color-1": "#ffffff",
"--prismui-background-color-2": "rgb(235, 235, 235)",
"--prismui-background-color-3": "#f6f6f8",
"--mc-float-block-shadow": "rgba(213, 213, 213, 0.25)",
"--devui-global-bg": "#f6f6f8",
"--mc-global-bg": "linear-gradient(to bottom, #D0C9FF 0%, #E6D6F0 8%, #F1DBEA 12%, #C8DCFB 40%, #ABC6F6 60%, #87AEFE 90%)",
@ -32,10 +34,18 @@ app = rx.App(
"--prismui-border-radius": "8px",
"--devui-border-radius-full": "100px",
"--font-family": "HuaweiFont,Helvetica,Arial,PingFangSC-Regular,Hiragino Sans GB,Microsoft YaHei,微软雅黑,Microsoft JhengHei",
"--prismui-font-size": "14px",
"--prismui-font-size-1": "14px",
"--prismui-font-size-2": "12px",
"--prismui-font-size-sm": "12px",
"--prismui-font-weight-1": "700",
"--devui-font-size": "14px",
"--devui-font-size-lg": "14px",
"--prismui-color-text": "#252b3a",
"--prismui-color-text-light": "#babbc0",
"--prismui-color-1": "#252b3a",
"--prismui-color-2": "#575d6c",
"--prismui-color-3": "#babbc0",
"--devui-text-weak": "#575d6c",
"--devui-light-text": "#ffffff",
"--placeholder": "#babbc0",

View File

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
"""
排版相关组件
"""
import reflex as rx

View File

@ -23,7 +23,7 @@ def render_conversation_history_item(
"""
# 会话激活状态
is_conversation_actived = conversation_id == ConversationState.conversation_id
is_actived = conversation_id == ConversationState.conversation_id
return rx.box(
rx.hstack(
@ -105,10 +105,10 @@ def render_conversation_history_item(
cursor="pointer",
style={
"opacity": rx.cond(
is_conversation_actived, "1", "0"
is_actived, "1", "0"
), # 若当前会话已激活则不透明,否则透明
"pointer_events": rx.cond(
is_conversation_actived, "auto", "none"
is_actived, "auto", "none"
), # 若当前会话已激活则可点击,否则不可点击
"transition": "opacity 0.18s ease",
},
@ -127,13 +127,11 @@ def render_conversation_history_item(
cursor="pointer",
style={
"background": rx.cond(
is_conversation_actived,
is_actived,
"linear-gradient(to right, #f3efff, #f3efff33, #e2f1fd33, #e2f1fd)",
"var(--devui-base-bg)",
),
"box_shadow": rx.cond(
is_conversation_actived, "2px 2px 8px #e9e9e9", "none"
),
"box_shadow": rx.cond(is_actived, "2px 2px 8px #e9e9e9", "none"),
"&:hover": {
"background": "linear-gradient(to right, #f3efff, #f3efff33, #e2f1fd33, #e2f1fd)",
"box_shadow": "2px 2px 8px #e9e9e9",
@ -313,28 +311,33 @@ def render_greeting() -> rx.Component:
)
def render_reasoning_thought_node(thought_node_id: int, thought_node: ThoughtNode):
def render_thought_node(thought_node_id: int, thought_node: ThoughtNode):
"""
渲染思考节点
:param thought_node_id: 思考节点唯一标识
:param thought_node: 思考节点实例
:return: Component
"""
return rx.hstack(
rx.vstack(
rx.box(
width="8px",
height="8px",
background_color=rx.color("blue", 7),
return rx.vstack(
rx.match(
thought_node.kind,
(
"thinking",
rx.markdown(
thought_node.content,
component_map={
"p": lambda text: rx.text(
text,
color="var(--prismui-color-text-light)",
margin="0 0 8px",
font_size="var(--prismui-font-size-sm)",
)
},
),
rx.box(width="2px", flex=1, background_color=rx.color("blue", 3)),
align_items="center",
spacing="0",
height="100%",
),
rx.markdown(thought_node.content, color=rx.color("gray", 11), padding_y="4px"),
rx.fragment(),
),
align_items="flex-start",
spacing="2",
width="100%",
key=thought_node_id,
)
@ -343,51 +346,51 @@ def render_reasoning_thought_node(thought_node_id: int, thought_node: ThoughtNod
def render_dialog_history_item(dialog_id: str, dialog: Dialog) -> rx.Component:
"""
渲染对话历史条目
:param run: 对话实例
:param dialog_id: 对话唯一标识
:param dialog: 对话实例
:return: Component
"""
# 推理状态
is_thinking = dialog.is_thinking
# 思考折叠面板展开状态
is_collapse_expanded = dialog.is_collapse_expanded
# 思考节点
thought_nodes = dialog.thought_nodes
# 推理折叠面板展开状态
is_reasoning_panel_open = dialog.is_collapse_expanded
return rx.vstack(
# 渲染问题和再次发送按钮
# 渲染问题和操作栏
rx.hstack(
rx.spacer(),
rx.vstack(
# 渲染问题
rx.markdown(
rx.text(
dialog.question,
max_width="600px",
padding="12px 16px",
background_color="var(--devui-global-bg)",
background_color="var(--prismui-background-color-3)",
border_radius="12px",
word_wrap="break-word",
word_break="break-all",
white_space="pre-line",
color="var(--prismui-color-text)",
style={
"& p.rt-Text": {
"padding": "0",
"margin": "0 !important",
},
},
),
# 再次发送按钮
# 操作栏
rx.hstack(
rx.box(
rx.icon(
"rotate-ccw",
width="14px",
height="14px",
color="var(--devui-text-weak)",
color="var(--prismui-color-2)",
),
padding="4px",
border_radius="4px",
cursor="pointer",
style={
"_hover": {
"background_color": "var(--prismui-background-color-2)",
}
},
),
width="100%",
margin_top="8px",
@ -399,31 +402,71 @@ def render_dialog_history_item(dialog_id: str, dialog: Dialog) -> rx.Component:
gap="4px",
font_size="var(--devui-font-size)",
),
# 渲染智能体思考链面板和回答
# 渲染思考折叠面板
rx.vstack(
# 标题栏
rx.box(
rx.hstack(
rx.text(
rx.cond(is_thinking, "思考中", "思考完成"),
color="var(--prismui-color-3)",
font_size="var(--prismui-font-size-2)",
),
rx.icon(
"chevron-right",
width="14px",
height="14px",
color="var(--prismui-color-3)",
style={
"transition": "transform 0.2s ease-in-out",
"transform": rx.cond(
is_collapse_expanded, "rotate(90deg)", "rotate(0deg)"
),
},
),
align_items="center",
gap="4px",
margin_bottom="8px",
line_height="22px",
),
cursor="pointer",
# 点击事件,展开/折叠思考折叠面板
on_click=lambda: ConversationState.toggle_collapse(dialog_id),
),
rx.cond(
is_collapse_expanded,
rx.auto_scroll(
rx.foreach(
thought_nodes,
lambda i, _: render_reasoning_thought_node(i[0], i[1]),
lambda i, _: render_thought_node(i[0], i[1]),
),
width="100%",
padding="0 12px",
),
rx.fragment(),
),
text_align="left",
width="100%",
margin_top="8px",
),
# 渲染回答
rx.markdown(
dialog.answer,
display="inline-block",
max_width="85%",
padding_x="1.25em",
padding_y="0.5em",
margin_left="auto",
margin_bottom="8px",
background_color=rx.color("gray", 2),
border_radius="12px",
color="var(--prismui-color-text)",
component_map={
"p": lambda text: rx.text(
text,
word_wrap="break-word",
word_break="break-all",
white_space="pre-line",
line_height="24px",
font_size="var(--prismui-font-size-1)",
color="var(--prismui-color-1)",
),
text_align="left",
"strong": lambda text: rx.text(
text,
display="inline",
font_weight="var(--prismui-font-weight-1)",
),
},
width="100%",
margin_bottom="8px",
),
@ -470,7 +513,7 @@ def render_dialog_history() -> rx.Component:
def render_create_conversation_button() -> rx.Component:
"""
渲染新建话按钮
渲染新建话按钮
:return: Component
"""
return rx.hstack(
@ -501,7 +544,7 @@ def render_create_conversation_button() -> rx.Component:
}
},
),
content="新建",
content="新建",
background_color="#ffffff",
box_shadow="0 2px 12px 0 rgba(37, 43, 58, .24)",
color="#252b3a",
@ -524,11 +567,11 @@ def render_create_conversation_button() -> rx.Component:
rx.hstack(
rx.input(
name="description",
placeholder="请输入话描述",
placeholder="请输入话描述",
flex="auto",
min_width="20ch",
),
rx.button(""),
rx.button(""),
spacing="2",
wrap="wrap",
width="100%",
@ -711,7 +754,7 @@ def render_conversation_history_collapse_button(
z_index=99,
width="16px",
height="40px",
background="var(--prismui-background-color)",
background="var(--prismui-background-color-1)",
box_shadow="2px 0 4px 0 var(--mc-float-block-shadow)",
border_radius=rx.cond(is_collapse_expanded, "6px", "0 6px 6px 0"),
transition="all 0.3s ease-in-out",

View File

@ -395,9 +395,9 @@ class ConversationState(rx.State):
yield
@rx.event
def toggle_reasoning_panel(self, dialog_id: str) -> None:
def toggle_collapse(self, dialog_id: str) -> None:
"""
展开/折叠指定运行唯一标识的推理面板
展开/折叠思考折叠面板
"""
# 指定运行
dialog = self.conversations[self.conversation_id].dialogs[dialog_id]

BIN
agent/database.db Normal file

Binary file not shown.