Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: improve API request and response models and docs #154

Merged
merged 5 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ To use different LLM providers, for more info check out our <a href="https://top

If you are using Networkx, create an account on Graphistry to visualize results:
```
cognee.config.set_graphistry_config({
"username": "YOUR_USERNAME",
"password": "YOUR_PASSWORD"
})
cognee.config.set_graphistry_config({
"username": "YOUR_USERNAME",
"password": "YOUR_PASSWORD"
})
```

(Optional) To run the UI, go to cognee-frontend directory and run:
Expand Down
4 changes: 2 additions & 2 deletions cognee-frontend/src/ui/Partials/SettingsModal/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export default function Settings({ onDone = () => {}, submitButtonText = 'Save'
},
body: JSON.stringify({
llm: newLLMConfig,
vectorDB: newVectorConfig,
vectorDb: newVectorConfig,
borisarzentar marked this conversation as resolved.
Show resolved Hide resolved
}),
})
.then(() => {
Expand Down Expand Up @@ -145,7 +145,7 @@ export default function Settings({ onDone = () => {}, submitButtonText = 'Save'
settings.llm.model = settings.llm.models[settings.llm.provider.value][0];
}
setLLMConfig(settings.llm);
setVectorDBConfig(settings.vectorDB);
setVectorDBConfig(settings.vectorDb);
};
fetchConfig();
}, []);
Expand Down
15 changes: 15 additions & 0 deletions cognee/api/DTO.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from pydantic import BaseModel, ConfigDict
from pydantic.alias_generators import to_camel, to_snake


class OutDTO(BaseModel):
model_config = ConfigDict(
alias_generator = to_camel,
populate_by_name = True,
)

class InDTO(BaseModel):
model_config = ConfigDict(
alias_generator = to_camel,
populate_by_name = True,
)
borisarzentar marked this conversation as resolved.
Show resolved Hide resolved
160 changes: 85 additions & 75 deletions cognee/api/client.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
""" FastAPI server for the Cognee API. """
from datetime import datetime
import os
from uuid import UUID
import aiohttp
import uvicorn
import logging
import sentry_sdk
from typing import Dict, Any, List, Union, Optional, Literal
from typing import List, Union, Optional, Literal
from typing_extensions import Annotated
from fastapi import FastAPI, HTTPException, Form, UploadFile, Query, Depends
from fastapi.responses import JSONResponse, FileResponse, Response
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel

from cognee.api.DTO import InDTO, OutDTO
from cognee.api.v1.search import SearchType
from cognee.modules.users.models import User
from cognee.modules.users.methods import get_authenticated_user
from cognee.modules.pipelines.models import PipelineRunStatus


# Set up logging
Expand Down Expand Up @@ -124,27 +129,39 @@ async def root():
"""
return {"message": "Hello, World, I am alive!"}


@app.get("/health")
def health_check():
"""
Health check endpoint that returns the server status.
"""
return Response(status_code = 200)

@app.get("/api/v1/datasets", response_model = list)

class ErrorResponseDTO(BaseModel):
message: str


class DatasetDTO(OutDTO):
id: UUID
name: str
created_at: datetime
updated_at: Optional[datetime]
owner_id: UUID

@app.get("/api/v1/datasets", response_model = list[DatasetDTO])
async def get_datasets(user: User = Depends(get_authenticated_user)):
try:
from cognee.modules.data.methods import get_datasets
datasets = await get_datasets(user.id)

return JSONResponse(
status_code = 200,
content = [dataset.to_json() for dataset in datasets],
)
return datasets
except Exception as error:
logger.error(f"Error retrieving datasets: {str(error)}")
raise HTTPException(status_code = 500, detail = f"Error retrieving datasets: {str(error)}") from error

@app.delete("/api/v1/datasets/{dataset_id}", response_model = dict)

@app.delete("/api/v1/datasets/{dataset_id}", response_model = None, responses = { 404: { "model": ErrorResponseDTO }})
async def delete_dataset(dataset_id: str, user: User = Depends(get_authenticated_user)):
from cognee.modules.data.methods import get_dataset, delete_dataset

Expand All @@ -153,19 +170,13 @@ async def delete_dataset(dataset_id: str, user: User = Depends(get_authenticated
if dataset is None:
return JSONResponse(
status_code = 404,
content = {
"detail": f"Dataset ({dataset_id}) not found."
}
content = ErrorResponseDTO(f"Dataset ({dataset_id}) not found."),
)

await delete_dataset(dataset)

return JSONResponse(
status_code = 200,
content = "OK",
)

@app.get("/api/v1/datasets/{dataset_id}/graph", response_model=list)
@app.get("/api/v1/datasets/{dataset_id}/graph", response_model = str)
async def get_dataset_graph(dataset_id: str, user: User = Depends(get_authenticated_user)):
from cognee.shared.utils import render_graph
from cognee.infrastructure.databases.graph import get_graph_engine
Expand All @@ -184,7 +195,17 @@ async def get_dataset_graph(dataset_id: str, user: User = Depends(get_authentica
content = "Graphistry credentials are not set. Please set them in your .env file.",
)

@app.get("/api/v1/datasets/{dataset_id}/data", response_model=list)

class DataDTO(OutDTO):
id: UUID
name: str
created_at: datetime
updated_at: Optional[datetime]
extension: str
mime_type: str
raw_data_location: str

@app.get("/api/v1/datasets/{dataset_id}/data", response_model = list[DataDTO], responses = { 404: { "model": ErrorResponseDTO }})
async def get_dataset_data(dataset_id: str, user: User = Depends(get_authenticated_user)):
from cognee.modules.data.methods import get_dataset_data, get_dataset

Expand All @@ -193,38 +214,33 @@ async def get_dataset_data(dataset_id: str, user: User = Depends(get_authenticat
if dataset is None:
return JSONResponse(
status_code = 404,
content = {
"detail": f"Dataset ({dataset_id}) not found."
}
content = ErrorResponseDTO(f"Dataset ({dataset_id}) not found."),
borisarzentar marked this conversation as resolved.
Show resolved Hide resolved
)

dataset_data = await get_dataset_data(dataset_id = dataset.id)

if dataset_data is None:
raise HTTPException(status_code = 404, detail = f"Dataset ({dataset.id}) not found.")
return []

return dataset_data

return [
data.to_json() for data in dataset_data
]

@app.get("/api/v1/datasets/status", response_model=dict)
@app.get("/api/v1/datasets/status", response_model = dict[str, PipelineRunStatus])
async def get_dataset_status(datasets: Annotated[List[str], Query(alias="dataset")] = None, user: User = Depends(get_authenticated_user)):
from cognee.api.v1.datasets.datasets import datasets as cognee_datasets

try:
datasets_statuses = await cognee_datasets.get_status(datasets)

return JSONResponse(
status_code = 200,
content = datasets_statuses,
)
return datasets_statuses
except Exception as error:
return JSONResponse(
status_code = 409,
content = {"error": str(error)}
)

@app.get("/api/v1/datasets/{dataset_id}/data/{data_id}/raw", response_class=FileResponse)

@app.get("/api/v1/datasets/{dataset_id}/data/{data_id}/raw", response_class = FileResponse)
async def get_raw_data(dataset_id: str, data_id: str, user: User = Depends(get_authenticated_user)):
from cognee.modules.data.methods import get_dataset, get_dataset_data

Expand Down Expand Up @@ -255,13 +271,8 @@ async def get_raw_data(dataset_id: str, data_id: str, user: User = Depends(get_a

return data.raw_data_location

class AddPayload(BaseModel):
data: Union[str, UploadFile, List[Union[str, UploadFile]]]
dataset_id: str
class Config:
arbitrary_types_allowed = True

@app.post("/api/v1/add", response_model=dict)
@app.post("/api/v1/add", response_model = None)
borisarzentar marked this conversation as resolved.
Show resolved Hide resolved
async def add(
data: List[UploadFile],
datasetId: str = Form(...),
Expand Down Expand Up @@ -297,90 +308,89 @@ async def add(
datasetId,
user = user,
)
return JSONResponse(
status_code = 200,
content = {
"message": "OK"
}
)
except Exception as error:
return JSONResponse(
status_code = 409,
content = {"error": str(error)}
)

class CognifyPayload(BaseModel):

class CognifyPayloadDTO(BaseModel):
datasets: List[str]

@app.post("/api/v1/cognify", response_model=dict)
async def cognify(payload: CognifyPayload, user: User = Depends(get_authenticated_user)):
@app.post("/api/v1/cognify", response_model = None)
async def cognify(payload: CognifyPayloadDTO, user: User = Depends(get_authenticated_user)):
""" This endpoint is responsible for the cognitive processing of the content."""
from cognee.api.v1.cognify.cognify_v2 import cognify as cognee_cognify
try:
await cognee_cognify(payload.datasets, user)
return JSONResponse(
status_code = 200,
content = {
"message": "OK"
}
)
except Exception as error:
return JSONResponse(
status_code = 409,
content = {"error": str(error)}
)

class SearchPayload(BaseModel):
searchType: SearchType

class SearchPayloadDTO(InDTO):
search_type: SearchType
query: str

@app.post("/api/v1/search", response_model=list)
async def search(payload: SearchPayload, user: User = Depends(get_authenticated_user)):
@app.post("/api/v1/search", response_model = list)
async def search(payload: SearchPayloadDTO, user: User = Depends(get_authenticated_user)):
""" This endpoint is responsible for searching for nodes in the graph."""
from cognee.api.v1.search import search as cognee_search

try:
results = await cognee_search(payload.searchType, payload.query, user)
results = await cognee_search(payload.search_type, payload.query, user)

return JSONResponse(
status_code = 200,
content = results,
)
return results
borisarzentar marked this conversation as resolved.
Show resolved Hide resolved
except Exception as error:
return JSONResponse(
status_code = 409,
content = {"error": str(error)}
)

@app.get("/api/v1/settings", response_model=dict)
from cognee.modules.settings.get_settings import LLMConfig, VectorDBConfig
borisarzentar marked this conversation as resolved.
Show resolved Hide resolved

class LLMConfigDTO(OutDTO, LLMConfig):
pass

class VectorDBConfigDTO(OutDTO, VectorDBConfig):
pass

class SettingsDTO(OutDTO):
llm: LLMConfigDTO
vector_db: VectorDBConfigDTO

@app.get("/api/v1/settings", response_model = SettingsDTO)
async def get_settings(user: User = Depends(get_authenticated_user)):
from cognee.modules.settings import get_settings as get_cognee_settings
return get_cognee_settings()

class LLMConfig(BaseModel):

class LLMConfigDTO(InDTO):
provider: Union[Literal["openai"], Literal["ollama"], Literal["anthropic"]]
model: str
apiKey: str
api_key: str
borisarzentar marked this conversation as resolved.
Show resolved Hide resolved

class VectorDBConfig(BaseModel):
class VectorDBConfigDTO(InDTO):
provider: Union[Literal["lancedb"], Literal["qdrant"], Literal["weaviate"]]
url: str
apiKey: str
api_key: str
borisarzentar marked this conversation as resolved.
Show resolved Hide resolved

class SettingsPayload(BaseModel):
llm: Optional[LLMConfig] = None
vectorDB: Optional[VectorDBConfig] = None
class SettingsPayloadDTO(InDTO):
llm: Optional[LLMConfigDTO] = None
vector_db: Optional[VectorDBConfigDTO] = None

@app.post("/api/v1/settings", response_model=dict)
async def save_config(new_settings: SettingsPayload, user: User = Depends(get_authenticated_user)):
@app.post("/api/v1/settings", response_model = None)
async def save_settings(new_settings: SettingsPayloadDTO, user: User = Depends(get_authenticated_user)):
from cognee.modules.settings import save_llm_config, save_vector_db_config

if new_settings.llm is not None:
await save_llm_config(new_settings.llm)
if new_settings.vectorDB is not None:
await save_vector_db_config(new_settings.vectorDB)
return JSONResponse(
status_code=200,
content="OK",
)

if new_settings.vector_db is not None:
await save_vector_db_config(new_settings.vector_db)
borisarzentar marked this conversation as resolved.
Show resolved Hide resolved


def start_api_server(host: str = "0.0.0.0", port: int = 8000):
Expand Down
4 changes: 2 additions & 2 deletions cognee/infrastructure/llm/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ def to_dict(self) -> dict:
"provider": self.llm_provider,
"model": self.llm_model,
"endpoint": self.llm_endpoint,
"apiKey": self.llm_api_key,
"api_key": self.llm_api_key,
"temperature": self.llm_temperature,
"streaming": self.llm_stream,
borisarzentar marked this conversation as resolved.
Show resolved Hide resolved
"transcriptionModel": self.transcription_model
"transcription_model": self.transcription_model
}

@lru_cache
Expand Down
6 changes: 6 additions & 0 deletions cognee/modules/pipelines/models/PipelineRun.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
from enum import Enum
from uuid import uuid4
from datetime import datetime, timezone
from sqlalchemy import Column, DateTime, String, JSON
from cognee.infrastructure.databases.relational import Base, UUID

class PipelineRunStatus(Enum):
DATASET_PROCESSING_STARTED = "DATASET_PROCESSING_STARTED"
DATASET_PROCESSING_COMPLETED = "DATASET_PROCESSING_COMPLETED"
DATASET_PROCESSING_FAILED = "DATASET_PROCESSING_ERRORED"
borisarzentar marked this conversation as resolved.
Show resolved Hide resolved

class PipelineRun(Base):
__tablename__ = "pipeline_runs"

Expand Down
2 changes: 1 addition & 1 deletion cognee/modules/pipelines/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .PipelineRun import PipelineRun
from .PipelineRun import PipelineRun, PipelineRunStatus
2 changes: 1 addition & 1 deletion cognee/modules/settings/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from .get_settings import get_settings
from .get_settings import get_settings, SettingsDict
from .save_llm_config import save_llm_config
from .save_vector_db_config import save_vector_db_config
Loading
Loading