redis_vl/vectorizers/
anthropic.rs1use async_trait::async_trait;
12
13use super::voyageai::{VoyageAIConfig, VoyageAITextVectorizer};
14use super::{AsyncVectorizer, Vectorizer};
15use crate::error::Result;
16
17const DEFAULT_MODEL: &str = "voyage-3-large";
19
20#[derive(Debug, Clone)]
26pub struct AnthropicConfig {
27 pub(crate) inner: VoyageAIConfig,
29}
30
31impl AnthropicConfig {
32 pub fn new(
37 api_key: impl Into<String>,
38 model: impl Into<String>,
39 input_type: Option<String>,
40 ) -> Self {
41 Self {
42 inner: VoyageAIConfig::new(api_key, model, input_type),
43 }
44 }
45
46 pub fn with_defaults(api_key: impl Into<String>, input_type: Option<String>) -> Self {
49 Self::new(api_key, DEFAULT_MODEL, input_type)
50 }
51
52 pub fn from_env(input_type: Option<String>) -> Result<Self> {
55 let inner = VoyageAIConfig::from_env(DEFAULT_MODEL, input_type)?;
56 Ok(Self { inner })
57 }
58
59 pub fn from_env_with_model(
62 model: impl Into<String>,
63 input_type: Option<String>,
64 ) -> Result<Self> {
65 let inner = VoyageAIConfig::from_env(model, input_type)?;
66 Ok(Self { inner })
67 }
68}
69
70#[derive(Debug, Clone)]
86pub struct AnthropicTextVectorizer {
87 inner: VoyageAITextVectorizer,
88}
89
90impl AnthropicTextVectorizer {
91 pub fn new(config: AnthropicConfig) -> Self {
93 Self {
94 inner: VoyageAITextVectorizer::new(config.inner),
95 }
96 }
97}
98
99impl Vectorizer for AnthropicTextVectorizer {
100 fn embed(&self, text: &str) -> Result<Vec<f32>> {
101 Vectorizer::embed(&self.inner, text)
102 }
103
104 fn embed_many(&self, texts: &[&str]) -> Result<Vec<Vec<f32>>> {
105 Vectorizer::embed_many(&self.inner, texts)
106 }
107}
108
109#[async_trait]
110impl AsyncVectorizer for AnthropicTextVectorizer {
111 async fn embed(&self, text: &str) -> Result<Vec<f32>> {
112 AsyncVectorizer::embed(&self.inner, text).await
113 }
114
115 async fn embed_many(&self, texts: &[&str]) -> Result<Vec<Vec<f32>>> {
116 AsyncVectorizer::embed_many(&self.inner, texts).await
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 #[test]
125 fn anthropic_config_stores_fields() {
126 let cfg = AnthropicConfig::new("key", "voyage-3-large", Some("document".into()));
127 assert_eq!(cfg.inner.api_key, "key");
128 assert_eq!(cfg.inner.model, "voyage-3-large");
129 assert_eq!(cfg.inner.input_type.as_deref(), Some("document"));
130 }
131
132 #[test]
133 fn anthropic_config_with_defaults_uses_default_model() {
134 let cfg = AnthropicConfig::with_defaults("key", None);
135 assert_eq!(cfg.inner.model, DEFAULT_MODEL);
136 assert!(cfg.inner.input_type.is_none());
137 }
138
139 #[test]
140 fn anthropic_vectorizer_is_send_sync() {
141 fn assert_send_sync<T: Send + Sync>() {}
142 assert_send_sync::<AnthropicTextVectorizer>();
143 }
144}