You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
2.2 KiB
74 lines
2.2 KiB
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<void> {
|
|
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));
|
|
}
|
|
}
|
|
|