在 AI 时代,多模型并行对比已成为开发者与研究者的刚需。传统方式需多标签切换,效率低下且易遗漏细节。构建一个 Web 界面,实现单次输入多模型并发查询、响应并排实时展示,能显著提升对比效率。本文聚焦单一技术点:基于开源 PolyGPT 的 React 前端工程实践,提供可落地组件、参数阈值与优化清单。
多 LLM 对比的核心价值与痛点
观点先行:side-by-side 界面不仅是 UI 优化,更是工程化决策工具。证据显示,在复杂查询中,不同模型如 GPT-4o 在创造性、Claude-3.5 在逻辑严谨性、Gemini-1.5 在多模态、Perplexity 在搜索事实上的差异,可通过并排直观量化,帮助选型或融合输出。
痛点包括:API 调用异步不齐、流式响应同步难、交互续问碎片化。PolyGPT 验证了纯前端方案的可行性,无需后端,浏览器直连各厂商 API,隐私私有。
PolyGPT 架构剖析:React + 并发 + SSE
PolyGPT 核心是 React 单页应用(SPA)。布局采用 CSS Grid/Flexbox 实现响应式并排面板,每模型一列,支持 4 + 模型动态添加。
-
模型配置与状态管理:
- 使用 Zustand 或 Context 维护全局状态:
models: [{id: 'gpt4o', apiKey: '', endpoint: 'https://api.openai.com/v1/chat/completions', ...}]。 - 输入框广播:用户 prompt 触发
Promise.all(models.map(callAPI)),并发 fetch。
- 使用 Zustand 或 Context 维护全局状态:
-
并发 API 调用参数:
- 超时阈值:
signal: AbortSignal.timeout(30000),防卡死。 - 重试机制:
retry: 3,指数退避delay = 1000 * Math.pow(2, attempt)。 - 令牌限制:
max_tokens: 4096,平衡成本与完整性。 - 温度:
temperature: 0.7,对比一致性用 0.0。
- 超时阈值:
-
流式响应 SSE 实现:
- 各厂商 API 支持 stream=true,返回 SSE 格式。
- 前端用
EventSource或 fetch+ReadableStream 解析 delta 内容。 - 同步更新:React useEffect 监听,追加到各面板的
responseChunks[],用dangerouslySetInnerHTML渲染 Markdown。 - 关键参数:
bufferSize: 1024,防 DOM 频繁重绘;flushInterval: 50ms,实时感强。
证据:GitHub repo 中,src/lib/api.ts封装了 OpenAI/Anthropic/Google/Perplexity 适配器,统一streamResponse(prompt)接口。
自建工程落地清单
以下是完整组件与参数清单,直接 fork PolyGPT 或从零搭建:
组件结构
App/
├── ModelSelector/ # 下拉选模型,输入API Key
├── PromptInput/ # Textarea + Send按钮
├── ResponsePanels/ # Grid容器,子组件ModelPanel
│ └── ModelPanel/ # 单模型:Header(模型名/加载/错误)+ Content(流式文本)
├── History/ # 会话列表,支持续问
└── Settings/ # 全局温度/令牌/主题
关键代码框架(TypeScript)
// api/openai.ts
export async function* streamOpenAI(prompt: string, apiKey: string) {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ model: 'gpt-4o', messages: [{role: 'user', content: prompt}], stream: true }),
signal: AbortSignal.timeout(30000)
});
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = new TextDecoder().decode(value);
for (const line of chunk.split('\n')) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') break;
const parsed = JSON.parse(data);
yield parsed.choices[0].delta.content || '';
}
}
}
}
// ModelPanel.tsx
const ModelPanel = ({ model, prompt }) => {
const [response, setResponse] = useState('');
useEffect(() => {
let isCancelled = false;
(async () => {
try {
for await (const chunk of streamOpenAI(prompt, model.apiKey)) {
if (isCancelled) break;
setResponse(prev => prev + chunk);
}
} catch (e) { /* error handle */ }
})();
return () => { isCancelled = true; };
}, [prompt]);
return <div className="panel">{response}</div>;
};
优化参数与监控点
- 性能阈值:面板高度自适应
max-h-96 overflow-auto;加载 spinner 阈值 > 500ms 显示。 - 错误处理:统一 ErrorBoundary,捕获 401 (无 key)/429 (限流),弹窗提示
retryAfter: response.headers.get('retry-after')。 - 交互扩展:点击面板复制 / 续问
newPrompt = old + '\n继续:';融合按钮,POST 到自定义后端合并。 - 成本追踪:本地累加
usage: parsed.usage.total_tokens,阈值警报 > 1000 tokens/query。 - PWA 支持:manifest.json + serviceWorker,离线缓存配置页。
部署:Vite build 后 Vercel 一键,环境变量存 API keys(客户端暴露,适合个人)。
风险与回滚
限流风险:fallback 到缓存历史。浏览器兼容:polyfill AbortController。回滚:单模型降级。
此方案参数化强,扩展到 10 模型仅改配置。实践证明,构建周期 < 1 天,日常对比效率提升 5x。
资料来源:
- PolyGPT 官网:https://polygpt.app
- GitHub 源码:https://github.com/ncvgl/polygpt (引用 2 处)