Release v1.0.0 candidate
This commit is contained in:
@@ -19,15 +19,34 @@ struct EmbedResponse {
|
||||
embedding: Vec<f32>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct OpenAIEmbedResponse {
|
||||
data: Vec<OpenAIEmbedData>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct OpenAIEmbedData {
|
||||
embedding: Vec<f32>,
|
||||
}
|
||||
|
||||
impl Embedder {
|
||||
pub fn new(model: String) -> Self {
|
||||
Self::with_url(model, Self::default_url())
|
||||
}
|
||||
|
||||
pub fn with_url(model: String, base_url: String) -> Self {
|
||||
Self {
|
||||
model,
|
||||
client: Client::new(),
|
||||
base_url: "http://localhost:11434".to_string(),
|
||||
base_url,
|
||||
}
|
||||
}
|
||||
|
||||
fn default_url() -> String {
|
||||
std::env::var("MOMENTRY_EMBED_URL")
|
||||
.unwrap_or_else(|_| "http://localhost:11434".to_string())
|
||||
}
|
||||
|
||||
pub async fn embed_text(&self, text: &str) -> Result<Vec<f32>> {
|
||||
self.embed_with_prefix(text, "").await
|
||||
}
|
||||
@@ -41,32 +60,64 @@ impl Embedder {
|
||||
}
|
||||
|
||||
async fn embed_with_prefix(&self, text: &str, prefix: &str) -> Result<Vec<f32>> {
|
||||
let url = format!("{}/api/embeddings", self.base_url);
|
||||
let prompt = format!("{}{}", prefix, text);
|
||||
|
||||
let response = self
|
||||
.client
|
||||
.post(&url)
|
||||
.json(&EmbedRequest {
|
||||
model: self.model.clone(),
|
||||
prompt,
|
||||
})
|
||||
.send()
|
||||
.await
|
||||
.context("Failed to send embedding request to Ollama")?;
|
||||
// Ollama API: POST {base_url}/api/embeddings with {model, prompt}
|
||||
// OpenAI-compatible: POST {base_url}/v1/embeddings with {input, model}
|
||||
let is_openai = self.base_url.contains(":1143"); // llama.cpp ports: 11436, 11437
|
||||
|
||||
if !response.status().is_success() {
|
||||
let status = response.status();
|
||||
let body = response.text().await.unwrap_or_default();
|
||||
anyhow::bail!("Ollama API error ({}): {}", status, body);
|
||||
if is_openai {
|
||||
let url = format!("{}/v1/embeddings", self.base_url);
|
||||
let body = serde_json::json!({
|
||||
"input": prompt,
|
||||
"model": self.model,
|
||||
});
|
||||
let response = self
|
||||
.client
|
||||
.post(&url)
|
||||
.json(&body)
|
||||
.send()
|
||||
.await
|
||||
.context("Failed to send embedding request")?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
let status = response.status();
|
||||
let body_text = response.text().await.unwrap_or_default();
|
||||
anyhow::bail!("Embedding API error ({}): {}", status, body_text);
|
||||
}
|
||||
|
||||
let result: OpenAIEmbedResponse = response
|
||||
.json()
|
||||
.await
|
||||
.context("Failed to parse embedding response")?;
|
||||
|
||||
Ok(result.data.into_iter().next().map(|d| d.embedding).unwrap_or_default())
|
||||
} else {
|
||||
let url = format!("{}/api/embeddings", self.base_url);
|
||||
let response = self
|
||||
.client
|
||||
.post(&url)
|
||||
.json(&EmbedRequest {
|
||||
model: self.model.clone(),
|
||||
prompt,
|
||||
})
|
||||
.send()
|
||||
.await
|
||||
.context("Failed to send embedding request to Ollama")?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
let status = response.status();
|
||||
let body_text = response.text().await.unwrap_or_default();
|
||||
anyhow::bail!("Ollama API error ({}): {}", status, body_text);
|
||||
}
|
||||
|
||||
let result: EmbedResponse = response
|
||||
.json()
|
||||
.await
|
||||
.context("Failed to parse Ollama response")?;
|
||||
|
||||
Ok(result.embedding)
|
||||
}
|
||||
|
||||
let result: EmbedResponse = response
|
||||
.json()
|
||||
.await
|
||||
.context("Failed to parse Ollama response")?;
|
||||
|
||||
Ok(result.embedding)
|
||||
}
|
||||
|
||||
pub async fn embed_chunk_content(&self, chunk: &crate::core::chunk::Chunk) -> Result<Vec<f32>> {
|
||||
|
||||
Reference in New Issue
Block a user