Spaces:
Running
Running
Download src/services/api/routes/retrieve.py from Leon4gr45/brain: direct link, hf CLI and curl.
- Browser
- Download file 25.6 kB
-
https://huggingface.co/spaces/Leon4gr45/brain/resolve/main/src/services/api/routes/retrieve.py
- Command line
-
hf download hf://spaces/Leon4gr45/brain/src/services/api/routes/retrieve.py
-
curl -L -o retrieve.py https://huggingface.co/spaces/Leon4gr45/brain/resolve/main/src/services/api/routes/retrieve.py
25.6 kB
| """ | |
| File: /retrieve.py | |
| Created Date: Saturday October 25th 2025 | |
| Author: Christian Nonis <alch.infoemail@gmail.com> | |
| ----- | |
| Last Modified: Thursday February 19th 2026 7:45:12 pm | |
| Modified By: Christian Nonis <alch.infoemail@gmail.com> | |
| ----- | |
| """ | |
| import json | |
| from typing import List, Literal, Optional | |
| from fastapi import APIRouter, Body, Depends, HTTPException, Query | |
| from fastapi.responses import JSONResponse | |
| from src.services.api.dependencies import get_brain_id | |
| from src.services.api.constants.requests import ( | |
| GetEntityContextResponse, | |
| GetEntityInfoResponse, | |
| GetEntitySibilingsResponse, | |
| GetEntityStatusResponse, | |
| GetContextRequestBody, | |
| GetContextResponse, | |
| RecommendResponse, | |
| RecommendRequestBody, | |
| RetrieveNeighborsAiModeRequestBody, | |
| RetrieveNeighborsWithIdentificationParamsRequestBody, | |
| RetrieveRequestResponse, | |
| RetrieveNeighborsRequestResponse, | |
| SearchRequestBody, | |
| SearchResponse, | |
| ) | |
| from src.services.api.constants.responses import ( | |
| ChangelogItemResponse, | |
| ChangelogListResponse, | |
| EntityListResponse, | |
| HopListResponse, | |
| LabelListResponse, | |
| ObservationItemResponse, | |
| ObservationListResponse, | |
| RelationshipListResponse, | |
| StructuredDataItemResponse, | |
| StructuredDataListResponse, | |
| TextChunkListResponse, | |
| TypeListResponse, | |
| VectorListResponse, | |
| VectorStoreListResponse, | |
| ) | |
| from src.services.api.controllers.retrieve import ( | |
| retrieve_neighbors as retrieve_neighbors_controller, | |
| retrieve_neighbors_ai_mode as retrieve_neighbors_ai_mode_controller, | |
| get_relationships as retrieve_get_relationships_controller, | |
| get_entities as retrieve_get_entities_controller, | |
| get_context as retrieve_get_context_controller, | |
| ) | |
| from src.services.api.controllers.kg import get_hops as get_hops_controller | |
| from src.services.api.controllers.retrieve import ( | |
| retrieve_data as retrieve_data_controller, | |
| ) | |
| from src.services.api.controllers.search import search as search_controller | |
| from src.services.api.controllers.structured_data import ( | |
| get_structured_data_by_id as get_structured_data_by_id_controller, | |
| get_structured_data_list as get_structured_data_list_controller, | |
| get_structured_data_types as get_structured_data_types_controller, | |
| get_text_chunks as get_text_chunks_controller, | |
| ) | |
| from src.services.api.controllers.observations import ( | |
| get_observation_by_id as get_observation_by_id_controller, | |
| get_observations_list as get_observations_list_controller, | |
| get_observation_labels as get_observation_labels_controller, | |
| ) | |
| from src.services.api.controllers.changelogs import ( | |
| get_changelog_by_id as get_changelog_by_id_controller, | |
| get_changelogs_list as get_changelogs_list_controller, | |
| get_changelog_types as get_changelog_types_controller, | |
| ) | |
| from src.services.api.controllers.entities import ( | |
| get_entity_info as get_entity_info_controller, | |
| get_entity_context as get_entity_context_controller, | |
| get_entity_sibilings as get_entity_sibilings_controller, | |
| get_entity_status as get_entity_status_controller, | |
| get_recommendations as get_recommendations_controller, | |
| ) | |
| from src.services.api.controllers.vectors import ( | |
| get_vector_stores as get_vector_stores_controller, | |
| list_vectors as list_vectors_controller, | |
| ) | |
| retrieve_router = APIRouter(prefix="/retrieve", tags=["retrieve"]) | |
| async def retrieve( | |
| text: str = Query(..., description="The text to search for."), | |
| limit: int = Query(10, description="The number of results to return."), | |
| preferred_entities: str = Query( | |
| "", | |
| description="The entities to prioritize in the relationships, separated by commas.", | |
| ), | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Retrieve data from the knowledge graph and data store. | |
| """ | |
| return await retrieve_data_controller(text, limit, preferred_entities, brain_id) | |
| async def get_neighbors( | |
| uuid: str = Query(..., description="The UUID of the entity to get neighbors for."), | |
| limit: int = Query(10, description="The number of neighbors to return."), | |
| look_for: Optional[str] = Query( | |
| None, | |
| description="The description of what in the neighbors should share with the target.", | |
| ), | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Get the neighbors of an entity. | |
| """ | |
| return await retrieve_neighbors_controller( | |
| uuid=uuid, limit=limit, look_for=look_for, brain_id=brain_id | |
| ) | |
| async def get_neighbors_with_identification_params( | |
| request: RetrieveNeighborsWithIdentificationParamsRequestBody, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Get the neighbors of an entity. | |
| """ | |
| request.brain_id = brain_id | |
| return await retrieve_neighbors_controller( | |
| identification_params=request.identification_params, | |
| limit=request.limit, | |
| look_for=request.look_for if request.look_for else None, | |
| brain_id=request.brain_id, | |
| ) | |
| async def get_neighbors_ai_mode( | |
| request: RetrieveNeighborsAiModeRequestBody = Body( | |
| ..., | |
| description="The request body for the retrieve neighbors AI mode endpoint.", | |
| ), | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Retrieve neighboring entities using AI-mode identification parameters. | |
| Parameters: | |
| request (RetrieveNeighborsAiModeRequestBody): Request body containing: | |
| - identification_params: parameters that identify the target entity or entities. | |
| - looking_for: description of the desired neighbors or relation types. | |
| - limit: maximum number of neighbor results to return. | |
| Returns: | |
| list: Neighboring entities that match the AI-mode identification and search criteria. | |
| """ | |
| return await retrieve_neighbors_ai_mode_controller( | |
| request.identification_params, | |
| request.looking_for, | |
| request.limit, | |
| brain_id, | |
| ) | |
| async def get_context( | |
| request: GetContextRequestBody, | |
| brain_id: str = Depends(get_brain_id), | |
| ) -> GetContextResponse: | |
| """ | |
| Handle an HTTP request to retrieve an entity's contextual information. | |
| Parameters: | |
| request (GetContextRequestBody): Request body containing: | |
| - text: The text to search context for. | |
| - brain_id: The brain/workspace identifier to query. | |
| Returns: | |
| GetContextResponse: Response containing the context information. | |
| """ | |
| request.brain_id = brain_id | |
| return await retrieve_get_context_controller(request) | |
| async def get_relationships( | |
| limit: int = 10, | |
| skip: int = 0, | |
| relationship_types: Optional[str] = None, | |
| from_node_labels: Optional[str] = None, | |
| to_node_labels: Optional[str] = None, | |
| query_text: Optional[str] = None, | |
| query_search_target: Optional[str] = "all", | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Retrieve relationships filtered by types, node labels, and query criteria. | |
| Parameters: | |
| relationship_types (Optional[str]): Comma-separated relationship types to include. | |
| from_node_labels (Optional[str]): Comma-separated source node labels to filter. | |
| to_node_labels (Optional[str]): Comma-separated target node labels to filter. | |
| query_text (Optional[str]): Text to match against relationships or nodes. | |
| query_search_target (Optional[str]): Target of the text query, such as "all", "source", or "target". | |
| limit (int): Maximum number of relationships to return. | |
| skip (int): Number of relationships to skip. | |
| brain_id (str): Brain (dataset) identifier. | |
| Returns: | |
| List of relationship records matching the filters. | |
| """ | |
| if relationship_types: | |
| relationship_types = relationship_types.split(",") | |
| if from_node_labels: | |
| from_node_labels = from_node_labels.split(",") | |
| if to_node_labels: | |
| to_node_labels = to_node_labels.split(",") | |
| return await retrieve_get_relationships_controller( | |
| limit, | |
| skip, | |
| relationship_types, | |
| from_node_labels, | |
| to_node_labels, | |
| query_text, | |
| query_search_target, | |
| brain_id, | |
| ) | |
| async def get_entities( | |
| limit: int = 10, | |
| skip: int = 0, | |
| node_labels: Optional[str] = None, | |
| query_text: Optional[str] = None, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Retrieve entities matching optional label and text filters with pagination. | |
| Parameters: | |
| node_labels (Optional[str]): Comma-separated node labels to filter by (e.g. "Person,Company"); when provided, only entities with any of these labels are returned. | |
| query_text (Optional[str]): Free-text filter to match entity properties or content. | |
| brain_id (str): Identifier of the brain/knowledge store to query. | |
| Returns: | |
| list: A list of entity records that match the provided filters and pagination parameters. | |
| """ | |
| if node_labels: | |
| node_labels = node_labels.split(",") | |
| return await retrieve_get_entities_controller( | |
| limit, skip, node_labels, query_text, brain_id | |
| ) | |
| async def get_structured_data_types( | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Get all unique types from structured data. | |
| """ | |
| return await get_structured_data_types_controller(brain_id) | |
| async def get_structured_data_by_id( | |
| id: str, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Get structured data by ID. | |
| """ | |
| return await get_structured_data_by_id_controller(id, brain_id) | |
| async def get_structured_data_list( | |
| limit: int = 10, | |
| skip: int = 0, | |
| types: Optional[str] = None, | |
| query_text: Optional[str] = None, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Get a list of structured data. | |
| """ | |
| if types: | |
| types = types.split(",") | |
| return await get_structured_data_list_controller( | |
| limit, skip, types, query_text, brain_id | |
| ) | |
| async def get_text_chunks( | |
| brain_id: str = Depends(get_brain_id), | |
| limit: int = 10, | |
| skip: int = 0, | |
| query_text: Optional[str] = None, | |
| metadata_eq: Optional[str] = Query(default=None), | |
| order: Literal["asc", "desc"] = Query(default="desc"), | |
| ): | |
| """ | |
| Get text chunks by a query text and optional metadata equality filters. | |
| """ | |
| metadata_eq_filters: Optional[dict[str, str]] = None | |
| if metadata_eq: | |
| try: | |
| parsed_metadata_eq = json.loads(metadata_eq) | |
| except json.JSONDecodeError as exc: | |
| raise HTTPException( | |
| status_code=422, | |
| detail="metadata_eq must be a valid JSON object string", | |
| ) from exc | |
| if not isinstance(parsed_metadata_eq, dict): | |
| raise HTTPException( | |
| status_code=422, | |
| detail="metadata_eq must be a JSON object string", | |
| ) | |
| if any( | |
| not isinstance(key, str) or not isinstance(value, str) | |
| for key, value in parsed_metadata_eq.items() | |
| ): | |
| raise HTTPException( | |
| status_code=422, | |
| detail="metadata_eq must be a JSON object with string keys and string values", | |
| ) | |
| metadata_eq_filters = parsed_metadata_eq | |
| results, total = await get_text_chunks_controller( | |
| brain_id, limit, skip, query_text, metadata_eq_filters, order | |
| ) | |
| return JSONResponse( | |
| content={ | |
| "message": "Text chunks retrieved successfully", | |
| "data": [r.model_dump(mode="json") for r in results], | |
| "total": total, | |
| } | |
| ) | |
| async def get_observation_labels( | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Get all unique labels from observations. | |
| """ | |
| return await get_observation_labels_controller(brain_id) | |
| async def get_observation_by_id( | |
| id: str, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Get observation by ID. | |
| """ | |
| return await get_observation_by_id_controller(id, brain_id) | |
| async def get_observations_list( | |
| limit: int = 10, | |
| skip: int = 0, | |
| resource_id: Optional[str] = None, | |
| labels: Optional[str] = None, | |
| query_text: Optional[str] = None, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Retrieve a list of observations filtered by the provided parameters. | |
| Parameters: | |
| limit (int): Maximum number of observations to return. | |
| skip (int): Number of observations to skip (offset). | |
| resource_id (Optional[str]): If provided, only return observations for this resource identifier. | |
| labels (Optional[str]): Comma-separated observation labels to filter by; when provided, labels are treated as a list of strings. | |
| query_text (Optional[str]): Full-text query to filter observations. | |
| brain_id (str): Identifier of the brain/tenant to query. | |
| Returns: | |
| list: A list of observation records that match the provided filters. | |
| """ | |
| if labels: | |
| labels = labels.split(",") | |
| return await get_observations_list_controller( | |
| limit, skip, resource_id, labels, query_text, brain_id | |
| ) | |
| async def get_changelog_types( | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Retrieve all unique changelog types for the specified brain. | |
| Parameters: | |
| brain_id (str): Identifier of the brain to query; defaults to "default". | |
| Returns: | |
| list[str]: List of unique changelog type names. | |
| """ | |
| return await get_changelog_types_controller(brain_id) | |
| async def get_changelog_by_id( | |
| id: str, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Retrieve a changelog entry by its unique identifier. | |
| Parameters: | |
| id (str): Unique identifier of the changelog entry. | |
| brain_id (str): Brain identifier to query. Defaults to "default". | |
| Returns: | |
| The changelog entry corresponding to the specified identifier. | |
| """ | |
| return await get_changelog_by_id_controller(id, brain_id) | |
| async def get_changelogs_list( | |
| limit: int = 10, | |
| skip: int = 0, | |
| types: Optional[str] = None, | |
| query_text: Optional[str] = None, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Retrieve a paginated list of changelogs. | |
| Parameters: | |
| types (Optional[str]): Optional comma-separated changelog types to filter by; each type will be applied as a filter. | |
| query_text (Optional[str]): Optional text used to filter changelogs by content or metadata. | |
| Returns: | |
| list: Changelog records matching the provided filters, constrained by `limit` and `skip`. | |
| """ | |
| if types: | |
| types = types.split(",") | |
| return await get_changelogs_list_controller( | |
| limit, skip, types, query_text, brain_id | |
| ) | |
| async def get_hops( | |
| query: str, | |
| degrees: Literal[2] = 2, | |
| flattened: bool = True, | |
| brain_id: str = Depends(get_brain_id), | |
| ): # noqa: F821 | |
| """ | |
| Compute graph hops for the given query. | |
| Parameters: | |
| query (str): Search text or entity identifier to start hop traversal from. | |
| degrees (int): Maximum number of hop degrees to traverse (default 2). | |
| flattened (bool): If True, return a flattened list of hops; otherwise preserve nested hop structure. | |
| brain_id (str): Identifier of the brain (knowledge graph) to query. | |
| Returns: | |
| list: Hops (paths) connecting matching entities up to the specified degree; the exact structure varies based on `flattened`. | |
| """ | |
| return await get_hops_controller(query, degrees, flattened, brain_id) | |
| async def get_entity_info( | |
| target: str, | |
| query: str, | |
| max_depth: int = 3, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Retrieve detailed information for an entity identified by the given target and query. | |
| Parameters: | |
| target (str): Identifier or name of the target entity to retrieve. | |
| query (str): Query text used to refine or disambiguate the requested entity information. | |
| max_depth (int): Maximum graph depth to traverse when collecting related information. | |
| brain_id (str): Identifier of the brain/namespace to query. | |
| Returns: | |
| dict: A mapping containing the entity's attributes and related contextual information. | |
| """ | |
| return await get_entity_info_controller(target, query, max_depth, brain_id) | |
| async def get_entity_context( | |
| target: str, | |
| context_depth: int = 3, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Retrieve contextual information for an entity identified by `target`. | |
| Parameters: | |
| target (str): Identifier or name of the target entity. | |
| context_depth (int): Maximum depth of related context to include. | |
| brain_id (str): Identifier of the brain/knowledge graph to query. | |
| Returns: | |
| dict: A mapping containing the entity's contextual information. | |
| """ | |
| return await get_entity_context_controller(target, context_depth, brain_id) | |
| async def get_entity_synergies( | |
| target: str, | |
| polarity: Literal["same", "opposite"] = "same", | |
| do: bool = False, | |
| pa: bool = False, | |
| ppa: bool = False, | |
| top_k: int = 50, | |
| labels: Optional[List[str]] = None, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Retrieve synergies for a specified entity. | |
| Parameters: | |
| target: Identifier or name of the target entity. | |
| polarity: "same" for matching node polarity; "opposite" for positive↔negative. | |
| do: If True, only direct synergies are returned. | |
| pa: If True, potential anchors are returned. | |
| ppa: If True, seed anchors are returned. | |
| top_k: Maximum synergies to return (default 50). | |
| labels: Optional candidate label filter. | |
| brain_id: Identifier of the knowledge brain to query. | |
| Returns: | |
| Synergy records for the target entity matching the requested polarity. | |
| """ | |
| return await get_entity_sibilings_controller( | |
| target, polarity, do, pa, ppa, top_k, labels, brain_id | |
| ) | |
| async def get_recommend( | |
| target: str, | |
| polarity: Literal["same", "opposite"] = "same", | |
| top_k: int = 20, | |
| labels: Optional[List[str]] = None, | |
| include_asymmetric: bool = True, | |
| include_multi_interest: bool = True, | |
| include_attribute_pref: bool = False, | |
| diversify: bool = True, | |
| asymmetric_direction: Literal["outbound", "inbound", "both"] = "outbound", | |
| exclude_seen: bool = False, | |
| recency_half_life_days: Optional[float] = None, | |
| dampen_degree: bool = False, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Preview: ranked event-graph recommendations composing synergies, asymmetric | |
| complementary walks, multi-interest medoids, and optional attribute | |
| preferences (retrieval-time only; no training). | |
| """ | |
| return await get_recommendations_controller( | |
| target, | |
| polarity, | |
| top_k, | |
| labels, | |
| include_asymmetric, | |
| include_multi_interest, | |
| diversify, | |
| asymmetric_direction, | |
| brain_id, | |
| exclude_seen, | |
| recency_half_life_days, | |
| dampen_degree, | |
| include_attribute_pref, | |
| None, | |
| ) | |
| async def post_recommend( | |
| body: RecommendRequestBody, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """Preview recommendation surface; request and response compatibility is kept.""" | |
| return await get_recommendations_controller( | |
| body.target, | |
| body.polarity, | |
| body.top_k, | |
| body.labels, | |
| body.include_asymmetric, | |
| body.include_multi_interest, | |
| body.diversify, | |
| body.asymmetric_direction, | |
| brain_id or body.brain_id, | |
| body.exclude_seen, | |
| body.recency_half_life_days, | |
| body.dampen_degree, | |
| body.include_attribute_pref, | |
| body.behavior_weights, | |
| ) | |
| async def get_search( | |
| query: str = Query(..., description="The search query."), | |
| k: int = Query(10, ge=1, le=200, description="Number of hits to return."), | |
| channels: Optional[str] = Query( | |
| "passages", | |
| description=( | |
| "Comma-separated channels: passages, entities, events, " | |
| "communities, and/or plugin:<name>." | |
| ), | |
| ), | |
| node_labels: Optional[str] = Query( | |
| None, | |
| description="Comma-separated node labels to filter the entities channel.", | |
| ), | |
| community_labels: Optional[str] = Query( | |
| None, | |
| description="Comma-separated hub labels for the communities channel.", | |
| ), | |
| expand: Literal["none", "neighbors"] = Query( | |
| "none", | |
| description="Optional 1-hop expansion from graph channel seeds.", | |
| ), | |
| fusion: Optional[Literal["rrf", "cc"]] = Query( | |
| None, description="Fusion override. Default is SEARCH_FUSION." | |
| ), | |
| rerank: Optional[str] = Query( | |
| None, | |
| description="none or plugin:<name>. Unknown plugin names return 400.", | |
| ), | |
| target: Optional[str] = Query( | |
| None, | |
| description="Optional USER uuid or id for query-gated rerank of retrieved hits.", | |
| ), | |
| profile_stages: bool = Query(False), | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| channel_list = [ | |
| item.strip() | |
| for item in (channels or "passages").split(",") | |
| if item.strip() | |
| ] or ["passages"] | |
| node_label_list = [ | |
| item.strip() | |
| for item in (node_labels or "").split(",") | |
| if item.strip() | |
| ] or None | |
| community_label_list = [ | |
| item.strip() | |
| for item in (community_labels or "").split(",") | |
| if item.strip() | |
| ] or None | |
| request = SearchRequestBody( | |
| query=query, | |
| k=k, | |
| channels=channel_list, | |
| node_labels=node_label_list, | |
| community_labels=community_label_list, | |
| expand=expand, | |
| fusion=fusion, | |
| rerank=rerank, | |
| target=target, | |
| profile_stages=profile_stages, | |
| brain_id=brain_id, | |
| ) | |
| return await search_controller(request) | |
| async def post_search( | |
| body: SearchRequestBody, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| body.brain_id = brain_id or body.brain_id | |
| return await search_controller(body) | |
| async def get_entity_status( | |
| target: str, | |
| types: Optional[List[str]] = None, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| Retrieve status information for a specified entity. | |
| Parameters: | |
| target (str): Identifier or name of the entity to inspect. | |
| types (Optional[List[str]]): Optional list of entity types to filter the status computation. | |
| brain_id (str): Identifier of the brain (knowledge graph) to query. | |
| Returns: | |
| status (dict): A dictionary containing the entity's status details. | |
| """ | |
| return await get_entity_status_controller(target, types or [], brain_id) | |
| async def get_vector_stores(): | |
| """ | |
| List available vector store names and dimensions. | |
| """ | |
| return await get_vector_stores_controller() | |
| async def get_vectors_list( | |
| store: str, | |
| limit: int = 10, | |
| skip: int = 0, | |
| include_embeddings: bool = False, | |
| brain_id: str = Depends(get_brain_id), | |
| ): | |
| """ | |
| List vectors in a store with pagination. | |
| """ | |
| return await list_vectors_controller( | |
| store, brain_id, limit, skip, include_embeddings | |
| ) | |