import { generateText } from "ai"; import { createOpenAICompatible } from "@ai-sdk/openai-compatible"; import { type LanguageModel } from "ai"; import { getSystemModelWithProviderById, getModelWithProviderById } from "#server/service/llm"; import { updateSession } from "./session"; import log4js from "logger"; const logger = log4js.getLogger("APP"); function resolveModel( provider: { name: string; apiKey: string | null; baseUrl: string | null; parseMode: string; }, modelId: string, ): LanguageModel { const baseUrl = provider.baseUrl?.replace(/\/+$/, "") || undefined; const openaiCompatible = createOpenAICompatible({ name: provider.name, apiKey: provider.apiKey || undefined, baseURL: baseUrl || "https://api.openai.com/v1", }); return openaiCompatible(modelId) as LanguageModel; } export async function generateSessionTitle( sessionId: string, firstUserMessage: string, firstAssistantMessage: string, titleModelId: number, userId: number | null, ): Promise { try { const modelRow = userId ? await getModelWithProviderById(titleModelId, userId) : await getSystemModelWithProviderById(titleModelId); if (!modelRow) { logger.warn("[AGENT-TITLE] titleModelId=%d not found, skip", titleModelId); return; } const { model, provider } = modelRow; if (!provider.apiKey) { logger.warn("[AGENT-TITLE] provider has no apiKey, skip"); return; } const languageModel = resolveModel(provider, model.modelId); const prompt = `请根据以下对话生成一个简短的标题(不超过20个字,不要加引号、不要加书名号): 用户: ${firstUserMessage.slice(0, 500)} 助手: ${firstAssistantMessage.slice(0, 500)} 标题:`; const result = await generateText({ model: languageModel, prompt, maxOutputTokens: 200, }); const title = result.text.trim().slice(0, 100); if (title) { await updateSession(sessionId, { title }); logger.info("[AGENT-TITLE] sessionId=%s title=%s", sessionId, title); } } catch (err) { logger.error("[AGENT-TITLE] sessionId=%s error: %s", sessionId, err instanceof Error ? err.message : String(err)); } }