Unified · Split
| @@ -5,6 +5,8 @@ use rusqlite::types::{FromSql, FromSqlResult, ToSqlOutput, ValueRef}; · 4 unmodified lines | |||
| 5 | use rusqlite::ToSql; | 5 | use rusqlite::ToSql; |
| 6 | use std::time::Instant; | 6 | use std::time::Instant; |
| 7 | 7 | ||
| 8 | use crate::models::LanguageModel; | ||
| 9 | |||
| 8 | #[derive(Debug, PartialEq, Clone)] | 10 | #[derive(Debug, PartialEq, Clone)] |
| 9 | pub struct Embedding(pub Vec<f32>); | 11 | pub struct Embedding(pub Vec<f32>); |
| 10 | 12 | ||
| @@ -66,6 +68,7 @@ impl Embedding { · 55 unmodified lines | |||
| 66 | 68 | ||
| 67 | #[async_trait] | 69 | #[async_trait] |
| 68 | pub trait EmbeddingProvider: Sync + Send { | 70 | pub trait EmbeddingProvider: Sync + Send { |
| 71 | fn base_model(&self) -> Box<dyn LanguageModel>; | ||
| 69 | fn is_authenticated(&self) -> bool; | 72 | fn is_authenticated(&self) -> bool; |
| 70 | async fn embed_batch(&self, spans: Vec<String>) -> Result<Vec<Embedding>>; | 73 | async fn embed_batch(&self, spans: Vec<String>) -> Result<Vec<Embedding>>; |
| 71 | fn max_tokens_per_batch(&self) -> usize; | 74 | fn max_tokens_per_batch(&self) -> usize; |
| @@ -3,10 +3,42 @@ use std::time::Instant; · 2 unmodified lines | |||
| 3 | use crate::{ | 3 | use crate::{ |
| 4 | completion::CompletionRequest, | 4 | completion::CompletionRequest, |
| 5 | embedding::{Embedding, EmbeddingProvider}, | 5 | embedding::{Embedding, EmbeddingProvider}, |
| 6 | models::{LanguageModel, TruncationDirection}, | ||
| 6 | }; | 7 | }; |
| 7 | use async_trait::async_trait; | 8 | use async_trait::async_trait; |
| 8 | use serde::Serialize; | 9 | use serde::Serialize; |
| 9 | 10 | ||
| 11 | pub struct DummyLanguageModel {} | ||
| 12 | |||
| 13 | impl LanguageModel for DummyLanguageModel { | ||
| 14 | fn name(&self) -> String { | ||
| 15 | "dummy".to_string() | ||
| 16 | } | ||
| 17 | fn capacity(&self) -> anyhow::Result<usize> { | ||
| 18 | anyhow::Ok(1000) | ||
| 19 | } | ||
| 20 | fn truncate( | ||
| 21 | &self, | ||
| 22 | content: &str, | ||
| 23 | length: usize, | ||
| 24 | direction: crate::models::TruncationDirection, | ||
| 25 | ) -> anyhow::Result<String> { | ||
| 26 | let truncated = match direction { | ||
| 27 | TruncationDirection::End => content.chars().collect::<Vec<char>>()[..length] | ||
| 28 | .iter() | ||
| 29 | .collect::<String>(), | ||
| 30 | TruncationDirection::Start => content.chars().collect::<Vec<char>>()[..length] | ||
| 31 | .iter() | ||
| 32 | .collect::<String>(), | ||
| 33 | }; | ||
| 34 | |||
| 35 | anyhow::Ok(truncated) | ||
| 36 | } | ||
| 37 | fn count_tokens(&self, content: &str) -> anyhow::Result<usize> { | ||
| 38 | anyhow::Ok(content.chars().collect::<Vec<char>>().len()) | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 10 | #[derive(Serialize)] | 42 | #[derive(Serialize)] |
| 11 | pub struct DummyCompletionRequest { | 43 | pub struct DummyCompletionRequest { |
| 12 | pub name: String, | 44 | pub name: String, |
| @@ -22,6 +54,9 @@ pub struct DummyEmbeddingProvider {} · 9 unmodified lines | |||
| 22 | 54 | ||
| 23 | #[async_trait] | 55 | #[async_trait] |
| 24 | impl EmbeddingProvider for DummyEmbeddingProvider { | 56 | impl EmbeddingProvider for DummyEmbeddingProvider { |
| 57 | fn base_model(&self) -> Box<dyn LanguageModel> { | ||
| 58 | Box::new(DummyLanguageModel {}) | ||
| 59 | } | ||
| 25 | fn is_authenticated(&self) -> bool { | 60 | fn is_authenticated(&self) -> bool { |
| 26 | true | 61 | true |
| 27 | } | 62 | } |
| @@ -19,6 +19,8 @@ use tiktoken_rs::{cl100k_base, CoreBPE}; · 18 unmodified lines | |||
| 19 | use util::http::{HttpClient, Request}; | 19 | use util::http::{HttpClient, Request}; |
| 20 | 20 | ||
| 21 | use crate::embedding::{Embedding, EmbeddingProvider}; | 21 | use crate::embedding::{Embedding, EmbeddingProvider}; |
| 22 | use crate::models::LanguageModel; | ||
| 23 | use crate::providers::open_ai::OpenAILanguageModel; | ||
| 22 | 24 | ||
| 23 | lazy_static! { | 25 | lazy_static! { |
| 24 | static ref OPENAI_API_KEY: Option<String> = env::var("OPENAI_API_KEY").ok(); | 26 | static ref OPENAI_API_KEY: Option<String> = env::var("OPENAI_API_KEY").ok(); |
| @@ -27,6 +29,7 @@ lazy_static! { · 2 unmodified lines | |||
| 27 | 29 | ||
| 28 | #[derive(Clone)] | 30 | #[derive(Clone)] |
| 29 | pub struct OpenAIEmbeddingProvider { | 31 | pub struct OpenAIEmbeddingProvider { |
| 32 | model: OpenAILanguageModel, | ||
| 30 | pub client: Arc<dyn HttpClient>, | 33 | pub client: Arc<dyn HttpClient>, |
| 31 | pub executor: Arc<Background>, | 34 | pub executor: Arc<Background>, |
| 32 | rate_limit_count_rx: watch::Receiver<Option<Instant>>, | 35 | rate_limit_count_rx: watch::Receiver<Option<Instant>>, |
| @@ -65,7 +68,10 @@ impl OpenAIEmbeddingProvider { · 32 unmodified lines | |||
| 65 | let (rate_limit_count_tx, rate_limit_count_rx) = watch::channel_with(None); | 68 | let (rate_limit_count_tx, rate_limit_count_rx) = watch::channel_with(None); |
| 66 | let rate_limit_count_tx = Arc::new(Mutex::new(rate_limit_count_tx)); | 69 | let rate_limit_count_tx = Arc::new(Mutex::new(rate_limit_count_tx)); |
| 67 | 70 | ||
| 71 | let model = OpenAILanguageModel::load("text-embedding-ada-002"); | ||
| 72 | |||
| 68 | OpenAIEmbeddingProvider { | 73 | OpenAIEmbeddingProvider { |
| 74 | model, | ||
| 69 | client, | 75 | client, |
| 70 | executor, | 76 | executor, |
| 71 | rate_limit_count_rx, | 77 | rate_limit_count_rx, |
| @@ -131,6 +137,10 @@ impl OpenAIEmbeddingProvider { · 59 unmodified lines | |||
| 131 | 137 | ||
| 132 | #[async_trait] | 138 | #[async_trait] |
| 133 | impl EmbeddingProvider for OpenAIEmbeddingProvider { | 139 | impl EmbeddingProvider for OpenAIEmbeddingProvider { |
| 140 | fn base_model(&self) -> Box<dyn LanguageModel> { | ||
| 141 | let model: Box<dyn LanguageModel> = Box::new(self.model.clone()); | ||
| 142 | model | ||
| 143 | } | ||
| 134 | fn is_authenticated(&self) -> bool { | 144 | fn is_authenticated(&self) -> bool { |
| 135 | OPENAI_API_KEY.as_ref().is_some() | 145 | OPENAI_API_KEY.as_ref().is_some() |
| 136 | } | 146 | } |
| @@ -4,6 +4,7 @@ use util::ResultExt; · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | use crate::models::{LanguageModel, TruncationDirection}; | 5 | use crate::models::{LanguageModel, TruncationDirection}; |
| 6 | 6 | ||
| 7 | #[derive(Clone)] | ||
| 7 | pub struct OpenAILanguageModel { | 8 | pub struct OpenAILanguageModel { |
| 8 | name: String, | 9 | name: String, |
| 9 | bpe: Option<CoreBPE>, | 10 | bpe: Option<CoreBPE>, |
| @@ -4,8 +4,11 @@ use crate::{ · 3 unmodified lines | |||
| 4 | semantic_index_settings::SemanticIndexSettings, | 4 | semantic_index_settings::SemanticIndexSettings, |
| 5 | FileToEmbed, JobHandle, SearchResult, SemanticIndex, EMBEDDING_QUEUE_FLUSH_TIMEOUT, | 5 | FileToEmbed, JobHandle, SearchResult, SemanticIndex, EMBEDDING_QUEUE_FLUSH_TIMEOUT, |
| 6 | }; | 6 | }; |
| 7 | use ai::embedding::{Embedding, EmbeddingProvider}; | 7 | use ai::providers::dummy::{DummyEmbeddingProvider, DummyLanguageModel}; |
| 8 | use ai::providers::dummy::DummyEmbeddingProvider; | 8 | use ai::{ |
| 9 | embedding::{Embedding, EmbeddingProvider}, | ||
| 10 | models::LanguageModel, | ||
| 11 | }; | ||
| 9 | use anyhow::Result; | 12 | use anyhow::Result; |
| 10 | use async_trait::async_trait; | 13 | use async_trait::async_trait; |
| 11 | use gpui::{executor::Deterministic, Task, TestAppContext}; | 14 | use gpui::{executor::Deterministic, Task, TestAppContext}; |
| @@ -1282,6 +1285,9 @@ impl FakeEmbeddingProvider { · 1270 unmodified lines | |||
| 1282 | 1285 | ||
| 1283 | #[async_trait] | 1286 | #[async_trait] |
| 1284 | impl EmbeddingProvider for FakeEmbeddingProvider { | 1287 | impl EmbeddingProvider for FakeEmbeddingProvider { |
| 1288 | fn base_model(&self) -> Box<dyn LanguageModel> { | ||
| 1289 | Box::new(DummyLanguageModel {}) | ||
| 1290 | } | ||
| 1285 | fn is_authenticated(&self) -> bool { | 1291 | fn is_authenticated(&self) -> bool { |
| 1286 | true | 1292 | true |
| 1287 | } | 1293 | } |