ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

LLM Zoomcamp 监控实战:在 Streamlit 仪表盘上可视化用户反馈与判官相关性评分

LLM Zoomcamp 监控实战:在 Streamlit 仪表盘上可视化用户反馈与判官相关性评分 LLM Zoomcamp 监控实战在 Streamlit 仪表盘上可视化用户反馈与判官相关性评分【免费下载链接】llm-zoomcampLLM Zoomcamp - a free online course about real-life applications of LLMs. In 10 weeks you will learn how to build an AI system that answers questions about your knowledge base. Register here 项目地址: https://gitcode.com/GitHub_Trending/ll/llm-zoomcamp反馈仪表盘是 LLM Zoomcamp 2026 期监控模块Module 5的核心一课前几课我们已经通过1/-1按钮收集了用户对回答的赞踩又用 LLM 判官为每条回答自动打上相关性标签但这两类信号至今还只躺在 PostgreSQL 的feedback表里没有任何可视化。本文讲解如何把这两类反馈接到第 07 课搭建的 Streamlit 仪表盘上让成本、延迟、质量三组指标同屏展示并说明为什么下一步需要合成数据来让图表活起来。读完你将掌握在db_query.py中编写反馈聚合查询、在dashboard.py中渲染相关性分布柱状图与赞踩计数指标以及完整的数据链路写入 → 查询 → 展示。两类反馈的来龙去脉到第 09 课为止系统中已经存在两种截然不同的反馈来源它们被统一写入同一张feedback表靠source列区分用户反馈source user第 08 课在聊天应用中为每条回答下方添加了1/-1按钮点击后通过 db_feedback.py 的save_feedback(conversation_id, user, score1)写入score字段1 代表赞-1 代表踩判官反馈source judge第 09 课内置了 LLM 判官judge.py每次回答后用结构化输出返回RELEVANT/PARTLY_RELEVANT/NON_RELEVANT三档标签及解释写入relevance与explanation字段。这张表的完整结构定义在 db_init.py 的init_feedback()中CREATE TABLE feedback ( id SERIAL PRIMARY KEY, conversation_id INTEGER REFERENCES conversations(id), source TEXT NOT NULL, relevance TEXT, explanation TEXT, score INTEGER, timestamp TIMESTAMP WITH TIME ZONE NOT NULL )从源码结构看这一设计刻意让两类反馈共用一张表用户给出的是二元极性赞/踩判官给出的是三档相关性标签而conversation_id外键把每条反馈精确绑定到某一次对话。这样一来仪表盘既能单独统计两类信号未来也能把用户说好与判官说相关做交叉比对。问题在于数据一直在写却没有任何地方能看到它们。第 07 课的仪表盘只展示了总对话数、平均响应时间、总成本、平均 token 数以及成本和延迟的时间序列反馈数据对运维人员完全不可见。本课要做的就是把这两个维度补上。第一步给 db_query.py 添加反馈聚合查询所有仪表盘数据都经由 db_query.py 统一封装数据库访问。该文件已有的get_conversations()拉取最近对话和get_stats()聚合统计沿用了统一的获取连接 → 执行 SQL → 关闭连接模式其中get_db_connection()来自db_init.py通过环境变量POSTGRES_HOST、POSTGRES_DB、POSTGRES_USER、POSTGRES_PASSWORD配置连接默认值分别为localhost、course_assistant、user、password。现在按同样的模式添加两个反馈查询函数。判官相关性分布get_relevance_stats()按relevance标签分组计数只统计source judge的行def get_relevance_stats(): conn get_db_connection() try: with conn.cursor() as cur: cur.execute( SELECT relevance, COUNT(*) FROM feedback WHERE source judge GROUP BY relevance ) rows cur.fetchall() finally: conn.close() return dict(rows)返回的是一个形如{RELEVANT: 12, PARTLY_RELEVANT: 5, NON_RELEVANT: 3}的字典——键是相关性标签值是出现次数。这个结构恰好能直接喂给 Streamlit 的st.bar_chart。用户赞踩统计get_user_feedback_stats()用两个条件聚合分别统计赞与踩的数量只统计source user的行def get_user_feedback_stats(): conn get_db_connection() try: with conn.cursor() as cur: cur.execute( SELECT SUM(CASE WHEN score 0 THEN 1 ELSE 0 END), SUM(CASE WHEN score 0 THEN 1 ELSE 0 END) FROM feedback WHERE source user ) row cur.fetchone() finally: conn.close() return row返回值是一个二元组(thumbs_up, thumbs_down)。注意这里的语义约定score 0即 1赞score 0即 -1踩这一约定与第 08 课save_feedback(conversation_id, user, score1)的调用方式一一对应字段级含义可回看 08-user-feedback.md。两个函数都严格遵循了finally: conn.close()的写法确保无论查询成功与否连接都会被释放——这是本模块所有数据库访问代码的通用防御性模式。第二步把反馈面板接入 dashboard.py接下来修改 dashboard.py。该文件当前结构为顶部四列metric展示汇总指标中部用st.line_chart绘制成本与响应时间的时间序列底部用纯文本列出最近对话prompt[:80]、answer[:200]截断。我们要在保留这些内容的基础上追加反馈面板。更新 import把两个新函数加进导入语句from db_query import get_conversations, get_stats, get_relevance_stats, get_user_feedback_stats判官相关性分布在页面合适位置例如成本/延迟图表之后添加st.subheader(Judge relevance) relevance get_relevance_stats() st.bar_chart(relevance)st.bar_chart会把字典的键作为横轴类别、值作为柱高三档相关性标签的分布一眼可见。当判官给出的NON_RELEVANT占比升高时通常意味着检索质量或提示词出了问题——这正是自动质量信号的价值不需要等用户点击每条回答都会产生一个可观测的质量标签。用户反馈紧随其后添加st.subheader(User feedback) thumbs_up, thumbs_down get_user_feedback_stats() col1, col2 st.columns(2) col1.metric(Thumbs up, int(thumbs_up or 0)) col2.metric(Thumbs down, int(thumbs_down or 0))thumbs_up or 0的写法是为了防御SUM在空表上返回None没有匹配行时聚合结果为 NULLint()则把 SQL 返回的数值转成 Streamlit 指标可接受的原生类型。两个metric并排展示赞踩总数语义与 ChatGPT 等产品中的反馈计数一致。运行仪表盘由于聊天应用已经占用了 8501 端口对应第 03 课仪表盘需要用独立端口启动uv run streamlit run dashboard.py --server.port 8502运行前提是本模块前面课程已完成PostgreSQL 已通过 Docker 启动、uv run python db_init.py已初始化conversations与feedback表、generate_data.py或真实对话已产生数据。若尚未安装依赖可参考 Makefile 中的项目定义使用uv管理 Python 环境与依赖。至此仪表盘呈现了四个维度的信息成本总成本、成本时间序列、速度平均响应时间、响应时间序列、自动质量判官相关性分布与人工质量用户赞踩计数。从第 07 课开始我们一直刻意把仪表盘保持得足够简单——st.subheaderst.bar_chartst.metric就完成了全部工作没有任何多余装饰这是为了让你能自上而下读懂每一行代码。第三步面对空图表的现实——为什么需要合成数据把面板加上之后立刻会撞上一个实际问题如果只有三五条真实对话这些图表几乎是空的。用户点赞可能只有 12 次相关性分布也撑不起有意义的柱状图。原因很直接真实流量需要真实用户而课程演示环境下不会有人持续提问。解决思路不是等用户而是主动造数据。第 11 课11-synthetic-data.md提供了一个 generate_data.py 脚本每秒钟向 PostgreSQL 插入一条带反馈的模拟对话循环不停直到 CtrlC 终止。uv run python generate_data.py该脚本的generate_one()揭示了反馈如何被填充的完整逻辑可与本课的查询逻辑对照理解从 5 个预置问题与 5 个预置回答中随机组合用fake_record()生成一条带随机 token 数、响应时间0.55.0 秒与成本0.00010.01 美元的LLMCallRecord经save_conversation()入库以 70% 概率写入一条source judge的反馈relevance从RELEVANT/PARTLY_RELEVANT/NON_RELEVANT三档随机取以 50% 概率写入一条source user的反馈分数从[1, 1, 1, 1, -1]中随机取——刻意让赞远多于踩模拟多数用户对回答满意的真实分布。这个闭环设计正好呼应本课的主题先把反馈写进feedback表第 08、09 课再把它查出来画成图本课最后用合成数据把图填满第 11 课为下一课迁移到 Grafana 提供有实际体积的数据基础。小结与源码路径本课完成了一次完整的反馈可视化闭环写入侧用户赞踩与判官相关性共用feedback表db_init.py由 db_feedback.py 的save_feedback()统一写入查询侧在 db_query.py 新增get_relevance_stats()与get_user_feedback_stats()两个聚合查询展示侧在 dashboard.py 增加Judge relevance柱状图与User feedback双指标与既有的成本、延迟面板并列数据供给用 generate_data.py 持续注入合成数据让仪表盘具备可观察的体量。至此成本 速度 质量三位一体的在线监控视图就齐了。下一步第 12 课起将把同样的数据接到 Grafana用 SQL 查询构建更强大的实时面板与告警能力。如果你想深入阅读每一环的完整实现本模块的课程笔记顺序为 07-streamlit-dashboard.md基础面板→ 08-user-feedback.md用户反馈采集→ 09-built-in-judge.md判官实现→ 10-feedback-dashboard.md本课→ 11-synthetic-data.md合成数据。【免费下载链接】llm-zoomcampLLM Zoomcamp - a free online course about real-life applications of LLMs. In 10 weeks you will learn how to build an AI system that answers questions about your knowledge base. Register here 项目地址: https://gitcode.com/GitHub_Trending/ll/llm-zoomcamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表