ai-cut/app/composables/useAIStoryboardAnalysis.ts

75 lines
2.3 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.

/**
* AI 故事分析 Composable
* 用於分析故事並提取資產
*/
import { useAIProvider } from './useAIProvider'
import { buildStoryAnalysisPrompt, type StoryAnalysisInput } from '~/utils/ai/prompts'
import { getTextModel } from '~/utils/storage'
import { DEFAULT_TEXT_MODEL } from '~/utils/clients/gemini-models'
import { getVisionModel } from '~/utils/storage'
import { DEFAULT_VISION_MODEL } from '~/utils/clients/gemini-models'
import type { StoryAnalysis } from '~/types/storyboard'
export function useAIStoryboardAnalysis() {
const isLoading = ref(false)
const error = ref<string | null>(null)
async function analyze(input: StoryAnalysisInput): Promise<StoryAnalysis> {
isLoading.value = true
error.value = null
try {
// 如果有圖片,使用視覺模型;否則使用文字模型
const modelName = input.styleImage
? (getVisionModel() || DEFAULT_VISION_MODEL)
: (getTextModel() || DEFAULT_TEXT_MODEL)
const provider = useAIProvider(modelName)
let prompt = buildStoryAnalysisPrompt(input)
// 如果有風格圖片,需要傳遞圖片給 API
if (input.styleImage) {
// 這裡需要根據 provider 類型處理圖片
// 暫時先傳遞文字 prompt實際實作時需要處理圖片
const result = await provider.analyzeCamera({
prompt,
image: {
mimeType: 'image/jpeg',
data: input.styleImage.replace(/^data:image\/\w+;base64,/, '')
}
})
// 解析 JSON 結果
const jsonMatch = result.match(/\{[\s\S]*\}/)
if (jsonMatch) {
return JSON.parse(jsonMatch[0]) as StoryAnalysis
}
throw new Error('無法解析分析結果')
} else {
const result = await provider.generateStoryboard(prompt)
// 解析 JSON 結果
const jsonMatch = result.match(/\{[\s\S]*\}/)
if (jsonMatch) {
return JSON.parse(jsonMatch[0]) as StoryAnalysis
}
throw new Error('無法解析分析結果')
}
} catch (err) {
const errorMessage = err instanceof Error ? err.message : '未知錯誤'
error.value = errorMessage
throw err
} finally {
isLoading.value = false
}
}
return {
analyze,
isLoading: readonly(isLoading),
error: readonly(error)
}
}