11""" FastAPI server for the Cognee API. """
2+ from datetime import datetime
23import os
4+ from uuid import UUID
35import aiohttp
46import uvicorn
57import logging
68import sentry_sdk
7- from typing import Dict , Any , List , Union , Optional , Literal
9+ from typing import List , Union , Optional , Literal
810from typing_extensions import Annotated
911from fastapi import FastAPI , HTTPException , Form , UploadFile , Query , Depends
1012from fastapi .responses import JSONResponse , FileResponse , Response
1113from fastapi .middleware .cors import CORSMiddleware
1214from pydantic import BaseModel
15+
16+ from cognee .api .DTO import InDTO , OutDTO
1317from cognee .api .v1 .search import SearchType
1418from cognee .modules .users .models import User
1519from cognee .modules .users .methods import get_authenticated_user
20+ from cognee .modules .pipelines .models import PipelineRunStatus
1621
1722
1823# Set up logging
@@ -124,48 +129,54 @@ async def root():
124129 """
125130 return {"message" : "Hello, World, I am alive!" }
126131
132+
127133@app .get ("/health" )
128134def health_check ():
129135 """
130136 Health check endpoint that returns the server status.
131137 """
132138 return Response (status_code = 200 )
133139
134- @app .get ("/api/v1/datasets" , response_model = list )
140+
141+ class ErrorResponseDTO (BaseModel ):
142+ message : str
143+
144+
145+ class DatasetDTO (OutDTO ):
146+ id : UUID
147+ name : str
148+ created_at : datetime
149+ updated_at : Optional [datetime ]
150+ owner_id : UUID
151+
152+ @app .get ("/api/v1/datasets" , response_model = list [DatasetDTO ])
135153async def get_datasets (user : User = Depends (get_authenticated_user )):
136154 try :
137155 from cognee .modules .data .methods import get_datasets
138156 datasets = await get_datasets (user .id )
139157
140- return JSONResponse (
141- status_code = 200 ,
142- content = [dataset .to_json () for dataset in datasets ],
143- )
158+ return datasets
144159 except Exception as error :
160+ logger .error (f"Error retrieving datasets: { str (error )} " )
145161 raise HTTPException (status_code = 500 , detail = f"Error retrieving datasets: { str (error )} " ) from error
146162
147- @app .delete ("/api/v1/datasets/{dataset_id}" , response_model = dict )
163+
164+ @app .delete ("/api/v1/datasets/{dataset_id}" , response_model = None , responses = { 404 : { "model" : ErrorResponseDTO }})
148165async def delete_dataset (dataset_id : str , user : User = Depends (get_authenticated_user )):
149166 from cognee .modules .data .methods import get_dataset , delete_dataset
150167
151- dataset = get_dataset (user .id , dataset_id )
168+ dataset = await get_dataset (user .id , dataset_id )
152169
153170 if dataset is None :
154- return JSONResponse (
171+ raise HTTPException (
155172 status_code = 404 ,
156- content = {
157- "detail" : f"Dataset ({ dataset_id } ) not found."
158- }
173+ detail = f"Dataset ({ dataset_id } ) not found."
159174 )
160175
161176 await delete_dataset (dataset )
162177
163- return JSONResponse (
164- status_code = 200 ,
165- content = "OK" ,
166- )
167178
168- @app .get ("/api/v1/datasets/{dataset_id}/graph" , response_model = list )
179+ @app .get ("/api/v1/datasets/{dataset_id}/graph" , response_model = str )
169180async def get_dataset_graph (dataset_id : str , user : User = Depends (get_authenticated_user )):
170181 from cognee .shared .utils import render_graph
171182 from cognee .infrastructure .databases .graph import get_graph_engine
@@ -184,7 +195,17 @@ async def get_dataset_graph(dataset_id: str, user: User = Depends(get_authentica
184195 content = "Graphistry credentials are not set. Please set them in your .env file." ,
185196 )
186197
187- @app .get ("/api/v1/datasets/{dataset_id}/data" , response_model = list )
198+
199+ class DataDTO (OutDTO ):
200+ id : UUID
201+ name : str
202+ created_at : datetime
203+ updated_at : Optional [datetime ]
204+ extension : str
205+ mime_type : str
206+ raw_data_location : str
207+
208+ @app .get ("/api/v1/datasets/{dataset_id}/data" , response_model = list [DataDTO ], responses = { 404 : { "model" : ErrorResponseDTO }})
188209async def get_dataset_data (dataset_id : str , user : User = Depends (get_authenticated_user )):
189210 from cognee .modules .data .methods import get_dataset_data , get_dataset
190211
@@ -193,38 +214,33 @@ async def get_dataset_data(dataset_id: str, user: User = Depends(get_authenticat
193214 if dataset is None :
194215 return JSONResponse (
195216 status_code = 404 ,
196- content = {
197- "detail" : f"Dataset ({ dataset_id } ) not found."
198- }
217+ content = ErrorResponseDTO (f"Dataset ({ dataset_id } ) not found." ),
199218 )
200219
201220 dataset_data = await get_dataset_data (dataset_id = dataset .id )
202221
203222 if dataset_data is None :
204- raise HTTPException (status_code = 404 , detail = f"Dataset ({ dataset .id } ) not found." )
223+ return []
224+
225+ return dataset_data
205226
206- return [
207- data .to_json () for data in dataset_data
208- ]
209227
210- @app .get ("/api/v1/datasets/status" , response_model = dict )
228+ @app .get ("/api/v1/datasets/status" , response_model = dict [ str , PipelineRunStatus ] )
211229async def get_dataset_status (datasets : Annotated [List [str ], Query (alias = "dataset" )] = None , user : User = Depends (get_authenticated_user )):
212230 from cognee .api .v1 .datasets .datasets import datasets as cognee_datasets
213231
214232 try :
215233 datasets_statuses = await cognee_datasets .get_status (datasets )
216234
217- return JSONResponse (
218- status_code = 200 ,
219- content = datasets_statuses ,
220- )
235+ return datasets_statuses
221236 except Exception as error :
222237 return JSONResponse (
223238 status_code = 409 ,
224239 content = {"error" : str (error )}
225240 )
226241
227- @app .get ("/api/v1/datasets/{dataset_id}/data/{data_id}/raw" , response_class = FileResponse )
242+
243+ @app .get ("/api/v1/datasets/{dataset_id}/data/{data_id}/raw" , response_class = FileResponse )
228244async def get_raw_data (dataset_id : str , data_id : str , user : User = Depends (get_authenticated_user )):
229245 from cognee .modules .data .methods import get_dataset , get_dataset_data
230246
@@ -255,13 +271,8 @@ async def get_raw_data(dataset_id: str, data_id: str, user: User = Depends(get_a
255271
256272 return data .raw_data_location
257273
258- class AddPayload (BaseModel ):
259- data : Union [str , UploadFile , List [Union [str , UploadFile ]]]
260- dataset_id : str
261- class Config :
262- arbitrary_types_allowed = True
263274
264- @app .post ("/api/v1/add" , response_model = dict )
275+ @app .post ("/api/v1/add" , response_model = None )
265276async def add (
266277 data : List [UploadFile ],
267278 datasetId : str = Form (...),
@@ -297,90 +308,89 @@ async def add(
297308 datasetId ,
298309 user = user ,
299310 )
300- return JSONResponse (
301- status_code = 200 ,
302- content = {
303- "message" : "OK"
304- }
305- )
306311 except Exception as error :
307312 return JSONResponse (
308313 status_code = 409 ,
309314 content = {"error" : str (error )}
310315 )
311316
312- class CognifyPayload (BaseModel ):
317+
318+ class CognifyPayloadDTO (BaseModel ):
313319 datasets : List [str ]
314320
315- @app .post ("/api/v1/cognify" , response_model = dict )
316- async def cognify (payload : CognifyPayload , user : User = Depends (get_authenticated_user )):
321+ @app .post ("/api/v1/cognify" , response_model = None )
322+ async def cognify (payload : CognifyPayloadDTO , user : User = Depends (get_authenticated_user )):
317323 """ This endpoint is responsible for the cognitive processing of the content."""
318324 from cognee .api .v1 .cognify .cognify_v2 import cognify as cognee_cognify
319325 try :
320326 await cognee_cognify (payload .datasets , user )
321- return JSONResponse (
322- status_code = 200 ,
323- content = {
324- "message" : "OK"
325- }
326- )
327327 except Exception as error :
328328 return JSONResponse (
329329 status_code = 409 ,
330330 content = {"error" : str (error )}
331331 )
332332
333- class SearchPayload (BaseModel ):
334- searchType : SearchType
333+
334+ class SearchPayloadDTO (InDTO ):
335+ search_type : SearchType
335336 query : str
336337
337- @app .post ("/api/v1/search" , response_model = list )
338- async def search (payload : SearchPayload , user : User = Depends (get_authenticated_user )):
338+ @app .post ("/api/v1/search" , response_model = list )
339+ async def search (payload : SearchPayloadDTO , user : User = Depends (get_authenticated_user )):
339340 """ This endpoint is responsible for searching for nodes in the graph."""
340341 from cognee .api .v1 .search import search as cognee_search
342+
341343 try :
342- results = await cognee_search (payload .searchType , payload .query , user )
344+ results = await cognee_search (payload .search_type , payload .query , user )
343345
344- return JSONResponse (
345- status_code = 200 ,
346- content = results ,
347- )
346+ return results
348347 except Exception as error :
349348 return JSONResponse (
350349 status_code = 409 ,
351350 content = {"error" : str (error )}
352351 )
353352
354- @app .get ("/api/v1/settings" , response_model = dict )
353+ from cognee .modules .settings .get_settings import LLMConfig , VectorDBConfig
354+
355+ class LLMConfigDTO (OutDTO , LLMConfig ):
356+ pass
357+
358+ class VectorDBConfigDTO (OutDTO , VectorDBConfig ):
359+ pass
360+
361+ class SettingsDTO (OutDTO ):
362+ llm : LLMConfigDTO
363+ vector_db : VectorDBConfigDTO
364+
365+ @app .get ("/api/v1/settings" , response_model = SettingsDTO )
355366async def get_settings (user : User = Depends (get_authenticated_user )):
356367 from cognee .modules .settings import get_settings as get_cognee_settings
357368 return get_cognee_settings ()
358369
359- class LLMConfig (BaseModel ):
370+
371+ class LLMConfigDTO (InDTO ):
360372 provider : Union [Literal ["openai" ], Literal ["ollama" ], Literal ["anthropic" ]]
361373 model : str
362- apiKey : str
374+ api_key : str
363375
364- class VectorDBConfig ( BaseModel ):
376+ class VectorDBConfigDTO ( InDTO ):
365377 provider : Union [Literal ["lancedb" ], Literal ["qdrant" ], Literal ["weaviate" ]]
366378 url : str
367- apiKey : str
379+ api_key : str
368380
369- class SettingsPayload ( BaseModel ):
370- llm : Optional [LLMConfig ] = None
371- vectorDB : Optional [VectorDBConfig ] = None
381+ class SettingsPayloadDTO ( InDTO ):
382+ llm : Optional [LLMConfigDTO ] = None
383+ vector_db : Optional [VectorDBConfigDTO ] = None
372384
373- @app .post ("/api/v1/settings" , response_model = dict )
374- async def save_config (new_settings : SettingsPayload , user : User = Depends (get_authenticated_user )):
385+ @app .post ("/api/v1/settings" , response_model = None )
386+ async def save_settings (new_settings : SettingsPayloadDTO , user : User = Depends (get_authenticated_user )):
375387 from cognee .modules .settings import save_llm_config , save_vector_db_config
388+
376389 if new_settings .llm is not None :
377390 await save_llm_config (new_settings .llm )
378- if new_settings .vectorDB is not None :
379- await save_vector_db_config (new_settings .vectorDB )
380- return JSONResponse (
381- status_code = 200 ,
382- content = "OK" ,
383- )
391+
392+ if new_settings .vector_db is not None :
393+ await save_vector_db_config (new_settings .vector_db )
384394
385395
386396def start_api_server (host : str = "0.0.0.0" , port : int = 8000 ):
0 commit comments