4.5 呈现AI分析结果、报告与用户反馈接口
到目前为止,我们已经有了后端强大的 AI 分析服务(包含文本流式输出、结构化数据输出以及异步任务队列),也有了前端炫酷的 2D/3D 数据可视化仪表盘。本节是将它们缝合在一起的关键环节:打造一个直观的“AI 洞察面板 (Insight Panel)”,并引入用户反馈机制 (Feedback),为构建“数据飞轮”和强化学习 (RLHF) 奠定基础。
源码地址:https://github.com/you-want/ai-data-analyzer
欢迎 star, 支持一波。
1. 打造 AI 洞察面板 (Insight Panel)
图表展示的是“客观事实”,而 AI 洞察面板展示的是“主观见解”和“行动建议”。在实际项目中,我们的后端AnalysisController提供了一个/analysis/structured接口,它会返回一个包含summary和confidenceScore等结构化 JSON 数据的分析结果。
为了更好地展示这些数据,我们在前端的frontend/src/components/目录下创建一个专门的AIInsightPanel.tsx组件:
"use client"; import React from 'react'; import FeedbackWidget from './FeedbackWidget'; interface AIInsightPanelProps { summary: string; confidenceScore: number; insightId?: string; } export default function AIInsightPanel({ summary, confidenceScore, insightId = "demo-insight-123" }: AIInsightPanelProps) { return ( <div className="bg-gradient-to-br from-indigo-50 to-blue-50 dark:from-indigo-950/30 dark:to-blue-900/20 p-6 rounded-xl border border-indigo-100 dark:border-indigo-800/50 relative overflow-hidden"> {/* 装饰性图标 */} <div className="absolute top-4 right-4 text-indigo-200 dark:text-indigo-800/50"> <svg className="w-12 h-12" fill="currentColor" viewBox="0 0 20 20"> <path d="M11.3 1.046A1 1 0 0112 2v5h4a1 1 0 01.82 1.573l-7 10A1 1 0 018 18v-5H4a1 1 0 01-.82-1.573l7-10a1 1 0 011.12-.38z"></path> </svg> </div> <h3 className="text-lg font-bold text-indigo-900 dark:text-indigo-200 mb-4 flex items-center gap-2"> <span>✨ AI 深度洞察</span> </h3> <div className="prose prose-indigo dark:prose-invert max-w-none text-gray-700 dark:text-gray-300"> {/* 展示 AI 的结构化总结,如果有 Markdown 也可以引入 react-markdown 渲染 */} <p className="whitespace-pre-wrap leading-relaxed">{summary}</p> <div className="mt-4 flex items-center gap-2"> <span className="text-xs px-2 py-1 bg-white/50 dark:bg-black/20 rounded-md text-indigo-600 dark:text-indigo-300 font-medium border border-indigo-100 dark:border-indigo-800/30"> 信心指数: {(confidenceScore * 100).toFixed(0)}% </span> </div> </div> {/* 引入用户反馈组件 */} <FeedbackWidget insightId={insightId} /> </div> ); }通过这个组件,我们将枯燥的 JSON 数据转换成了一个具有现代感、视觉层级清晰的洞察卡片。
2. 后端新增:支持反馈的 API 接口
为了让反馈组件能够真正工作,我们需要在后端的AnalysisController中新增一个接收反馈的接口。这为未来基于人类反馈的强化学习 (RLHF) 埋下了伏笔。
打开backend/src/analysis/analysis.controller.ts,增加如下代码:
// 接收用户对 AI 分析结果的反馈 (RLHF 基础)@Post('feedback')@HttpCode(HttpStatus.OK)submitFeedback(@Body()payload:{insightId:string;type:'up'|'down';comment?:string;},){// 在实际项目中,这里会将反馈存入数据库,关联到具体的 AnalysisResultconsole.log(`[Feedback Received] InsightID:${payload.insightId}, Type:${payload.type}, Comment:${payload.comment||'N/A'}`,);return{success:true,message:'反馈已记录,感谢您的评价!',};}有了这个接口,后端就能收集到用户对每次分析质量的评价。在更复杂的系统中,我们可以利用这些标注数据对大模型进行微调 (Fine-tuning)。
3. 设计用户反馈组件 (Feedback Widget)
接下来,我们在前端实现这个发送反馈的交互组件FeedbackWidget.tsx:
"use client"; import { useState } from 'react'; interface FeedbackWidgetProps { insightId: string; } export default function FeedbackWidget({ insightId }: FeedbackWidgetProps) { const [feedback, setFeedback] = useState<'up' | 'down' | null>(null); const [submitting, setSubmitting] = useState(false); const handleFeedback = async (type: 'up' | 'down') => { if (submitting || feedback) return; // 防止重复提交 setSubmitting(true); try { const res = await fetch('http://localhost:3001/analysis/feedback', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ insightId, type }) }); if (res.ok) { setFeedback(type); // 更新状态为已反馈 } } catch (error) { console.error('提交反馈失败', error); } finally { setSubmitting(false); } }; return ( <div className="mt-4 pt-4 border-t border-indigo-100/50 dark:border-indigo-900/30 flex items-center justify-between"> <span className="text-sm text-indigo-600/80 dark:text-indigo-300/80">这个分析对您有帮助吗?</span> <div className="flex gap-2"> <button onClick={() => handleFeedback('up')} disabled={submitting || feedback !== null} className={`p-2 rounded-full transition-colors ${ feedback === 'up' ? 'bg-indigo-200 text-indigo-700 dark:bg-indigo-800 dark:text-indigo-200' : 'hover:bg-indigo-100 text-indigo-400 dark:hover:bg-indigo-900/50 dark:text-indigo-400' } ${submitting ? 'opacity-50 cursor-not-allowed' : ''}`} > 👍 </button> <button onClick={() => handleFeedback('down')} disabled={submitting || feedback !== null} className={`p-2 rounded-full transition-colors ${ feedback === 'down' ? 'bg-red-100 text-red-600 dark:bg-red-900/40 dark:text-red-300' : 'hover:bg-red-50 text-red-400 dark:hover:bg-red-900/20 dark:text-red-400' } ${submitting ? 'opacity-50 cursor-not-allowed' : ''}`} > 👎 </button> </div> </div> ); }4. 将洞察面板接入现有的 AnalysisForm
最后一步,将我们漂亮的洞察面板整合进系统已有的交互表单中。修改frontend/src/components/AnalysisForm.tsx的渲染部分:
import { useState } from 'react'; import AIInsightPanel from './AIInsightPanel'; // ...(省略前面的组件代码和 fetch 逻辑) {/* 渲染后端返回的结构化 JSON 数据,引入 AI 洞察面板与反馈 */} {result && result.success && result.data && ( <div className="mt-4"> <AIInsightPanel summary={result.data.summary} confidenceScore={result.data.confidenceScore} insightId="demo-insight-123" // 模拟 ID,实际应使用 result.data.id /> </div> )}小结
祝贺你!完成了【第 4 章】的学习后,你的系统已经不再仅仅是一个后端 API,而是一个拥有完整体验、视觉极佳、具备 AI 交互反馈能力的自动化数据分析平台原型了。
在接下来的【第 5 章】终章里,我们将探讨如何将这个玩具原型打磨成可以支撑成千上万用户的生产级企业应用!