fix: arc-share retrieved chunks, centralize entity embeddings, and trim hot-path clones.

This commit is contained in:
Per Stark
2026-06-06 23:05:53 +02:00
parent 676fdbc132
commit 4559ee0aa8
41 changed files with 368 additions and 289 deletions
@@ -6,11 +6,9 @@ use serde::{Deserialize, Serialize};
use common::{
error::AppError,
storage::{
types::{
knowledge_entity::{KnowledgeEntity, KnowledgeEntityType},
knowledge_relationship::KnowledgeRelationship,
},
storage::types::{
knowledge_entity::{KnowledgeEntity, KnowledgeEntityType},
knowledge_relationship::KnowledgeRelationship,
},
utils::embedding::EmbeddingProvider,
};
@@ -83,25 +81,32 @@ impl LLMEnrichmentResult {
entity_concurrency: usize,
embedding_provider: &EmbeddingProvider,
) -> Result<Vec<EmbeddedKnowledgeEntity>, AppError> {
stream::iter(self.knowledge_entities.clone().into_iter().map(|entity| {
let mapper = Arc::clone(&mapper);
let source_id = source_id.to_string();
let user_id = user_id.to_string();
let tasks: Vec<_> = self
.knowledge_entities
.iter()
.map(|entity| {
let llm_entity = entity.clone();
let mapper = Arc::clone(&mapper);
let source_id = source_id.to_string();
let user_id = user_id.to_string();
async move {
create_single_entity(
&entity,
&source_id,
&user_id,
mapper,
embedding_provider,
)
.await
}
}))
.buffer_unordered(entity_concurrency.max(1))
.try_collect()
.await
async move {
create_single_entity(
llm_entity,
&source_id,
&user_id,
mapper,
embedding_provider,
)
.await
}
})
.collect();
stream::iter(tasks)
.buffer_unordered(entity_concurrency.max(1))
.try_collect()
.await
}
fn process_relationships(
@@ -129,7 +134,7 @@ impl LLMEnrichmentResult {
}
async fn create_single_entity(
llm_entity: &LLMKnowledgeEntity,
llm_entity: LLMKnowledgeEntity,
source_id: &str,
user_id: &str,
mapper: Arc<GraphMapper>,
@@ -137,9 +142,11 @@ async fn create_single_entity(
) -> Result<EmbeddedKnowledgeEntity, AppError> {
let assigned_id = mapper.get_id(&llm_entity.key)?.to_string();
let embedding_input = format!(
"name: {}, description: {}, type: {}",
llm_entity.name, llm_entity.description, llm_entity.entity_type
let entity_type = KnowledgeEntityType::from(llm_entity.entity_type);
let embedding_input = KnowledgeEntity::embedding_input_text(
&llm_entity.name,
&llm_entity.description,
entity_type,
);
let embedding = embedding_provider.embed(&embedding_input).await?;
@@ -149,9 +156,9 @@ async fn create_single_entity(
id: assigned_id,
created_at: now,
updated_at: now,
name: llm_entity.name.clone(),
description: llm_entity.description.clone(),
entity_type: KnowledgeEntityType::from(llm_entity.entity_type.clone()),
name: llm_entity.name,
description: llm_entity.description,
entity_type,
source_id: source_id.to_string(),
metadata: None,
user_id: user_id.into(),
@@ -48,20 +48,20 @@ const STORE_RELATIONSHIPS: &str = r"
pub(super) async fn store_vector_chunks(
db: &SurrealDbClient,
task_id: &str,
chunks: &[EmbeddedTextChunk],
chunks: Vec<EmbeddedTextChunk>,
) -> Result<usize, AppError> {
let chunk_count = chunks.len();
for embedded in chunks {
TextChunk::store_with_embedding(embedded.chunk.clone(), embedded.embedding.clone(), db)
.await?;
debug!(
task_id = %task_id,
chunk_id = %embedded.chunk.id,
chunk_len = embedded.chunk.chunk.chars().count(),
"chunk persisted"
);
TextChunk::store_with_embedding(embedded.chunk, embedded.embedding, db).await?;
}
Ok(chunks.len())
Ok(chunk_count)
}
/// Persists knowledge entities and their relationships.
+1 -1
View File
@@ -155,7 +155,7 @@ pub async fn persist(
let entity_count = entities.len();
let relationship_count = relationships.len();
let chunk_count = store_vector_chunks(ctx.db, ctx.task_id.as_str(), &chunks).await?;
let chunk_count = store_vector_chunks(ctx.db, ctx.task_id.as_str(), chunks).await?;
store_graph_entities(ctx.db, &ctx.pipeline_config.tuning, entities, relationships).await?;
ctx.db.store_item(text_content).await?;
rebuild(ctx.db).await?;
+1 -1
View File
@@ -92,7 +92,7 @@ impl MockServices {
entity: retrieved_entity,
score: 0.8,
chunks: std::sync::Arc::new(vec![RetrievedChunk {
chunk: retrieved_chunk,
chunk: std::sync::Arc::new(retrieved_chunk),
score: 0.7,
}]),
}],
@@ -74,10 +74,7 @@ pub async fn extract_text_from_file(
config: &AppConfig,
storage: &StorageManager,
) -> Result<String, AppError> {
let file_bytes = storage
.get(&file_info.path)
.await
.map_err(AppError::from)?;
let file_bytes = storage.get(&file_info.path).await.map_err(AppError::from)?;
let local_path = resolve_existing_local_path(storage, &file_info.path).await;
match file_info.mime_type.as_str() {