
Qwen3-0.6B-FP8实战教程Chainlit中添加vLLM生成结果的评分与反馈收集1. 引言为什么我们需要给AI的回答打分想象一下你部署了一个AI助手用户每天会问它成百上千个问题。有些回答很精彩用户很满意有些回答可能不太准确甚至完全跑偏了。作为开发者你怎么知道哪些回答好哪些需要改进这就是我们今天要解决的问题。你已经用vLLM部署了Qwen3-0.6B-FP8模型也用Chainlit搭建了漂亮的前端界面用户可以直接对话。但对话结束后呢用户对回答满不满意模型在哪些问题上表现好哪些问题上容易出错如果只是让用户和AI聊天你很难收集到这些宝贵的反馈。今天我就带你给这个AI对话系统加上一个“评分和反馈”功能。用户可以对AI的回答打分也可以留言提建议。这些数据会自动保存下来帮你了解模型的表现找到需要优化的地方。简单来说我们要做三件事在Chainlit界面上添加一个评分按钮比如1-5颗星让用户可以提交文字反馈把这些评分和反馈保存到文件里方便你后续分析整个过程不需要复杂的数据库用Python自带的文件操作就能搞定。跟着我做30分钟就能让你的AI助手变得更“聪明”。2. 环境准备与项目结构在开始之前我们先确认一下你的环境已经准备好了。如果你已经按照之前的教程部署好了Qwen3-0.6B-FP8和Chainlit可以直接跳到下一步。2.1 确认环境状态打开终端检查你的模型服务是否正常运行# 查看vLLM服务日志 cat /root/workspace/llm.log如果看到类似下面的输出说明模型已经加载成功可以正常使用了INFO 07-10 14:30:22 llm_engine.py:73] Initializing an LLM engine... INFO 07-10 14:30:25 llm_engine.py:176] # GPU blocks: 500, # CPU blocks: 256 INFO 07-10 14:30:25 llm_engine.py:177] Available memory: 14.00 GB INFO 07-10 14:30:25 llm_engine.py:178] Model: Qwen3-0.6B-FP8 INFO 07-10 14:30:25 llm_engine.py:179] Serving on http://0.0.0.0:80002.2 项目文件结构我们先来看看整个项目的文件结构。为了添加评分功能我们需要修改两个主要文件your_project/ ├── app.py # Chainlit主程序文件需要修改 ├── requirements.txt # Python依赖包列表 ├── feedback/ # 新建的文件夹存放反馈数据 │ └── feedback_data.json # 反馈数据文件自动生成 └── chainlit.md # Chainlit配置文件可选如果你还没有app.py文件别担心我会给你完整的代码。如果你已经有了我们只需要在现有代码基础上添加一些功能。3. 基础代码让Chainlit调用vLLM在添加评分功能之前我们先确保基础的对话功能是正常的。这里我给你一个完整的app.py代码它包含了Chainlit调用vLLM的基本功能。# app.py - 基础版本 import chainlit as cl import requests import json from datetime import datetime # vLLM服务的地址根据你的实际情况修改 VLLM_API_URL http://localhost:8000/v1/completions cl.on_chat_start async def start_chat(): 聊天开始时执行 await cl.Message( content你好我是基于Qwen3-0.6B-FP8的AI助手。有什么可以帮你的吗 ).send() cl.on_message async def main(message: cl.Message): 处理用户消息 user_input message.content # 准备请求数据 payload { model: Qwen3-0.6B-FP8, prompt: user_input, max_tokens: 512, temperature: 0.7, top_p: 0.9 } # 发送请求到vLLM try: response requests.post(VLLM_API_URL, jsonpayload) response.raise_for_status() # 解析响应 result response.json() ai_response result[choices][0][text] # 发送AI回复 await cl.Message( contentai_response ).send() except Exception as e: error_msg f请求失败: {str(e)} await cl.Message(contenterror_msg).send()保存这个文件然后在终端运行chainlit run app.py打开浏览器访问http://localhost:8000你应该能看到Chainlit的聊天界面可以和AI正常对话了。4. 核心功能添加评分与反馈收集现在进入正题我们要给AI的回答加上评分功能。我会分步骤讲解你可以跟着一步步实现。4.1 第一步修改消息处理函数我们需要修改main函数让它在发送AI回复后显示一个评分按钮。Chainlit提供了Action功能可以很方便地添加交互按钮。# 在文件开头添加导入 import os import json from datetime import datetime # 在文件开头定义反馈文件路径 FEEDBACK_DIR feedback FEEDBACK_FILE os.path.join(FEEDBACK_DIR, feedback_data.json) # 确保反馈目录存在 os.makedirs(FEEDBACK_DIR, exist_okTrue) cl.on_message async def main(message: cl.Message): 处理用户消息 - 增强版包含评分功能 user_input message.content # 准备请求数据 payload { model: Qwen3-0.6B-FP8, prompt: user_input, max_tokens: 512, temperature: 0.7, top_p: 0.9 } # 发送请求到vLLM try: response requests.post(VLLM_API_URL, jsonpayload) response.raise_for_status() # 解析响应 result response.json() ai_response result[choices][0][text] # 保存对话上下文用于后续评分 context { user_input: user_input, ai_response: ai_response, timestamp: datetime.now().isoformat() } # 发送AI回复 msg await cl.Message( contentai_response ).send() # 在消息后添加评分按钮 actions [ cl.Action(namerating_1, value1, label⭐, description不满意), cl.Action(namerating_2, value2, label⭐⭐, description一般), cl.Action(namerating_3, value3, label⭐⭐⭐, description还行), cl.Action(namerating_4, value4, label⭐⭐⭐⭐, description满意), cl.Action(namerating_5, value5, label⭐⭐⭐⭐⭐, description非常满意), cl.Action(nameopen_feedback, valueopen, label 详细反馈) ] await msg.send_actions(actions) # 保存上下文到用户会话中 cl.user_session.set(last_context, context) except Exception as e: error_msg f请求失败: {str(e)} await cl.Message(contenterror_msg).send()4.2 第二步处理评分按钮点击当用户点击评分按钮时我们需要捕获这个事件并保存评分。Chainlit使用cl.action_callback装饰器来处理按钮点击。cl.action_callback(rating_1) cl.action_callback(rating_2) cl.action_callback(rating_3) cl.action_callback(rating_4) cl.action_callback(rating_5) async def handle_rating(action: cl.Action): 处理评分按钮点击 rating int(action.value) # 获取评分值1-5 # 从用户会话中获取对话上下文 context cl.user_session.get(last_context) if context: # 添加评分信息 feedback_data { **context, rating: rating, feedback_type: rating_only, feedback_text: , feedback_timestamp: datetime.now().isoformat() } # 保存到文件 save_feedback(feedback_data) # 给用户反馈 rating_text [不满意, 一般, 还行, 满意, 非常满意][rating-1] await cl.Message( contentf感谢你的评分你给了{rating}颗星{rating_text}。 ).send() else: await cl.Message( content抱歉无法找到对应的对话记录。 ).send() # 移除评分按钮 await action.remove()4.3 第三步处理详细反馈有些用户可能想提供更详细的反馈我们提供一个“详细反馈”按钮点击后可以输入文字。cl.action_callback(open_feedback) async def open_feedback(action: cl.Action): 打开详细反馈输入 # 发送一个消息提示用户输入反馈 await cl.Message( content请告诉我你对这个回答有什么建议或意见 ).send() # 设置一个标志表示正在等待反馈 cl.user_session.set(waiting_for_feedback, True) # 移除按钮 await action.remove() cl.on_message async def handle_feedback_message(message: cl.Message): 处理用户输入的反馈 # 检查是否在等待反馈 if cl.user_session.get(waiting_for_feedback): feedback_text message.content # 从用户会话中获取对话上下文 context cl.user_session.get(last_context) if context: # 创建反馈数据 feedback_data { **context, rating: 0, # 详细反馈可能没有评分 feedback_type: text_feedback, feedback_text: feedback_text, feedback_timestamp: datetime.now().isoformat() } # 保存到文件 save_feedback(feedback_data) # 给用户反馈 await cl.Message( content感谢你的详细反馈这对我们改进AI助手很有帮助。 ).send() # 清除等待标志 cl.user_session.set(waiting_for_feedback, False) return # 如果不是反馈消息交给原来的main函数处理 # 注意这里需要修改原来的main函数避免重复处理 # 我们会在完整代码中解决这个问题4.4 第四步保存反馈数据我们需要一个函数来把反馈数据保存到JSON文件中。这样数据可以持久化保存方便后续分析。def save_feedback(feedback_data): 保存反馈数据到JSON文件 try: # 检查文件是否存在 if os.path.exists(FEEDBACK_FILE): with open(FEEDBACK_FILE, r, encodingutf-8) as f: try: all_feedback json.load(f) except json.JSONDecodeError: all_feedback [] else: all_feedback [] # 添加新反馈 all_feedback.append(feedback_data) # 保存回文件 with open(FEEDBACK_FILE, w, encodingutf-8) as f: json.dump(all_feedback, f, ensure_asciiFalse, indent2) print(f反馈已保存: {feedback_data.get(user_input, )[:50]}...) except Exception as e: print(f保存反馈失败: {str(e)})5. 完整代码一键部署的解决方案为了让你更方便地使用我把所有代码整合在一起。你可以直接复制下面的完整代码到app.py文件中。# app.py - 完整版本包含评分和反馈功能 import chainlit as cl import requests import json import os from datetime import datetime # 配置信息 VLLM_API_URL http://localhost:8000/v1/completions FEEDBACK_DIR feedback FEEDBACK_FILE os.path.join(FEEDBACK_DIR, feedback_data.json) # 确保反馈目录存在 os.makedirs(FEEDBACK_DIR, exist_okTrue) def save_feedback(feedback_data): 保存反馈数据到JSON文件 try: # 检查文件是否存在 if os.path.exists(FEEDBACK_FILE): with open(FEEDBACK_FILE, r, encodingutf-8) as f: try: all_feedback json.load(f) except json.JSONDecodeError: all_feedback [] else: all_feedback [] # 添加新反馈 all_feedback.append(feedback_data) # 保存回文件 with open(FEEDBACK_FILE, w, encodingutf-8) as f: json.dump(all_feedback, f, ensure_asciiFalse, indent2) print(f反馈已保存: {feedback_data.get(user_input, )[:50]}...) except Exception as e: print(f保存反馈失败: {str(e)}) cl.on_chat_start async def start_chat(): 聊天开始时执行 # 初始化用户会话 cl.user_session.set(waiting_for_feedback, False) await cl.Message( content你好我是基于Qwen3-0.6B-FP8的AI助手。有什么可以帮你的吗\n\n 小提示在每个回答后你可以点击星星评分或者点击按钮提供详细反馈。 ).send() cl.on_message async def handle_message(message: cl.Message): 统一处理所有消息 # 检查是否在等待反馈 if cl.user_session.get(waiting_for_feedback): await handle_feedback_input(message) return # 否则处理普通聊天消息 await handle_chat_message(message) async def handle_chat_message(message: cl.Message): 处理普通聊天消息 user_input message.content # 准备请求数据 payload { model: Qwen3-0.6B-FP8, prompt: user_input, max_tokens: 512, temperature: 0.7, top_p: 0.9 } # 发送请求到vLLM try: response requests.post(VLLM_API_URL, jsonpayload) response.raise_for_status() # 解析响应 result response.json() ai_response result[choices][0][text] # 保存对话上下文 context { user_input: user_input, ai_response: ai_response, timestamp: datetime.now().isoformat() } # 发送AI回复 msg await cl.Message( contentai_response ).send() # 添加评分按钮 actions [ cl.Action(namerating_1, value1, label⭐, description不满意), cl.Action(namerating_2, value2, label⭐⭐, description一般), cl.Action(namerating_3, value3, label⭐⭐⭐, description还行), cl.Action(namerating_4, value4, label⭐⭐⭐⭐, description满意), cl.Action(namerating_5, value5, label⭐⭐⭐⭐⭐, description非常满意), cl.Action(nameopen_feedback, valueopen, label 详细反馈) ] await msg.send_actions(actions) # 保存上下文 cl.user_session.set(last_context, context) except Exception as e: error_msg f请求失败: {str(e)} await cl.Message(contenterror_msg).send() async def handle_feedback_input(message: cl.Message): 处理用户输入的反馈 feedback_text message.content # 从用户会话中获取对话上下文 context cl.user_session.get(last_context) if context: # 创建反馈数据 feedback_data { **context, rating: 0, # 详细反馈可能没有评分 feedback_type: text_feedback, feedback_text: feedback_text, feedback_timestamp: datetime.now().isoformat() } # 保存到文件 save_feedback(feedback_data) # 给用户反馈 await cl.Message( content感谢你的详细反馈这对我们改进AI助手很有帮助。 ).send() # 清除等待标志 cl.user_session.set(waiting_for_feedback, False) # 评分按钮处理函数 cl.action_callback(rating_1) cl.action_callback(rating_2) cl.action_callback(rating_3) cl.action_callback(rating_4) cl.action_callback(rating_5) async def handle_rating(action: cl.Action): 处理评分按钮点击 rating int(action.value) # 从用户会话中获取对话上下文 context cl.user_session.get(last_context) if context: # 创建反馈数据 feedback_data { **context, rating: rating, feedback_type: rating_only, feedback_text: , feedback_timestamp: datetime.now().isoformat() } # 保存到文件 save_feedback(feedback_data) # 给用户反馈 rating_text [不满意, 一般, 还行, 满意, 非常满意][rating-1] await cl.Message( contentf感谢你的评分你给了{rating}颗星{rating_text}。 ).send() else: await cl.Message( content抱歉无法找到对应的对话记录。 ).send() # 移除按钮 await action.remove() cl.action_callback(open_feedback) async def open_feedback(action: cl.Action): 打开详细反馈输入 # 发送提示消息 await cl.Message( content请告诉我你对这个回答有什么建议或意见 ).send() # 设置等待标志 cl.user_session.set(waiting_for_feedback, True) # 移除按钮 await action.remove()6. 运行与测试代码准备好了现在我们来测试一下。6.1 启动应用在终端运行以下命令# 确保在项目目录下 chainlit run app.py如果一切正常你会看到类似下面的输出Your app is available at http://localhost:80006.2 测试评分功能打开浏览器访问http://localhost:8000然后问一个问题比如介绍一下Python的特点等待AI回答你会看到AI的回复点击评分按钮在AI回答下面有5个星星按钮和一个详细反馈按钮测试不同评分点击不同的星星看看有什么反应测试详细反馈点击 详细反馈按钮然后输入你的建议6.3 查看反馈数据所有的评分和反馈都会自动保存到feedback/feedback_data.json文件中。你可以随时查看这个文件了解用户对AI回答的评价。打开终端查看反馈数据# 查看反馈文件内容 cat feedback/feedback_data.json你会看到类似这样的数据[ { user_input: 介绍一下Python的特点, ai_response: Python是一种高级编程语言具有简洁易读的语法..., timestamp: 2024-07-10T14:30:22.123456, rating: 4, feedback_type: rating_only, feedback_text: , feedback_timestamp: 2024-07-10T14:30:25.789012 }, { user_input: 如何学习机器学习, ai_response: 学习机器学习需要掌握数学基础、编程技能..., timestamp: 2024-07-10T14:35:10.123456, rating: 0, feedback_type: text_feedback, feedback_text: 回答比较全面但可以更具体一些, feedback_timestamp: 2024-07-10T14:35:15.789012 } ]7. 进阶功能数据分析与可视化收集到反馈数据后我们可以进一步分析这些数据了解模型的表现。这里我给你几个简单的分析脚本。7.1 基础数据分析脚本创建一个analyze_feedback.py文件# analyze_feedback.py - 分析反馈数据 import json import os from datetime import datetime from collections import Counter FEEDBACK_FILE feedback/feedback_data.json def analyze_feedback(): 分析反馈数据 if not os.path.exists(FEEDBACK_FILE): print(还没有反馈数据) return with open(FEEDBACK_FILE, r, encodingutf-8) as f: try: feedback_list json.load(f) except json.JSONDecodeError: print(反馈文件格式错误) return if not feedback_list: print(反馈列表为空) return print(f总反馈数量: {len(feedback_list)}) print( * 50) # 分析评分分布 ratings [f.get(rating, 0) for f in feedback_list] rating_counter Counter(ratings) print(评分分布:) for rating in sorted(rating_counter.keys()): count rating_counter[rating] percentage count / len(feedback_list) * 100 if rating 0: print(f 无评分仅文字反馈: {count}条 ({percentage:.1f}%)) else: stars ⭐ * rating print(f {stars} ({rating}星): {count}条 ({percentage:.1f}%)) print( * 50) # 分析反馈类型 feedback_types [f.get(feedback_type, unknown) for f in feedback_list] type_counter Counter(feedback_types) print(反馈类型分布:) for ftype, count in type_counter.items(): percentage count / len(feedback_list) * 100 print(f {ftype}: {count}条 ({percentage:.1f}%)) print( * 50) # 显示最近的几条文字反馈 text_feedbacks [ f for f in feedback_list if f.get(feedback_type) text_feedback and f.get(feedback_text, ).strip() ] if text_feedbacks: print(f文字反馈数量: {len(text_feedbacks)}) print(最近5条文字反馈:) print(- * 30) for i, feedback in enumerate(text_feedbacks[-5:], 1): user_input feedback.get(user_input, )[:50] feedback_text feedback.get(feedback_text, )[:100] timestamp feedback.get(feedback_timestamp, ) print(f{i}. 用户问题: {user_input}...) print(f 反馈内容: {feedback_text}...) print(f 时间: {timestamp}) print() if __name__ __main__: analyze_feedback()运行这个脚本python analyze_feedback.py你会看到类似这样的输出总反馈数量: 23 评分分布: ⭐ (1星): 2条 (8.7%) ⭐⭐ (2星): 3条 (13.0%) ⭐⭐⭐ (3星): 5条 (21.7%) ⭐⭐⭐⭐ (4星): 8条 (34.8%) ⭐⭐⭐⭐⭐ (5星): 3条 (13.0%) 无评分仅文字反馈: 2条 (8.7%) 反馈类型分布: rating_only: 21条 (91.3%) text_feedback: 2条 (8.7%) 文字反馈数量: 2 最近5条文字反馈: ------------------------------ 1. 用户问题: 如何学习机器学习... 反馈内容: 回答比较全面但可以更具体一些... 时间: 2024-07-10T14:35:15.7890127.2 可视化评分分布如果你想更直观地看到评分分布可以安装matplotlib来画图pip install matplotlib然后创建一个visualize_ratings.py文件# visualize_ratings.py - 可视化评分分布 import json import matplotlib.pyplot as plt from collections import Counter FEEDBACK_FILE feedback/feedback_data.json def visualize_ratings(): 可视化评分分布 with open(FEEDBACK_FILE, r, encodingutf-8) as f: feedback_list json.load(f) # 提取评分排除0分即文字反馈 ratings [f.get(rating, 0) for f in feedback_list if f.get(rating, 0) 0] if not ratings: print(没有评分数据) return # 统计评分分布 rating_counter Counter(ratings) # 准备数据 stars [⭐, ⭐⭐, ⭐⭐⭐, ⭐⭐⭐⭐, ⭐⭐⭐⭐⭐] labels [f{i}星\n{stars[i-1]} for i in range(1, 6)] values [rating_counter.get(i, 0) for i in range(1, 6)] # 创建图表 plt.figure(figsize(10, 6)) # 柱状图 bars plt.bar(labels, values, color[#ff6b6b, #ffa726, #ffee58, #9ccc65, #26a69a]) # 添加数值标签 for bar, value in zip(bars, values): height bar.get_height() plt.text(bar.get_x() bar.get_width()/2., height 0.1, f{value}, hacenter, vabottom) # 设置标题和标签 plt.title(AI回答评分分布, fontsize16, fontweightbold) plt.xlabel(评分等级, fontsize12) plt.ylabel(数量, fontsize12) plt.grid(axisy, alpha0.3) # 调整布局 plt.tight_layout() # 保存图片 plt.savefig(feedback/rating_distribution.png, dpi300, bbox_inchestight) print(图表已保存到 feedback/rating_distribution.png) # 显示图表 plt.show() if __name__ __main__: visualize_ratings()运行这个脚本它会生成一个评分分布的柱状图保存为PNG文件。8. 实用技巧与常见问题8.1 如何自定义评分按钮如果你觉得5星评分太复杂可以改成简单的好/中/差三个选项# 修改actions部分 actions [ cl.Action(namerating_good, valuegood, label 好, description回答很好), cl.Action(namerating_medium, valuemedium, label 中, description回答一般), cl.Action(namerating_bad, valuebad, label 差, description回答不好), cl.Action(nameopen_feedback, valueopen, label 详细反馈) ]然后在处理函数中根据value值来保存不同的评分。8.2 如何保存更多信息你可以在反馈数据中添加更多字段比如feedback_data { **context, rating: rating, feedback_type: rating_only, feedback_text: , feedback_timestamp: datetime.now().isoformat(), # 添加更多字段 model_name: Qwen3-0.6B-FP8, model_version: 1.0, user_id: anonymous, # 如果有用户系统可以改成实际ID session_id: cl.user_session.get(id, unknown) }8.3 常见问题解决问题1点击评分按钮没反应检查浏览器控制台是否有错误确认Chainlit版本是否支持Action功能需要0.7.0以上检查网络连接是否正常问题2反馈数据没有保存检查feedback目录是否有写入权限查看终端是否有错误信息确认JSON文件格式是否正确问题3同时有多个用户时数据混乱目前的实现是所有人共享一个文件如果需要区分用户可以添加用户ID字段或者为每个用户创建单独的文件问题4数据量大了怎么办当前使用JSON文件适合小规模数据如果数据量很大比如每天几千条建议改用数据库可以考虑使用SQLite轻量级或MySQL等9. 总结从对话到改进的完整闭环通过今天的学习你已经成功为Qwen3-0.6B-FP8模型添加了评分和反馈收集功能。让我们回顾一下实现了什么9.1 核心功能实现评分系统用户可以对AI回答进行1-5星评分文字反馈用户可以提交详细的改进建议数据保存所有反馈自动保存到JSON文件数据分析提供了分析脚本可以查看评分分布和反馈内容9.2 这个功能的价值有了这个系统你现在可以了解用户满意度通过评分分布知道用户对AI回答的整体满意度发现模型弱点通过低分反馈找到模型表现不好的问题类型收集改进建议通过文字反馈获得具体的改进方向持续优化模型基于反馈数据调整提示词或考虑模型微调9.3 下一步可以做什么如果你想让这个系统更强大可以考虑添加数据库支持用SQLite或MySQL替代JSON文件支持更大数据量实现实时监控创建一个仪表盘实时显示评分趋势自动分析反馈用AI分析文字反馈自动分类和总结集成到训练流程把反馈数据用于模型微调形成闭环9.4 最后的建议评分和反馈收集只是第一步更重要的是如何利用这些数据。建议你定期查看反馈每周花10分钟看看用户的反馈关注低分回答特别关注1-2星的回答分析问题在哪里回应用户反馈如果用户提供了有价值的建议可以考虑在后续版本中改进记住一个好的AI系统不是一蹴而就的而是通过不断收集反馈、持续改进而逐渐完善的。你现在有了收集反馈的工具就迈出了改进的第一步。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。