Skip to main content

lc_schema/messages/
image.rs

1//! 图片内容类型(多模态 vision 支持)
2
3use serde::{Deserialize, Serialize};
4
5/// 图片内容(URL 或 base64 data URI)
6///
7/// OpenAI Vision 使用 `image_url.url`(可为 https URL 或 `data:image/...;base64,...`),
8/// Ollama 使用 base64 原始数据。本类型统一存储为 `url` 字段,
9/// 由各 provider 在序列化时转换。
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
11pub struct ImageContent {
12    pub url: String,
13}
14
15impl ImageContent {
16    /// 从 URL 创建
17    pub fn from_url(url: impl Into<String>) -> Self {
18        Self { url: url.into() }
19    }
20
21    /// 从 base64 数据创建(自动包装为 data URI)
22    pub fn from_base64(data: impl Into<String>) -> Self {
23        Self {
24            url: format!("data:image/png;base64,{}", data.into()),
25        }
26    }
27
28    /// 从指定 MIME 类型的 base64 创建
29    pub fn from_base64_with_mime(data: impl Into<String>, mime: &str) -> Self {
30        Self {
31            url: format!("data:{};base64,{}", mime, data.into()),
32        }
33    }
34
35    /// 是否为 base64 data URI
36    pub fn is_base64(&self) -> bool {
37        self.url.starts_with("data:")
38    }
39
40    /// 提取 base64 原始数据(若是 data URI)
41    pub fn base64_data(&self) -> Option<&str> {
42        self.url
43            .split_once(',')
44            .filter(|(prefix, _)| prefix.contains("base64"))
45            .map(|(_, data)| data)
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn test_from_url() {
55        let img = ImageContent::from_url("https://example.com/image.jpg");
56        assert_eq!(img.url, "https://example.com/image.jpg");
57        assert!(!img.is_base64());
58    }
59
60    #[test]
61    fn test_from_base64() {
62        let img = ImageContent::from_base64("abc123");
63        assert!(img.is_base64());
64        assert_eq!(img.base64_data(), Some("abc123"));
65    }
66
67    #[test]
68    fn test_from_base64_with_mime() {
69        let img = ImageContent::from_base64_with_mime("xyz", "image/jpeg");
70        assert!(img.url.starts_with("data:image/jpeg;base64,"));
71        assert_eq!(img.base64_data(), Some("xyz"));
72    }
73
74    #[test]
75    fn test_url_not_base64() {
76        let img = ImageContent::from_url("https://example.com/img.png");
77        assert_eq!(img.base64_data(), None);
78    }
79}