| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- function registerLlmRoutes(app, options) {
- const llmBaseUrl = options.llmBaseUrl;
- const llmApiKey = options.llmApiKey;
- // 非流式调用已迁移至云函数 proxyHub(cloud-functions/08-proxyHub.js)。
- // 但流式 SSE 调用必须走本地 Express(云函数不支持流式输出),由前端 fetch 直连。
- app.post('/api/llm/chat/stream', async (req, res) => {
- try {
- const { model, messages, temperature, max_tokens, ...rest } = req.body || {};
- if (!Array.isArray(messages) || messages.length === 0) {
- return res.status(400).json({ error: '缺少 messages 参数' });
- }
- const payload = {
- model: model || 'gpt-4o',
- messages,
- temperature: temperature ?? 0.7,
- max_tokens: max_tokens || 4096,
- ...rest,
- stream: true,
- };
- const url = `${llmBaseUrl}/v1/chat/completions`;
- console.log(`🤖 [Stream] LLM Chat 请求: model=${payload.model}, messages=${messages.length}条`);
- const upstream = await fetch(url, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': `Bearer ${llmApiKey}`,
- },
- body: JSON.stringify(payload),
- });
- if (!upstream.ok) {
- const errText = await upstream.text();
- console.error('🤖 [Stream] 上游错误:', upstream.status, errText);
- return res.status(upstream.status).json({ error: errText || `upstream ${upstream.status}` });
- }
- res.setHeader('Content-Type', 'text/event-stream; charset=utf-8');
- res.setHeader('Cache-Control', 'no-cache, no-transform');
- res.setHeader('Connection', 'keep-alive');
- res.setHeader('X-Accel-Buffering', 'no');
- res.flushHeaders?.();
- const reader = upstream.body.getReader();
- const onAbort = () => {
- try { reader.cancel(); } catch {}
- };
- req.on('close', onAbort);
- try {
- while (true) {
- const { value, done } = await reader.read();
- if (done) break;
- if (value) res.write(Buffer.from(value));
- }
- } finally {
- req.off('close', onAbort);
- res.end();
- }
- } catch (err) {
- console.error('🤖 [Stream] 异常:', err.message);
- if (!res.headersSent) {
- res.status(500).json({ error: `LLM 流式请求失败: ${err.message}` });
- } else {
- try { res.end(); } catch {}
- }
- }
- });
- }
- module.exports = { registerLlmRoutes };
|