subx_cli/services/ai/
prompts.rs

1use crate::Result;
2use crate::error::SubXError;
3use crate::services::ai::{AnalysisRequest, ConfidenceScore, MatchResult, VerificationRequest};
4use serde_json;
5
6impl super::OpenAIClient {
7    /// 建立內容分析的 Prompt
8    pub fn build_analysis_prompt(&self, request: &AnalysisRequest) -> String {
9        let mut prompt = String::new();
10        prompt.push_str("請分析以下影片和字幕檔案的匹配關係:\n\n");
11
12        prompt.push_str("影片檔案:\n");
13        for video in &request.video_files {
14            prompt.push_str(&format!("- {}\n", video));
15        }
16
17        prompt.push_str("\n字幕檔案:\n");
18        for subtitle in &request.subtitle_files {
19            prompt.push_str(&format!("- {}\n", subtitle));
20        }
21
22        if !request.content_samples.is_empty() {
23            prompt.push_str("\n字幕內容預覽:\n");
24            for sample in &request.content_samples {
25                prompt.push_str(&format!("檔案: {}\n", sample.filename));
26                prompt.push_str(&format!("內容: {}\n\n", sample.content_preview));
27            }
28        }
29
30        prompt.push_str(
31            "請根據檔名模式等因素,提供匹配建議。\n\
32            回應格式為 JSON:\n\
33            {\n\
34              \"matches\": [\n\
35                {\n\
36                  \"video_file\": \"影片檔名\",\n\
37                  \"subtitle_file\": \"字幕檔名\",\n\
38                  \"confidence\": 0.95,\n\
39                  \"match_factors\": [\"檔名相似\"]\n\
40                }\n\
41              ],\n\
42              \"confidence\": 0.9,\n\
43              \"reasoning\": \"匹配原因說明\"\n\
44            }",
45        );
46
47        prompt
48    }
49
50    /// 從 AI 回應中解析匹配結果
51    pub fn parse_match_result(&self, response: &str) -> Result<MatchResult> {
52        let json_start = response.find('{').unwrap_or(0);
53        let json_end = response.rfind('}').map(|i| i + 1).unwrap_or(response.len());
54        let json_str = &response[json_start..json_end];
55
56        serde_json::from_str(json_str)
57            .map_err(|e| SubXError::AiService(format!("AI 回應解析失敗: {}", e)))
58    }
59
60    /// 建立匹配驗證的 Prompt
61    pub fn build_verification_prompt(&self, request: &VerificationRequest) -> String {
62        let mut prompt = String::new();
63        prompt.push_str("請根據以下匹配資訊評估信心度:\n");
64        prompt.push_str(&format!("影片檔案: {}\n", request.video_file));
65        prompt.push_str(&format!("字幕檔案: {}\n", request.subtitle_file));
66        prompt.push_str("匹配因素:\n");
67        for factor in &request.match_factors {
68            prompt.push_str(&format!("- {}\n", factor));
69        }
70        prompt.push_str(
71            "\n請以 JSON 格式回應,格式如下:\n{\n  \"score\": 0.9,\n  \"factors\": [\"...\"]\n}",
72        );
73        prompt
74    }
75
76    /// 從 AI 回應中解析信心度分數
77    pub fn parse_confidence_score(&self, response: &str) -> Result<ConfidenceScore> {
78        let json_start = response.find('{').unwrap_or(0);
79        let json_end = response.rfind('}').map(|i| i + 1).unwrap_or(response.len());
80        let json_str = &response[json_start..json_end];
81
82        serde_json::from_str(json_str)
83            .map_err(|e| SubXError::AiService(format!("AI 信心度解析失敗: {}", e)))
84    }
85}