This commit is contained in:
parent
7d6d1d64a8
commit
d1aac8762a
|
|
@ -1,8 +1,8 @@
|
||||||
"""empty message
|
"""empty message
|
||||||
|
|
||||||
Revision ID: 6cd382f48060
|
Revision ID: 51f049b860bb
|
||||||
Revises:
|
Revises:
|
||||||
Create Date: 2026-07-13 17:24:40.090382
|
Create Date: 2026-07-13 22:23:49.155469
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
@ -12,7 +12,7 @@ import sqlalchemy as sa
|
||||||
import sqlmodel
|
import sqlmodel
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = '6cd382f48060'
|
revision: str = '51f049b860bb'
|
||||||
down_revision: Union[str, Sequence[str], None] = None
|
down_revision: Union[str, Sequence[str], None] = None
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
@ -20,7 +20,9 @@ app = rx.App(
|
||||||
"*::before, *::after": {
|
"*::before, *::after": {
|
||||||
"box_sizing": "border-box",
|
"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)",
|
"--mc-float-block-shadow": "rgba(213, 213, 213, 0.25)",
|
||||||
"--devui-global-bg": "#f6f6f8",
|
"--devui-global-bg": "#f6f6f8",
|
||||||
"--mc-global-bg": "linear-gradient(to bottom, #D0C9FF 0%, #E6D6F0 8%, #F1DBEA 12%, #C8DCFB 40%, #ABC6F6 60%, #87AEFE 90%)",
|
"--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",
|
"--prismui-border-radius": "8px",
|
||||||
"--devui-border-radius-full": "100px",
|
"--devui-border-radius-full": "100px",
|
||||||
"--font-family": "HuaweiFont,Helvetica,Arial,PingFangSC-Regular,Hiragino Sans GB,Microsoft YaHei,微软雅黑,Microsoft JhengHei",
|
"--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-size-sm": "12px",
|
||||||
|
"--prismui-font-weight-1": "700",
|
||||||
"--devui-font-size": "14px",
|
"--devui-font-size": "14px",
|
||||||
"--devui-font-size-lg": "14px",
|
"--devui-font-size-lg": "14px",
|
||||||
"--prismui-color-text": "#252b3a",
|
"--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-text-weak": "#575d6c",
|
||||||
"--devui-light-text": "#ffffff",
|
"--devui-light-text": "#ffffff",
|
||||||
"--placeholder": "#babbc0",
|
"--placeholder": "#babbc0",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
排版相关组件
|
||||||
|
"""
|
||||||
|
import reflex as rx
|
||||||
|
|
@ -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(
|
return rx.box(
|
||||||
rx.hstack(
|
rx.hstack(
|
||||||
|
|
@ -105,10 +105,10 @@ def render_conversation_history_item(
|
||||||
cursor="pointer",
|
cursor="pointer",
|
||||||
style={
|
style={
|
||||||
"opacity": rx.cond(
|
"opacity": rx.cond(
|
||||||
is_conversation_actived, "1", "0"
|
is_actived, "1", "0"
|
||||||
), # 若当前会话已激活则不透明,否则透明
|
), # 若当前会话已激活则不透明,否则透明
|
||||||
"pointer_events": rx.cond(
|
"pointer_events": rx.cond(
|
||||||
is_conversation_actived, "auto", "none"
|
is_actived, "auto", "none"
|
||||||
), # 若当前会话已激活则可点击,否则不可点击
|
), # 若当前会话已激活则可点击,否则不可点击
|
||||||
"transition": "opacity 0.18s ease",
|
"transition": "opacity 0.18s ease",
|
||||||
},
|
},
|
||||||
|
|
@ -127,13 +127,11 @@ def render_conversation_history_item(
|
||||||
cursor="pointer",
|
cursor="pointer",
|
||||||
style={
|
style={
|
||||||
"background": rx.cond(
|
"background": rx.cond(
|
||||||
is_conversation_actived,
|
is_actived,
|
||||||
"linear-gradient(to right, #f3efff, #f3efff33, #e2f1fd33, #e2f1fd)",
|
"linear-gradient(to right, #f3efff, #f3efff33, #e2f1fd33, #e2f1fd)",
|
||||||
"var(--devui-base-bg)",
|
"var(--devui-base-bg)",
|
||||||
),
|
),
|
||||||
"box_shadow": rx.cond(
|
"box_shadow": rx.cond(is_actived, "2px 2px 8px #e9e9e9", "none"),
|
||||||
is_conversation_actived, "2px 2px 8px #e9e9e9", "none"
|
|
||||||
),
|
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
"background": "linear-gradient(to right, #f3efff, #f3efff33, #e2f1fd33, #e2f1fd)",
|
"background": "linear-gradient(to right, #f3efff, #f3efff33, #e2f1fd33, #e2f1fd)",
|
||||||
"box_shadow": "2px 2px 8px #e9e9e9",
|
"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_id: 思考节点唯一标识
|
||||||
:param thought_node: 思考节点实例
|
:param thought_node: 思考节点实例
|
||||||
:return: Component
|
:return: Component
|
||||||
"""
|
"""
|
||||||
return rx.hstack(
|
return rx.vstack(
|
||||||
rx.vstack(
|
rx.match(
|
||||||
rx.box(
|
thought_node.kind,
|
||||||
width="8px",
|
(
|
||||||
height="8px",
|
"thinking",
|
||||||
background_color=rx.color("blue", 7),
|
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)),
|
rx.fragment(),
|
||||||
align_items="center",
|
|
||||||
spacing="0",
|
|
||||||
height="100%",
|
|
||||||
),
|
),
|
||||||
rx.markdown(thought_node.content, color=rx.color("gray", 11), padding_y="4px"),
|
|
||||||
align_items="flex-start",
|
align_items="flex-start",
|
||||||
spacing="2",
|
|
||||||
width="100%",
|
width="100%",
|
||||||
key=thought_node_id,
|
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:
|
def render_dialog_history_item(dialog_id: str, dialog: Dialog) -> rx.Component:
|
||||||
"""
|
"""
|
||||||
渲染对话历史条目
|
渲染对话历史条目
|
||||||
:param run: 对话实例
|
:param dialog_id: 对话唯一标识
|
||||||
|
:param dialog: 对话实例
|
||||||
:return: Component
|
:return: Component
|
||||||
"""
|
"""
|
||||||
# 推理状态
|
# 推理状态
|
||||||
is_thinking = dialog.is_thinking
|
is_thinking = dialog.is_thinking
|
||||||
|
# 思考折叠面板展开状态
|
||||||
|
is_collapse_expanded = dialog.is_collapse_expanded
|
||||||
# 思考节点
|
# 思考节点
|
||||||
thought_nodes = dialog.thought_nodes
|
thought_nodes = dialog.thought_nodes
|
||||||
|
|
||||||
# 推理折叠面板展开状态
|
|
||||||
is_reasoning_panel_open = dialog.is_collapse_expanded
|
|
||||||
|
|
||||||
return rx.vstack(
|
return rx.vstack(
|
||||||
# 渲染问题和再次发送按钮
|
# 渲染问题和操作栏
|
||||||
rx.hstack(
|
rx.hstack(
|
||||||
rx.spacer(),
|
rx.spacer(),
|
||||||
rx.vstack(
|
rx.vstack(
|
||||||
# 渲染问题
|
# 渲染问题
|
||||||
rx.markdown(
|
rx.text(
|
||||||
dialog.question,
|
dialog.question,
|
||||||
max_width="600px",
|
max_width="600px",
|
||||||
padding="12px 16px",
|
padding="12px 16px",
|
||||||
background_color="var(--devui-global-bg)",
|
background_color="var(--prismui-background-color-3)",
|
||||||
border_radius="12px",
|
border_radius="12px",
|
||||||
word_wrap="break-word",
|
word_wrap="break-word",
|
||||||
word_break="break-all",
|
word_break="break-all",
|
||||||
|
white_space="pre-line",
|
||||||
color="var(--prismui-color-text)",
|
color="var(--prismui-color-text)",
|
||||||
style={
|
|
||||||
"& p.rt-Text": {
|
|
||||||
"padding": "0",
|
|
||||||
"margin": "0 !important",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
# 再次发送按钮
|
# 操作栏
|
||||||
rx.hstack(
|
rx.hstack(
|
||||||
rx.box(
|
rx.box(
|
||||||
rx.icon(
|
rx.icon(
|
||||||
"rotate-ccw",
|
"rotate-ccw",
|
||||||
width="14px",
|
width="14px",
|
||||||
height="14px",
|
height="14px",
|
||||||
color="var(--devui-text-weak)",
|
color="var(--prismui-color-2)",
|
||||||
),
|
),
|
||||||
padding="4px",
|
padding="4px",
|
||||||
border_radius="4px",
|
border_radius="4px",
|
||||||
cursor="pointer",
|
cursor="pointer",
|
||||||
|
style={
|
||||||
|
"_hover": {
|
||||||
|
"background_color": "var(--prismui-background-color-2)",
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
width="100%",
|
width="100%",
|
||||||
margin_top="8px",
|
margin_top="8px",
|
||||||
|
|
@ -399,32 +402,72 @@ def render_dialog_history_item(dialog_id: str, dialog: Dialog) -> rx.Component:
|
||||||
gap="4px",
|
gap="4px",
|
||||||
font_size="var(--devui-font-size)",
|
font_size="var(--devui-font-size)",
|
||||||
),
|
),
|
||||||
# 渲染智能体思考链面板和回答
|
# 渲染思考折叠面板
|
||||||
rx.vstack(
|
rx.vstack(
|
||||||
|
# 标题栏
|
||||||
rx.auto_scroll(
|
rx.box(
|
||||||
rx.foreach(
|
rx.hstack(
|
||||||
thought_nodes,
|
rx.text(
|
||||||
lambda i, _: render_reasoning_thought_node(i[0], i[1]),
|
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",
|
||||||
),
|
),
|
||||||
width="100%",
|
cursor="pointer",
|
||||||
padding="0 12px",
|
# 点击事件,展开/折叠思考折叠面板
|
||||||
|
on_click=lambda: ConversationState.toggle_collapse(dialog_id),
|
||||||
),
|
),
|
||||||
# 渲染回答
|
rx.cond(
|
||||||
rx.markdown(
|
is_collapse_expanded,
|
||||||
dialog.answer,
|
rx.auto_scroll(
|
||||||
display="inline-block",
|
rx.foreach(
|
||||||
max_width="85%",
|
thought_nodes,
|
||||||
padding_x="1.25em",
|
lambda i, _: render_thought_node(i[0], i[1]),
|
||||||
padding_y="0.5em",
|
),
|
||||||
margin_left="auto",
|
width="100%",
|
||||||
margin_bottom="8px",
|
),
|
||||||
background_color=rx.color("gray", 2),
|
rx.fragment(),
|
||||||
border_radius="12px",
|
|
||||||
color="var(--prismui-color-text)",
|
|
||||||
),
|
),
|
||||||
text_align="left",
|
text_align="left",
|
||||||
width="100%",
|
width="100%",
|
||||||
|
margin_top="8px",
|
||||||
|
),
|
||||||
|
# 渲染回答
|
||||||
|
rx.markdown(
|
||||||
|
dialog.answer,
|
||||||
|
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)",
|
||||||
|
),
|
||||||
|
"strong": lambda text: rx.text(
|
||||||
|
text,
|
||||||
|
display="inline",
|
||||||
|
font_weight="var(--prismui-font-weight-1)",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
width="100%",
|
||||||
margin_bottom="8px",
|
margin_bottom="8px",
|
||||||
),
|
),
|
||||||
width="100%",
|
width="100%",
|
||||||
|
|
@ -470,7 +513,7 @@ def render_dialog_history() -> rx.Component:
|
||||||
|
|
||||||
def render_create_conversation_button() -> rx.Component:
|
def render_create_conversation_button() -> rx.Component:
|
||||||
"""
|
"""
|
||||||
渲染新建对话按钮
|
渲染新建会话按钮
|
||||||
:return: Component
|
:return: Component
|
||||||
"""
|
"""
|
||||||
return rx.hstack(
|
return rx.hstack(
|
||||||
|
|
@ -501,7 +544,7 @@ def render_create_conversation_button() -> rx.Component:
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
content="新建对话",
|
content="新建会话",
|
||||||
background_color="#ffffff",
|
background_color="#ffffff",
|
||||||
box_shadow="0 2px 12px 0 rgba(37, 43, 58, .24)",
|
box_shadow="0 2px 12px 0 rgba(37, 43, 58, .24)",
|
||||||
color="#252b3a",
|
color="#252b3a",
|
||||||
|
|
@ -524,11 +567,11 @@ def render_create_conversation_button() -> rx.Component:
|
||||||
rx.hstack(
|
rx.hstack(
|
||||||
rx.input(
|
rx.input(
|
||||||
name="description",
|
name="description",
|
||||||
placeholder="请输入对话描述",
|
placeholder="请输入会话描述",
|
||||||
flex="auto",
|
flex="auto",
|
||||||
min_width="20ch",
|
min_width="20ch",
|
||||||
),
|
),
|
||||||
rx.button("创建"),
|
rx.button("新建"),
|
||||||
spacing="2",
|
spacing="2",
|
||||||
wrap="wrap",
|
wrap="wrap",
|
||||||
width="100%",
|
width="100%",
|
||||||
|
|
@ -711,7 +754,7 @@ def render_conversation_history_collapse_button(
|
||||||
z_index=99,
|
z_index=99,
|
||||||
width="16px",
|
width="16px",
|
||||||
height="40px",
|
height="40px",
|
||||||
background="var(--prismui-background-color)",
|
background="var(--prismui-background-color-1)",
|
||||||
box_shadow="2px 0 4px 0 var(--mc-float-block-shadow)",
|
box_shadow="2px 0 4px 0 var(--mc-float-block-shadow)",
|
||||||
border_radius=rx.cond(is_collapse_expanded, "6px", "0 6px 6px 0"),
|
border_radius=rx.cond(is_collapse_expanded, "6px", "0 6px 6px 0"),
|
||||||
transition="all 0.3s ease-in-out",
|
transition="all 0.3s ease-in-out",
|
||||||
|
|
|
||||||
|
|
@ -395,9 +395,9 @@ class ConversationState(rx.State):
|
||||||
yield
|
yield
|
||||||
|
|
||||||
@rx.event
|
@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]
|
dialog = self.conversations[self.conversation_id].dialogs[dialog_id]
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue