拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Yuxi Dashboard 架构分层与会话多维分析实战:从 Thin Router 到 Thread Analytics

Yuxi Dashboard 架构分层与会话多维分析实战从 Thin Router 到 Thread Analytics【免费下载链接】Yuxi可私有部署的多租户知识智能体平台统一 RAG、知识图谱、多智能体、MCP/Skills、沙盒与权限管理。Self-hosted knowledge agent platform for RAG, knowledge graphs and multi-agent workflows.项目地址: https://gitcode.com/GitHub_Trending/yu/Yuxi本指南围绕 Yuxi 项目的架构决策文档docs/develop-guides/decisions/implemented/2026-08-24-dashboard-architecture-and-thread-analytics.md展开系统讲解 Dashboard 从路由直接聚合数据重构为Thin Router - Service - Repository三层架构的全过程以及新增的会话Thread多维分析统计与审计能力的实现原理。读完本文你将掌握 Yuxi 后台统计模块的完整调用链、会话分析 API 的每个参数与响应字段、SQL 批量聚合的关键写法以及前后端多 Tab 审计工作台的落地方式可直接用于二次开发或部署后的运营分析。背景Dashboard 的三类历史问题在本次架构决策之前Yuxi 的 Dashboard 模块存在三个相互关联的问题构成了本次重构的直接动因接口与架构分层不清dashboard_router.py直接承载跨表聚合与数据组装逻辑不符合项目的 Thin Router 规范知识库统计接口碎片化分散在多个入口。知识库文件统计查询低效且路径不当knowledge_dashboard_service.py此前遍历所有知识库并循环加载全量文件对象N1 内存加载未在 SQL 层直接聚合且缺乏对虚拟目录的准确过滤——文件夹记录会被当作普通文件计入统计。展示维度单一且未充分利用会话数据既有会话查询接口缺少对应的前端展示与审计入口管理员无法直观获知全平台会话的增长动态、互动轮数深度、智能体承载与高频用户分布。这三类问题的本质是统计读模型缺少独立分层导致查询路径低效、展示维度受限、运营视角缺失。决策文档给出的解法是后端分层重构 会话多维分析能力 前端多 Tab 工作台三管齐下。决策一重构后端分层Thin Router - Service - Repository1.1 新建 DashboardService 集中承载用例决策在 backend/package/yuxi/services/dashboard_service.py 新建DashboardService集中承载基础统计、调用时序、智能体分析、会话检索与会话多维分析五类用例get_basic_stats()基础统计指标会话数、消息数、用户数、满意度get_user_activity_stats()用户总量与活跃趋势get_tool_call_stats()工具调用总量、成功率与分布get_agent_analytics()智能体对话、满意度与工具使用情况get_call_timeseries()调用分析时间序列get_thread_analytics()会话多维分析汇总list_conversations()/get_conversation_detail()会话审计分页列表与详情流水。从源码结构看Service 层只做依赖注入 业务用例编排其内部构造仅持有DashboardRepository与ConversationRepository两个数据访问对象跨表聚合逻辑全部下沉到 Repositoryclass DashboardService: def __init__(self, db: AsyncSession): self.db db self.repo DashboardRepository(db) self.conv_repo ConversationRepository(db)1.2 路由层保持轻量backend/server/routers/dashboard_router.py 中的dashboard路由组APIRouter(prefix/dashboard, tags[Dashboard])现在只负责三件事依赖注入通过Depends(get_db)获取会话、Depends(get_superadmin_user)校验超级管理员权限参数校验使用Literal约束枚举值、Query约束范围Pydantic 模型装配把 Repository/Service 返回的 dict 装配为带类型声明的响应模型。例如会话多维分析的入口dashboard.get(/stats/threads, response_modelThreadAnalyticsResponse) async def get_thread_analytics_stats( time_range: Literal[7days, 14days, 30days, 90days] 30days, agent_id: str | None None, include_subagents: bool Query(False, description是否将子智能体会话纳入统计), db: AsyncSession Depends(get_db), current_user: User Depends(get_superadmin_user), ): data await DashboardService(db).get_thread_analytics( time_rangetime_range, agent_idagent_id, include_subagentsinclude_subagents, ) return ThreadAnalyticsResponse(**data)ThreadAnalyticsResponse完整定义了响应的六个区块summary、daily_trends、depth_distribution、agent_distribution、top_users、status_distribution。所有路由的权限模型一致全部挂get_superadmin_user即只有超级管理员可以访问 Dashboard 全部统计与审计接口这是多租户私有部署下的安全基线。1.3 知识库统计改为 SQL 批量聚合决策同时优化了 backend/package/yuxi/services/knowledge_dashboard_service.pyService 只做业务展示映射聚合交给 Repository。数据库层的关键实现在KnowledgeFileRepository.aggregate_dashboard_stats()backend/package/yuxi/repositories/knowledge_file_repository.py它用一条 SQL 完成文件类型分布、节点数与存储容量计算result await session.execute( select( KnowledgeFile.file_type, func.count(KnowledgeFile.file_id), func.coalesce(func.sum(KnowledgeFile.file_size), 0), func.coalesce(func.sum(KnowledgeFile.chunk_count), 0), ) .where(or_(KnowledgeFile.is_folder.is_(False), KnowledgeFile.is_folder.is_(None))) .group_by(KnowledgeFile.file_type) )注意is_folder的过滤条件False与NULL都被视为普通文件纳入统计这正对应决策中将历史is_folder NULL记录按普通文件处理的要求——历史遗留记录不会因字段缺失而漏统计虚拟目录is_folder True则被准确排除。Service 层随后将原始扩展名映射为可读的中文类型名FILE_TYPE_MAPPING覆盖 txt/pdf/docx/md/html/json/csv/xlsx/pptx/常见图片音视频与压缩包数据库类型同理映射为 FAISS、Milvus、Dify、Qdrant、Elasticsearch 等展示名DATABASE_TYPE_MAPPING。单批 SQL 聚合彻底消除了原先遍历知识库 循环加载全量文件对象的 N1 内存加载隐患。决策二会话多维分析统计与检索能力这是本次决策的核心增量。DashboardRepository.get_thread_analytics()backend/package/yuxi/repositories/dashboard_repository.py一次查询返回六大维度的统计。2.1 核心指标汇总summarysummary区块提供运营最关心的总量指标字段含义total_threads总会话数active_threads活跃会话数时间范围内有新消息的会话数total_messages总消息数排除审计类消息类型total_tokens总 Token 消耗Run 实测用量优先无 Run 时回退历史ConversationStatsavg_messages_per_thread平均对话轮数total_messages / total_threadsavg_tokens_per_thread平均 Token 消耗pinned_threads置顶会话数Token 汇总的实现值得关注_conversation_token_totals()通过子查询按会话汇总AgentRun.token_usage中的实测用量只采纳已上报调用数或complete 标记的 Run缺失时回退ConversationStats.total_tokens——既反映真实计费用量又兼容无 Run 记录的历史数据。2.2 每日增长与活跃时序daily_trendsdaily_trends每天输出date、new_threads当日新建会话数、active_threads当日有消息的会话数、message_count当日消息量。关键设计是按上海日历日批量聚合_shanghai_date_group()在 PostgreSQL 上用func.date(column INTERVAL 8 hours)生成按 UTC8 对齐的日期分组表达式SQLite 则退化为func.date(column, 8 hours)保证本地时区的日界正确。决策明确要求每日趋势按上海日历日使用批量聚合查询而不是随 7/14/30/90 天范围逐日执行 SQL。对应测试 backend/test/unit/services/test_dashboard_service.py 中test_thread_analytics_query_count_does_not_grow_with_time_range验证了这一点无论时间范围取 7 天还是 90 天SQL 执行次数都保持恒定——聚合后仅在 Python 侧补齐空日期避免查询次数随时间范围线性放大。2.3 对话深度分布depth_distributiondepth_distribution按每个会话的消息数来自ConversationStats.message_count缺失按 0 处理分桶统计0 条、1-2 条、3-5 条、6-10 条、11-20 条、20 条实现上使用单条 SQL 的六个CASE WHEN条件求和一次往返完成全部分桶而不是逐桶查询。这个维度直接回答平台会话是浅尝辄止还是深入多轮的问题是评估智能体粘性的核心指标。2.4 智能体分布与高频用户榜agent_distribution按agent_id分组输出thread_count、message_count、token_count、avg_messages及展示用agent_name/agent_avatar按会话数降序top_users高频用户活跃榜Top 10包含thread_count、message_count与last_active_at最近活跃时间。两个维度都通过AgentRepository.list_by_slugs一次性装配名称与头像避免逐条查询。2.5 运营统计的统一口径决策强调运营统计统一排除已注销用户、已删除会话与已删除智能体。这一点贯穿所有聚合查询例如conversation_filters恒包含status_filter ( Conversation.status ! deleted if include_subagents else Conversation.status.notin_((deleted, subagent)) ) conversation_filters [ Conversation.created_at.isnot(None), status_filter, User.is_deleted 0, ] if agent_id: conversation_filters.append(Conversation.agent_id agent_id)agent_id过滤统一约束汇总、趋势、深度、排行与状态分布——一旦传入某个智能体所有区块同步收窄到该智能体保证口径一致。include_subagents参数则控制子智能体会话是否纳入统计。2.6 会话审计检索list_conversationslist_conversations从仅看活跃会话升级为默认展示全部状态以服务审计场景backend/package/yuxi/repositories/dashboard_repository.py支持uid、agent_id、statusactive/archived/deleted/subagent/all、search关键词过滤search同时匹配会话标题、thread_id、用户 uid 与用户名ilike模糊查询使用func.count独立统计真实总数total配合limit/offset实现真实总数分页而非数组长度伪造每条记录通过user_deleted、agent_deleted标记标注已注销用户、已删除会话和已删除智能体并回退展示 uid/slug 原文保证审计时身份信息不丢失会话详情get_conversation_detail(thread_id)返回完整消息流水每条消息附带role、content、token_count及嵌套的tool_calls工具名、输入、输出、状态、错误信息管理员可实时查看请求流水与工具执行详情。决策三前端多 Tab 布局与会话审计工作台前端重构在 web/src/views/DashboardView.vue 落地为系统概览 / 会话分析双 Tab 工作台。3.1 Tab 状态与 URL 同步使用全站共享PageHeader组件承载 Tabv-model:active-key绑定activeTabTab 配置为[{ key: overview, ... }, { key: threads, label: 会话分析 }]Tab 状态同步到 URL通过watch(activeTab)将?tabthreads写入route.queryoverview 时删除该参数页面刷新或分享链接后可直接恢复对应 Tab见normalizeTab的归一化逻辑首次激活后保留图表实例overviewActivated/threadActivated标记保证组件只挂载一次后续用v-show切换显示避免重复重建与隐藏容器初始化规避图表销毁泄漏。3.2 两个 Tab 的职责划分Tab 1系统概览保留并优化基础 KPI 概览、调用时序监控、用户活跃度、智能体分析、工具调用监控与知识库使用情况Tab 2会话分析试点呈现 4 张核心指标卡 2x2 可视化图表网格增长趋势、深度分布、智能体排行、高频用户榜下方是全平台会话审计表格支持关键词/状态/Agent/用户筛选点击任意会话打开右侧交互抽屉查看请求流水与工具执行详情长标识uid、agent_id、thread_id省略展示并保留完整 tooltip。前端 API 封装位于 web/src/apis/dashboard_api.js其中getThreadStats支持timeRange7days/14days/30days/90days、agentId、includeSubagents三个参数getConversations/getConversationOptions/getConversationDetail对应审计列表、筛选项与详情。整体 UI 统一遵循系统设计 Token--gray-*、--main-*、语义色严格适配深浅色与自适应断点。替代方案与取舍决策文档记录了被否决的两条路径理解它们有助于把握最终方案的边界在原有单页继续追加所有图表页面过长且认知负荷极重无法清晰区分系统运行时监控与业务会话分析与审计因此选择多 Tab 拆分解耦在应用层遍历或逐日查询会话统计数据量或时间范围增大时会造成明显的 IO 与延迟因此选择在 PostgreSQL/SQLAlchemy 读模型层批量聚合后补齐空日期——这也是读模型下沉到 SQL这一模式的核心动机。后果与验证重构带来的直接收益Dashboard 路由与服务实现严格解耦消除了知识库统计的 N1 文件查询隐患超级管理员获得会话深度分析与交互审计能力可点击任意会话实时查看请求流水与工具执行详情前后端均通过类型检查、规范测试与构建校验。决策文档附带的验收矩阵定义了四个可执行的验证入口验收主张失败面语义 Owner直接证据 / 命令路由仅作为薄适配层业务逻辑下沉至 Service路由内出现直接仓库组装或跨表计算backend/server/routers/dashboard_router.pyuv run --group test pytest test/unit/services/test_dashboard_service.py知识库统计使用 SQL 聚合且排除文件夹虚拟目录被计入文件数或 N1 循环回退backend/package/yuxi/services/knowledge_dashboard_service.pyuv run --group test pytest test/integration/api/test_dashboard_router.py会话多维分析统计与审计抽屉正常加载时序或深度分布维度缺失或无法展开工具调用web/src/components/dashboard/ThreadStatsComponent.vuepnpm run lint:checkpnpm run buildnode --test test/**/*.test.js会话趋势与分页不会随范围线性放大 SQL 或伪造总数90 天趋势逐日查询末页与下一页判断错误backend/package/yuxi/repositories/dashboard_repository.pyuv run --group test pytest test/unit/services/test_dashboard_service.py真实 HTTP integration测试侧的关键用例backend/test/unit/services/test_dashboard_service.py包括test_dashboard_service_thread_analytics多维统计契约、test_thread_analytics_groups_daily_trends_by_shanghai_date上海日历日分桶、test_thread_analytics_query_count_does_not_grow_with_time_rangeSQL 次数恒定、test_conversation_tokens_use_runs_and_expose_missing_usageToken 实测用量与缺失标记从测试命名即可看出每个架构承诺都有对应契约守护。会话分析 API 快速参考/api/dashboard/stats/threads是本次重构的核心接口完整参数与响应结构如下请求参数参数取值默认值说明time_range7days/14days/30days/90days30days统计时间范围agent_id智能体 slug无按智能体过滤统一约束汇总/趋势/深度/排行/状态分布include_subagentstrue/falsefalse是否将子智能体会话纳入统计响应结构{ summary: { total_threads: 0, active_threads: 0, total_messages: 0, total_tokens: 0, avg_messages_per_thread: 0.0, avg_tokens_per_thread: 0, pinned_threads: 0 }, daily_trends: [ { date: 2026-08-01, new_threads: 0, active_threads: 0, message_count: 0 } ], depth_distribution: { 0 条: 0, 1-2 条: 0, 3-5 条: 0, 6-10 条: 0, 11-20 条: 0, 20 条: 0 }, agent_distribution: [ { agent_id: , agent_name: , thread_count: 0, message_count: 0, token_count: 0, avg_messages: 0.0, agent_avatar: null } ], top_users: [ { uid: , username: null, avatar: null, thread_count: 0, message_count: 0, last_active_at: null } ], status_distribution: { active: 0 } }审计侧配套接口GET /api/dashboard/conversations/options提供用户与 Agent 筛选项已删除的排在末尾GET /api/dashboard/conversations支持uid/agent_id/status/search/limit/offsetlimit上限 200、search最长 255 字符GET /api/dashboard/conversations/{thread_id}返回完整消息流水与工具调用明细。所有接口均需超级管理员权限。小结本次 Dashboard 架构重构的完整脉络可以概括为读模型分层Router 变薄、Service 管用例、Repository 管 SQL 聚合→ 能力补全会话多维分析 审计检索→ 前端工作台化多 Tab URL 状态 惰性激活。其中上海日历日批量聚合 空日期补齐与实测 Token 用量回退历史两处设计分别解决了统计扩展性与数据可信度问题是同类后台统计模块可以直接借鉴的实现范式。部署 Yuxi 后管理员可在会话分析Tab 中直接观察全平台会话增长、轮数深度与高频用户分布并可下钻到任意会话的逐条消息与工具执行记录完成交互审计。【免费下载链接】Yuxi可私有部署的多租户知识智能体平台统一 RAG、知识图谱、多智能体、MCP/Skills、沙盒与权限管理。Self-hosted knowledge agent platform for RAG, knowledge graphs and multi-agent workflows.项目地址: https://gitcode.com/GitHub_Trending/yu/Yuxi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门