mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
add search indexing to api routes
This commit is contained in:
@@ -2,9 +2,9 @@
|
||||
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from fastapi import APIRouter, HTTPException, BackgroundTasks, Depends
|
||||
|
||||
from basic_memory.deps import DocumentServiceDep
|
||||
from basic_memory.deps import DocumentServiceDep, get_search_service
|
||||
from basic_memory.schemas.request import DocumentRequest, DocumentPathId
|
||||
from basic_memory.schemas.response import DocumentResponse, DocumentCreateResponse
|
||||
from basic_memory.services.document_service import (
|
||||
@@ -20,22 +20,23 @@ router = APIRouter(prefix="/documents", tags=["documents"])
|
||||
@router.post("/create", response_model=DocumentCreateResponse, status_code=201)
|
||||
async def create_document(
|
||||
doc: DocumentRequest,
|
||||
background_tasks: BackgroundTasks,
|
||||
service: DocumentServiceDep,
|
||||
search_service = Depends(get_search_service)
|
||||
) -> DocumentCreateResponse:
|
||||
"""Create a new document.
|
||||
|
||||
The document will be created with appropriate frontmatter including:
|
||||
- Generated ID
|
||||
- Creation timestamp
|
||||
- Last modified timestamp
|
||||
- Any provided doc_metadata
|
||||
"""
|
||||
"""Create a new document with search indexing."""
|
||||
try:
|
||||
document = await service.create_document(
|
||||
path_id=doc.path_id,
|
||||
content=doc.content,
|
||||
metadata=doc.doc_metadata,
|
||||
)
|
||||
# Index the new document
|
||||
await search_service.index_document(
|
||||
document,
|
||||
doc.content,
|
||||
background_tasks=background_tasks
|
||||
)
|
||||
return DocumentCreateResponse.model_validate(document.__dict__)
|
||||
except DocumentError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
@@ -71,9 +72,11 @@ async def get_document(
|
||||
async def update_document(
|
||||
path_id: DocumentPathId,
|
||||
doc: DocumentRequest,
|
||||
background_tasks: BackgroundTasks,
|
||||
service: DocumentServiceDep,
|
||||
search_service = Depends(get_search_service)
|
||||
) -> DocumentResponse:
|
||||
"""Update a document by ID."""
|
||||
"""Update a document by ID with search indexing."""
|
||||
# Verify FilePaths match
|
||||
if doc.path_id != path_id:
|
||||
raise HTTPException(
|
||||
@@ -86,10 +89,16 @@ async def update_document(
|
||||
content=doc.content,
|
||||
metadata=doc.doc_metadata,
|
||||
)
|
||||
# Update search index
|
||||
await search_service.index_document(
|
||||
document,
|
||||
doc.content,
|
||||
background_tasks=background_tasks
|
||||
)
|
||||
doc_dict = document.__dict__ | {"content": doc.content}
|
||||
return DocumentResponse.model_validate(doc_dict)
|
||||
except DocumentNotFoundError:
|
||||
raise HTTPException(status_code=404, detail=f"Document not found: {id}")
|
||||
raise HTTPException(status_code=404, detail=f"Document not found: {path_id}")
|
||||
except DocumentWriteError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
|
||||
@@ -97,12 +106,17 @@ async def update_document(
|
||||
@router.delete("/{path_id:path}", status_code=204)
|
||||
async def delete_document(
|
||||
path_id: DocumentPathId,
|
||||
background_tasks: BackgroundTasks,
|
||||
service: DocumentServiceDep,
|
||||
search_service = Depends(get_search_service)
|
||||
) -> None:
|
||||
"""Delete a document by ID."""
|
||||
"""Delete a document by ID and remove from search index."""
|
||||
try:
|
||||
# Delete from storage
|
||||
await service.delete_document_by_path_id(path_id)
|
||||
# Remove from search index (in background)
|
||||
background_tasks.add_task(search_service.delete_by_path_id, path_id)
|
||||
except DocumentNotFoundError:
|
||||
raise HTTPException(status_code=404, detail=f"Document not found: {id}")
|
||||
raise HTTPException(status_code=404, detail=f"Document not found: {path_id}")
|
||||
except DocumentWriteError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
@@ -1,11 +1,12 @@
|
||||
"""Router for knowledge graph operations."""
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from fastapi import APIRouter, HTTPException, BackgroundTasks, Depends
|
||||
from loguru import logger
|
||||
|
||||
from basic_memory.deps import (
|
||||
EntityServiceDep,
|
||||
KnowledgeServiceDep,
|
||||
get_search_service,
|
||||
)
|
||||
from basic_memory.schemas import (
|
||||
CreateEntityRequest,
|
||||
@@ -31,10 +32,18 @@ router = APIRouter(prefix="/knowledge", tags=["knowledge"])
|
||||
|
||||
@router.post("/entities", response_model=EntityListResponse)
|
||||
async def create_entities(
|
||||
data: CreateEntityRequest, knowledge_service: KnowledgeServiceDep
|
||||
data: CreateEntityRequest,
|
||||
background_tasks: BackgroundTasks,
|
||||
knowledge_service: KnowledgeServiceDep,
|
||||
search_service = Depends(get_search_service)
|
||||
) -> EntityListResponse:
|
||||
"""Create new entities in the knowledge graph."""
|
||||
"""Create new entities in the knowledge graph and index them."""
|
||||
entities = await knowledge_service.create_entities(data.entities)
|
||||
|
||||
# Index each entity
|
||||
for entity in entities:
|
||||
await search_service.index_entity(entity, background_tasks=background_tasks)
|
||||
|
||||
return EntityListResponse(
|
||||
entities=[EntityResponse.model_validate(entity) for entity in entities]
|
||||
)
|
||||
@@ -42,10 +51,18 @@ async def create_entities(
|
||||
|
||||
@router.post("/relations", response_model=EntityListResponse)
|
||||
async def create_relations(
|
||||
data: CreateRelationsRequest, knowledge_service: KnowledgeServiceDep
|
||||
data: CreateRelationsRequest,
|
||||
background_tasks: BackgroundTasks,
|
||||
knowledge_service: KnowledgeServiceDep,
|
||||
search_service = Depends(get_search_service),
|
||||
) -> EntityListResponse:
|
||||
"""Create relations between entities."""
|
||||
"""Create relations between entities and update search index."""
|
||||
updated_entities = await knowledge_service.create_relations(data.relations)
|
||||
|
||||
# Reindex updated entities since relations have changed
|
||||
for entity in updated_entities:
|
||||
await search_service.index_entity(entity, background_tasks=background_tasks)
|
||||
|
||||
return EntityListResponse(
|
||||
entities=[EntityResponse.model_validate(entity) for entity in updated_entities]
|
||||
)
|
||||
@@ -53,13 +70,20 @@ async def create_relations(
|
||||
|
||||
@router.post("/observations", response_model=EntityResponse)
|
||||
async def add_observations(
|
||||
data: AddObservationsRequest, knowledge_service: KnowledgeServiceDep
|
||||
data: AddObservationsRequest,
|
||||
background_tasks: BackgroundTasks,
|
||||
knowledge_service: KnowledgeServiceDep,
|
||||
search_service = Depends(get_search_service)
|
||||
) -> EntityResponse:
|
||||
"""Add observations to an entity."""
|
||||
"""Add observations to an entity and update search index."""
|
||||
logger.debug(f"Adding observations to entity: {data.path_id}")
|
||||
updated_entity = await knowledge_service.add_observations(
|
||||
data.path_id, data.observations, data.context
|
||||
)
|
||||
|
||||
# Reindex the entity with new observations
|
||||
await search_service.index_entity(updated_entity, background_tasks=background_tasks)
|
||||
|
||||
return EntityResponse.model_validate(updated_entity)
|
||||
|
||||
|
||||
@@ -104,29 +128,52 @@ async def open_nodes(data: OpenNodesRequest, entity_service: EntityServiceDep) -
|
||||
|
||||
@router.post("/entities/delete", response_model=DeleteEntitiesResponse)
|
||||
async def delete_entities(
|
||||
data: DeleteEntitiesRequest, knowledge_service: KnowledgeServiceDep
|
||||
data: DeleteEntitiesRequest,
|
||||
background_tasks: BackgroundTasks,
|
||||
knowledge_service: KnowledgeServiceDep,
|
||||
search_service = Depends(get_search_service)
|
||||
) -> DeleteEntitiesResponse:
|
||||
"""Delete a specific entity by PathId."""
|
||||
"""Delete entities and remove from search index."""
|
||||
deleted = await knowledge_service.delete_entities(data.path_ids)
|
||||
|
||||
# Remove each deleted entity from search index
|
||||
for path_id in data.path_ids:
|
||||
background_tasks.add_task(search_service.delete_by_path_id, path_id)
|
||||
|
||||
return DeleteEntitiesResponse(deleted=deleted)
|
||||
|
||||
|
||||
@router.post("/observations/delete", response_model=EntityResponse)
|
||||
async def delete_observations(
|
||||
data: DeleteObservationsRequest, knowledge_service: KnowledgeServiceDep
|
||||
data: DeleteObservationsRequest,
|
||||
background_tasks: BackgroundTasks,
|
||||
knowledge_service: KnowledgeServiceDep,
|
||||
search_service = Depends(get_search_service)
|
||||
) -> EntityResponse:
|
||||
"""Delete observations from an entity."""
|
||||
"""Delete observations and update search index."""
|
||||
path_id = data.path_id
|
||||
updated_entity = await knowledge_service.delete_observations(path_id, data.observations)
|
||||
|
||||
# Reindex the entity since observations changed
|
||||
await search_service.index_entity(updated_entity, background_tasks=background_tasks)
|
||||
|
||||
return EntityResponse.model_validate(updated_entity)
|
||||
|
||||
|
||||
@router.post("/relations/delete", response_model=EntityListResponse)
|
||||
async def delete_relations(
|
||||
data: DeleteRelationsRequest, knowledge_service: KnowledgeServiceDep
|
||||
data: DeleteRelationsRequest,
|
||||
background_tasks: BackgroundTasks,
|
||||
knowledge_service: KnowledgeServiceDep,
|
||||
search_service = Depends(get_search_service)
|
||||
) -> EntityListResponse:
|
||||
"""Delete relations between entities."""
|
||||
"""Delete relations and update search index."""
|
||||
updated_entities = await knowledge_service.delete_relations(data.relations)
|
||||
|
||||
# Reindex entities since relations changed
|
||||
for entity in updated_entities:
|
||||
await search_service.index_entity(entity, background_tasks=background_tasks)
|
||||
|
||||
return EntityListResponse(
|
||||
entities=[EntityResponse.model_validate(entity) for entity in updated_entities]
|
||||
)
|
||||
)
|
||||
Reference in New Issue
Block a user