"use server"; import { streamText } from "ai"; import { createOpenAI } from "@ai-sdk/openai"; import { createStreamableValue } from "ai/rsc"; import { ERROR_PREFIX } from "@/lib/constant"; import { extractChangeDetails, extractZhangMingRen, readGuaMarkdown, } from "@/lib/content/zhouyi"; const model = process.env.OPENAI_MODEL ?? "huihui_ai/gemma-4-abliterated:e4b"; const openai = createOpenAI({ baseURL: process.env.OPENAI_BASE_URL ?? "https://op.bz121.com/v1", }); const STREAM_INTERVAL = 60; const MAX_SIZE = 6; export async function getAnswer( prompt: string, guaMark: string, guaTitle: string, guaResult: string, guaChange: string, ) { console.log(prompt, guaTitle, guaResult, guaChange); const stream = createStreamableValue(); try { const guaDetail = await readGuaMarkdown(guaMark); const explain = extractZhangMingRen(guaDetail) ?? ""; const changeList = extractChangeDetails(guaDetail, guaChange, guaTitle); const { fullStream } = streamText({ temperature: 0.5, model: openai(model), messages: [ { role: "system", content: `你是一位精通《周易》的AI助手,根据用户提供的卦象和问题,提供准确的卦象解读和实用建议 任务要求:逻辑清晰,语气得当 1. 解读卦象:分析主卦、变爻及变卦,解读整体趋势和吉凶 2. 关联问题:针对用户问题,结合卦象信息,提供具体分析 3. 提供建议:根据卦象启示,给出切实可行的建议,帮助用户解决实际问题`, }, { role: "user", content: `我摇到的卦象:${guaTitle} ${guaResult} ${guaChange} 我的问题:${prompt} ${explain} ${changeList.join("\n")}`, }, ], maxRetries: 0, }); let buffer = ""; let done = false; const intervalId = setInterval(() => { if (done && buffer.length === 0) { clearInterval(intervalId); stream.done(); return; } if (buffer.length <= MAX_SIZE) { stream.update(buffer); buffer = ""; } else { const chunk = buffer.slice(0, MAX_SIZE); buffer = buffer.slice(MAX_SIZE); stream.update(chunk); } }, STREAM_INTERVAL); (async () => { for await (const part of fullStream) { switch (part.type) { case "text-delta": buffer += part.textDelta; break; case "error": const err = part.error as any; stream.update(ERROR_PREFIX + (err.message ?? err.toString())); break; } } })() .catch(console.error) .finally(() => { done = true; }); return { data: stream.value }; } catch (err: any) { stream.done(); return { error: err.message ?? err }; } }