From a7b746df5f7b6a455e980569f3a4e41573dad3e2 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 23 Feb 2026 10:35:08 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20v0.1=E5=B0=81=E7=89=88=E2=80=94?= =?UTF-8?q?=E2=80=94=E6=B2=89=E6=B5=B8=E5=BC=8F=E5=AF=B9=E8=AF=9DMVP?= =?UTF-8?q?=EF=BC=8CAI=E5=8A=A8=E6=80=81=E6=8F=90=E9=97=AE=EF=BC=8C?= =?UTF-8?q?=E6=8E=A2=E7=B4=A2=E4=B8=ADloading=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/chat/page.jsx | 21 ++++++++++++++++- server.js | 59 ++++++++++++++++++++++++++--------------------- 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/app/chat/page.jsx b/app/chat/page.jsx index 5a2e4bc..75f2590 100644 --- a/app/chat/page.jsx +++ b/app/chat/page.jsx @@ -210,7 +210,7 @@ function QuestionView({ question, onAnswer, questionIndex, total }) { // ── 主页面 ──────────────────────────────────────────────── export default function ChatPage() { - const [stage, setStage] = useState('intro'); // intro | chat | loading | done + const [stage, setStage] = useState('intro'); // intro | chat | waiting | loading | done const [question, setQuestion] = useState(''); const [qIndex, setQIndex] = useState(0); const [total, setTotal] = useState(30); @@ -236,6 +236,7 @@ export default function ChatPage() { }; const handleAnswer = async (answer) => { + setStage('waiting'); // 显示探索中 try { const r = await fetch('/api/chat', { method: 'POST', @@ -250,9 +251,11 @@ export default function ChatPage() { } setQuestion(d.reply); setQIndex((i) => i + 1); + setStage('chat'); } catch { setQuestion('网络有点问题,我们继续。你刚才的回答我已经记住了。'); setQIndex((i) => i + 1); + setStage('chat'); } }; @@ -260,6 +263,22 @@ export default function ChatPage() { <> {stage === 'intro' && } + {stage === 'waiting' && ( +
+
+ 探索中…… +
+ +
+ )} {stage === 'loading' && (
正在连接...
diff --git a/server.js b/server.js index 0c56563..439f617 100644 --- a/server.js +++ b/server.js @@ -17,7 +17,7 @@ const opening = '开始前,我想先简单认识你一下。就像朋友聊天 const questionBank = [ '你今年大概在哪个年龄段?比如20岁以下、20-29、30-39这样。', - '你平时怎么称呼自己更舒服?', + '你是男生还是女生呀?', '你现在主要在做什么?上学、上班、自己做事,还是在休息调整?', '最近这几天,有没有一件小事让你心情变好?', '如果只说一件事,你现在最发愁的是什么?', @@ -60,21 +60,25 @@ function loadSystemPrompt() { async function callAI(messages) { const key = process.env.YCAPIS_API_KEY; if (!key) return null; - const res = await fetch('https://ycapis.com/v1/chat/completions', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${key}`, - }, - body: JSON.stringify({ - model: 'gpt-5.3-codex', - temperature: 0.7, - messages, - }), - }); - if (!res.ok) return null; - const data = await res.json(); - return data?.choices?.[0]?.message?.content || null; + try { + const res = await fetch('https://ycapis.com/v1/responses', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${key}`, + }, + body: JSON.stringify({ + model: 'gpt-5.3-codex', + input: messages.map(m => ({ role: m.role, content: m.content })), + max_output_tokens: 300, + }), + }); + if (!res.ok) return null; + const data = await res.json(); + return data?.output?.[0]?.content?.[0]?.text || null; + } catch { + return null; + } } function previewReport(session) { @@ -118,7 +122,7 @@ app.prepare().then(() => { server.post('/api/session/new', (req, res) => { const sessionId = `lgj_${Date.now().toString(36)}`; - sessions.set(sessionId, { index: 0, answers: [], skips: 0, prompt: loadSystemPrompt() }); + sessions.set(sessionId, { index: 0, answers: [], questions: [], skips: 0, prompt: loadSystemPrompt() }); res.json({ sessionId, opening, total: 30 }); }); @@ -134,25 +138,28 @@ app.prepare().then(() => { s.index += 1; } - const done = s.index >= questionBank.length; + const done = s.index >= 30; if (done) { return res.json({ done: true, reply: '你已经完成全部对话。接下来我会为你生成专属灵镜报告。' }); } - const progress = s.index > 0 && s.index % 5 === 0 ? `你已经完成第${Math.ceil(s.index / 6)}/5阶段了。` : ''; - const bridge = userAnswer ? '我听懂了。' : '我们继续。'; - const nextQ = questionBank[s.index]; - - let aiReply = `${bridge}${progress ? ` ${progress}` : ''} ${nextQ}`.trim(); + const progress = s.index > 0 && s.index % 6 === 0 ? `(你已经完成第${Math.ceil(s.index / 6)}/5阶段了。)` : ''; + // 全部交给AI动态生成,不用硬编码题库 const ds = await callAI([ { role: 'system', content: s.prompt }, { role: 'assistant', content: opening }, - ...s.answers.slice(-8).map((a) => ({ role: 'user', content: a })), - { role: 'user', content: `请按规则继续下一问。当前问题建议:${nextQ}` }, + ...s.answers.flatMap((a, i) => [ + { role: 'assistant', content: s.questions[i] || '' }, + { role: 'user', content: a } + ]).filter(m => m.content), + { role: 'user', content: `[系统提示] 用户刚才回答了:"${userAnswer}"。${progress}请用温暖口语接住他的回答,然后继续问下一个问题。注意:只问一个问题,用大白话,不用专业术语。当前已问第${s.index}题,共30题。` } ]); - if (ds) aiReply = ds; + const aiReply = ds || '嗯,我听到了。我们继续,你现在主要在做什么?上学、上班、还是在休整?'; + + // 记录AI问的问题 + s.questions.push(aiReply); return res.json({ done: false, reply: aiReply, index: s.index + 1, total: 30 }); });