Files
freedakgmail e44dd0bd95 0.0.8.0
2025-11-23 18:03:04 +08:00

269 lines
6.5 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { FamilyMember } from "@/types/family"
/**
* AI 辅助功能配置
*/
export interface AIConfig {
provider: "openai" | "custom" | "browser"
apiKey?: string
apiEndpoint?: string
model?: string
}
/**
* 获取 AI 配置
*/
export function getAIConfig(): AIConfig | null {
if (typeof window === "undefined") return null
const config = localStorage.getItem("ai-config")
return config ? JSON.parse(config) : null
}
/**
* 保存 AI 配置
*/
export function saveAIConfig(config: AIConfig): void {
if (typeof window === "undefined") return
localStorage.setItem("ai-config", JSON.stringify(config))
}
/**
* 生成成员简介
*/
export async function generateBio(member: Partial<FamilyMember>): Promise<string> {
const config = getAIConfig()
if (!config) {
throw new Error("请先配置 AI 服务")
}
const prompt = `请根据以下信息生成一段简洁的人物简介(100字以内):
姓名:${member.fullName || "未知"}
性别:${member.gender === "MALE" ? "男" : member.gender === "FEMALE" ? "女" : "未知"}
出生日期:${member.birthDate || "未知"}
${member.deathDate ? `逝世日期:${member.deathDate}` : ""}
籍贯:${member.ancestralHome || "未知"}
${member.courtesyName ? `字:${member.courtesyName}` : ""}
${member.artName ? `号:${member.artName}` : ""}
请用第三人称,简洁专业的语言描述。`
return await callAI(prompt, config)
}
/**
* 分析家族关系
*/
export async function analyzeRelationship(
member1: FamilyMember,
member2: FamilyMember,
allMembers: FamilyMember[]
): Promise<string> {
const config = getAIConfig()
if (!config) {
throw new Error("请先配置 AI 服务")
}
const prompt = `请分析以下两位家族成员的关系:
成员A${member1.fullName},第${member1.generation}
成员B${member2.fullName},第${member2.generation}
家族成员总数:${allMembers.length}
请分析他们可能的关系(如:兄弟、堂兄弟、叔侄等),并给出理由。`
return await callAI(prompt, config)
}
/**
* 智能推荐字辈
*/
export async function suggestGenerationName(
generation: number,
existingNames: string[]
): Promise<string[]> {
const config = getAIConfig()
if (!config) {
throw new Error("请先配置 AI 服务")
}
const prompt = `请为家族第${generation}世推荐5个合适的字辈用字。
已使用的字辈:${existingNames.join("、")}
要求:
1. 符合中国传统字辈命名习惯
2. 寓意吉祥、积极向上
3. 避免与已有字辈重复
4. 只返回5个汉字,用逗号分隔`
const response = await callAI(prompt, config)
return response.split(/[,,、]/).map(s => s.trim()).filter(Boolean).slice(0, 5)
}
/**
* 生成家族故事标题
*/
export async function generateStoryTitle(content: string): Promise<string> {
const config = getAIConfig()
if (!config) {
throw new Error("请先配置 AI 服务")
}
const prompt = `请为以下家族故事生成一个简洁有吸引力的标题(10字以内):
${content.substring(0, 200)}...
只返回标题,不要其他内容。`
return await callAI(prompt, config)
}
/**
* 智能数据校验
*/
export async function validateMemberData(member: Partial<FamilyMember>): Promise<{
valid: boolean
issues: string[]
suggestions: string[]
}> {
const config = getAIConfig()
if (!config) {
return {
valid: true,
issues: [],
suggestions: []
}
}
const prompt = `请检查以下家族成员信息是否合理:
姓名:${member.fullName || "未填写"}
性别:${member.gender || "未填写"}
出生日期:${member.birthDate || "未填写"}
逝世日期:${member.deathDate || "未填写"}
世代:${member.generation || "未填写"}
请指出可能存在的问题和改进建议。以JSON格式返回:
{
"valid": true/false,
"issues": ["问题1", "问题2"],
"suggestions": ["建议1", "建议2"]
}`
try {
const response = await callAI(prompt, config)
return JSON.parse(response)
} catch (error) {
return {
valid: true,
issues: [],
suggestions: []
}
}
}
/**
* 调用 AI API
*/
async function callAI(prompt: string, config: AIConfig): Promise<string> {
if (config.provider === "browser") {
// 使用浏览器内置 AI(如果支持)
if ("ai" in window && "languageModel" in (window as any).ai) {
try {
const session = await (window as any).ai.languageModel.create()
const result = await session.prompt(prompt)
return result
} catch (error) {
throw new Error("浏览器 AI 不可用")
}
} else {
throw new Error("浏览器不支持内置 AI")
}
}
if (config.provider === "openai") {
// 调用 OpenAI API
const response = await fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${config.apiKey}`,
},
body: JSON.stringify({
model: config.model || "gpt-3.5-turbo",
messages: [
{
role: "system",
content: "你是一个专业的家谱管理助手,帮助用户整理和分析家族信息。"
},
{
role: "user",
content: prompt
}
],
temperature: 0.7,
max_tokens: 500,
}),
})
if (!response.ok) {
throw new Error(`API 调用失败: ${response.statusText}`)
}
const data = await response.json()
return data.choices[0].message.content.trim()
}
if (config.provider === "custom") {
// 调用自定义 API
const response = await fetch(config.apiEndpoint!, {
method: "POST",
headers: {
"Content-Type": "application/json",
...(config.apiKey ? { "Authorization": `Bearer ${config.apiKey}` } : {}),
},
body: JSON.stringify({ prompt }),
})
if (!response.ok) {
throw new Error(`API 调用失败: ${response.statusText}`)
}
const data = await response.json()
return data.response || data.result || data.text || ""
}
throw new Error("不支持的 AI 提供商")
}
/**
* 检查 AI 是否可用
*/
export function isAIAvailable(): boolean {
const config = getAIConfig()
if (!config) return false
if (config.provider === "browser") {
return typeof window !== "undefined" && "ai" in window
}
if (config.provider === "openai") {
return !!config.apiKey
}
if (config.provider === "custom") {
return !!config.apiEndpoint
}
return false
}