diff --git a/.env.template b/.env.template index ba7126182..da862f285 100644 --- a/.env.template +++ b/.env.template @@ -62,3 +62,6 @@ DB_NAME=cognee_db # MIGRATION_DB_PASSWORD=cognee # MIGRATION_DB_HOST="127.0.0.1" # MIGRATION_DB_PORT=5432 + +# LITELLM Logging Level. Set to quiten down logging +LITELLM_LOG="ERROR" diff --git a/cognee-frontend/src/app/auth/AuthPage.tsx b/cognee-frontend/src/app/auth/AuthPage.tsx index 7b7391039..9cfb5e89f 100644 --- a/cognee-frontend/src/app/auth/AuthPage.tsx +++ b/cognee-frontend/src/app/auth/AuthPage.tsx @@ -9,9 +9,9 @@ import SignInForm from '@/ui/Partials/SignInForm/SignInForm'; export default function AuthPage() { return (
- + - + diff --git a/cognee-frontend/src/app/favicon.ico b/cognee-frontend/src/app/favicon.ico index 718d6fea4..f3b120fe0 100644 Binary files a/cognee-frontend/src/app/favicon.ico and b/cognee-frontend/src/app/favicon.ico differ diff --git a/cognee-frontend/src/app/favicon.png b/cognee-frontend/src/app/favicon.png new file mode 100644 index 000000000..90e5fa392 Binary files /dev/null and b/cognee-frontend/src/app/favicon.png differ diff --git a/cognee-frontend/src/app/globals.css b/cognee-frontend/src/app/globals.css index 7179f07b6..118237db8 100644 --- a/cognee-frontend/src/app/globals.css +++ b/cognee-frontend/src/app/globals.css @@ -5,6 +5,12 @@ "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", monospace; + --button-padding: 14px 20px !important; + --button-border-radius: 100px !important; + --global-color-primary: #6510F4 !important; + --global-color-primary-active: #500cc5 !important; + --global-color-primary-text: white !important; + --global-color-secondary: #0DFF00 !important; --global-background-default: #0D051C; --textarea-default-color: #0D051C !important; } diff --git a/cognee-frontend/src/app/page.module.css b/cognee-frontend/src/app/page.module.css index 02878d478..696d52720 100644 --- a/cognee-frontend/src/app/page.module.css +++ b/cognee-frontend/src/app/page.module.css @@ -11,7 +11,6 @@ display: flex; flex-direction: row; flex: 1; - gap: 32px; } .datasetsView { @@ -28,6 +27,7 @@ .dataView { width: 70%; animation: grow-width 0.3s ease-in-out; + padding: 0 0 0 32px; } @keyframes grow-width { diff --git a/cognee-frontend/src/app/page.tsx b/cognee-frontend/src/app/page.tsx index e1aafe01b..3d8a04dc2 100644 --- a/cognee-frontend/src/app/page.tsx +++ b/cognee-frontend/src/app/page.tsx @@ -68,9 +68,9 @@ export default function Home() { return (
- + - + diff --git a/cognee-frontend/src/app/wizard/AddStep/AddStep.tsx b/cognee-frontend/src/app/wizard/AddStep/AddStep.tsx index f377a46e4..6052ac52c 100644 --- a/cognee-frontend/src/app/wizard/AddStep/AddStep.tsx +++ b/cognee-frontend/src/app/wizard/AddStep/AddStep.tsx @@ -21,7 +21,7 @@ export default function AddStep({ onNext }: ConfigStepProps) { const uploadFiles = useCallback(() => { disableUploading() - addData({ id: 'main' }, files) + addData({ name: 'main' }, files) .then(() => { onNext(); }) diff --git a/cognee-frontend/src/app/wizard/WizardPage.tsx b/cognee-frontend/src/app/wizard/WizardPage.tsx index 2c3aeccfd..1a9158975 100644 --- a/cognee-frontend/src/app/wizard/WizardPage.tsx +++ b/cognee-frontend/src/app/wizard/WizardPage.tsx @@ -33,9 +33,9 @@ export default function WizardPage({ return (
- + - + {wizardStep === 'explore' && ( diff --git a/cognee-frontend/src/modules/exploration/getExplorationGraphUrl.ts b/cognee-frontend/src/modules/exploration/getExplorationGraphUrl.ts index 185f16a81..080302691 100644 --- a/cognee-frontend/src/modules/exploration/getExplorationGraphUrl.ts +++ b/cognee-frontend/src/modules/exploration/getExplorationGraphUrl.ts @@ -1,13 +1,12 @@ import { fetch } from '@/utils'; export default function getExplorationGraphUrl(dataset: { id: string }) { - return fetch(`/v1/datasets/${dataset.id}/graph`) + return fetch('/v1/visualize') .then(async (response) => { if (response.status !== 200) { throw new Error((await response.text()).replaceAll("\"", "")); } return response; }) - .then((response) => response.text()) - .then((text) => text.replace('"', '')); + .then((response) => response.text()); } diff --git a/cognee-frontend/src/modules/ingestion/addData.ts b/cognee-frontend/src/modules/ingestion/addData.ts index caa280837..601c6f884 100644 --- a/cognee-frontend/src/modules/ingestion/addData.ts +++ b/cognee-frontend/src/modules/ingestion/addData.ts @@ -1,11 +1,16 @@ import { fetch } from '@/utils'; -export default function addData(dataset: { id: string }, files: File[]) { +export default function addData(dataset: { id?: string, name?: string }, files: File[]) { const formData = new FormData(); files.forEach((file) => { formData.append('data', file, file.name); }) - formData.append('datasetId', dataset.id); + if (dataset.id) { + formData.append('datasetId', dataset.id); + } + if (dataset.name) { + formData.append('datasetName', dataset.name); + } return fetch('/v1/add', { method: 'POST', diff --git a/cognee-frontend/src/ui/App/Loading/CognifyLoadingIndicator/CognifyLoadingIndicator.module.css b/cognee-frontend/src/ui/App/Loading/CognifyLoadingIndicator/CognifyLoadingIndicator.module.css index 1ce50963d..1c2388373 100644 --- a/cognee-frontend/src/ui/App/Loading/CognifyLoadingIndicator/CognifyLoadingIndicator.module.css +++ b/cognee-frontend/src/ui/App/Loading/CognifyLoadingIndicator/CognifyLoadingIndicator.module.css @@ -3,7 +3,7 @@ width: 106px; height: 106px; border-radius: 50%; - background: linear-gradient(90deg, #D82EB5 0.52%, #9245FD 103.83%); + background: linear-gradient(90deg, #6510F4 0.52%, #0DFF00 103.83%); } .donut1.spin { animation: rotate1 1s linear infinite; @@ -13,13 +13,13 @@ width: 76px; height: 76px; border-radius: 50%; - background: linear-gradient(90deg, #D82EB5 0.52%, #9245FD 103.83%); + background: linear-gradient(90deg, #6510F4 0.52%, #0DFF00 103.83%); position: relative; left: 15px; top: 15px; } .donut2.spin { - background: linear-gradient(270deg, #D82EB5 0.52%, #9245FD 103.83%); + background: linear-gradient(270deg, #6510F4 0.52%, #0DFF00 103.83%); animation: rotate1 1s linear infinite; } @@ -27,7 +27,7 @@ width: 46px; height: 46px; border-radius: 50%; - background: linear-gradient(90deg, #D82EB5 0.52%, #9245FD 103.83%); + background: linear-gradient(90deg, #6510F4 0.52%, #0DFF00 103.83%); position: relative; left: 15px; top: 15px; diff --git a/cognee-frontend/src/ui/App/Logo/Logo.tsx b/cognee-frontend/src/ui/App/Logo/Logo.tsx deleted file mode 100644 index 26dc86135..000000000 --- a/cognee-frontend/src/ui/App/Logo/Logo.tsx +++ /dev/null @@ -1,13 +0,0 @@ -export default function Logo({ width = 29, height = 32, className = '' }) { - return ( - - - - - - - - - - ); -} \ No newline at end of file diff --git a/cognee-frontend/src/ui/App/Logo/TextLogo.tsx b/cognee-frontend/src/ui/App/Logo/TextLogo.tsx new file mode 100644 index 000000000..2ea9607a0 --- /dev/null +++ b/cognee-frontend/src/ui/App/Logo/TextLogo.tsx @@ -0,0 +1,7 @@ +export default function TextLogo({ width = 158, height = 44, color = 'currentColor', className = '' }) { + return ( + + + + ); +} diff --git a/cognee-frontend/src/ui/App/Logo/TextLogo.v1.tsx b/cognee-frontend/src/ui/App/Logo/TextLogo.v1.tsx deleted file mode 100644 index 884f63d61..000000000 --- a/cognee-frontend/src/ui/App/Logo/TextLogo.v1.tsx +++ /dev/null @@ -1,14 +0,0 @@ -export default function TextLogo({ width = 160, height = 42, color = 'currentColor', className = '' }) { - return ( - - - - - - - - - - - ); -} \ No newline at end of file diff --git a/cognee-frontend/src/ui/App/Logo/TextLogo.v2.tsx b/cognee-frontend/src/ui/App/Logo/TextLogo.v2.tsx deleted file mode 100644 index e16206363..000000000 --- a/cognee-frontend/src/ui/App/Logo/TextLogo.v2.tsx +++ /dev/null @@ -1,29 +0,0 @@ -export default function TextLogo({ width = 285, height = 81, color = 'white' }) { - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - ); -} \ No newline at end of file diff --git a/cognee-frontend/src/ui/App/index.ts b/cognee-frontend/src/ui/App/index.ts index d0f095694..719972a6d 100644 --- a/cognee-frontend/src/ui/App/index.ts +++ b/cognee-frontend/src/ui/App/index.ts @@ -1,4 +1,3 @@ -export { default as Logo } from './Logo/Logo'; -export { default as TextLogo } from './Logo/TextLogo.v2'; +export { default as TextLogo } from './Logo/TextLogo'; export { default as LoadingIndicator } from './Loading/DefaultLoadingIndicator/LoadingIndicator'; export { default as CognifyLoadingIndicator } from './Loading/CognifyLoadingIndicator/CognifyLoadingIndicator'; diff --git a/cognee-frontend/src/ui/Layout/Divider/Divider.module.css b/cognee-frontend/src/ui/Layout/Divider/Divider.module.css index e9e33d6f9..ec3854f3f 100644 --- a/cognee-frontend/src/ui/Layout/Divider/Divider.module.css +++ b/cognee-frontend/src/ui/Layout/Divider/Divider.module.css @@ -1,5 +1,5 @@ .divider { height: 1px; - background: linear-gradient(90deg, #D82EB5 0.52%, #9245FD 103.83%); + background: linear-gradient(90deg, #6510F4 0.52%, #0DFF00 103.83%); } diff --git a/cognee-frontend/src/ui/Partials/Explorer/Explorer.tsx b/cognee-frontend/src/ui/Partials/Explorer/Explorer.tsx index ea50a726a..8ae30c1e9 100644 --- a/cognee-frontend/src/ui/Partials/Explorer/Explorer.tsx +++ b/cognee-frontend/src/ui/Partials/Explorer/Explorer.tsx @@ -1,9 +1,9 @@ -import { useCallback, useEffect, useState } from 'react'; import classNames from 'classnames'; +import { useCallback, useEffect, useState } from 'react'; import { Spacer, Stack, Text } from 'ohmy-ui'; -import { getExplorationGraphUrl } from '@/modules/exploration'; -import { IFrameView, SearchView } from '@/ui/Partials'; import { LoadingIndicator } from '@/ui/App'; +import { IFrameView, SearchView } from '@/ui/Partials'; +import { getExplorationGraphUrl } from '@/modules/exploration'; import styles from './Explorer.module.css'; interface ExplorerProps { @@ -14,13 +14,13 @@ interface ExplorerProps { export default function Explorer({ dataset, className, style }: ExplorerProps) { const [error, setError] = useState(null); - const [graphUrl, setGraphUrl] = useState(null); + const [graphHtml, setGraphHtml] = useState(null); const exploreData = useCallback(() => { getExplorationGraphUrl(dataset) - .then((graphUrl) => { + .then((graphHtml) => { setError(null); - setGraphUrl(graphUrl); + setGraphHtml(graphHtml); }) .catch((error) => { setError(error); @@ -43,12 +43,12 @@ export default function Explorer({ dataset, className, style }: ExplorerProps) { {error.message} ) : ( <> - {!graphUrl ? ( + {!graphHtml ? ( ) : ( - + )} )} diff --git a/cognee-frontend/src/ui/Partials/Footer/Footer.tsx b/cognee-frontend/src/ui/Partials/Footer/Footer.tsx index ac74f5dc2..17b4f854e 100644 --- a/cognee-frontend/src/ui/Partials/Footer/Footer.tsx +++ b/cognee-frontend/src/ui/Partials/Footer/Footer.tsx @@ -13,10 +13,10 @@ export default function Footer() {
- + - +
diff --git a/cognee-frontend/src/ui/Partials/SearchView/SearchView.tsx b/cognee-frontend/src/ui/Partials/SearchView/SearchView.tsx index b4fa07777..8def51c00 100644 --- a/cognee-frontend/src/ui/Partials/SearchView/SearchView.tsx +++ b/cognee-frontend/src/ui/Partials/SearchView/SearchView.tsx @@ -31,11 +31,11 @@ export default function SearchView() { value: 'INSIGHTS', label: 'Query insights from documents', }, { - value: 'SUMMARIES', - label: 'Query document summaries', + value: 'GRAPH_COMPLETION', + label: 'Completion using Cognee\'s graph based memory', }, { - value: 'CHUNKS', - label: 'Query document chunks', + value: 'RAG_COMPLETION', + label: 'Completion using RAG', }]; const [searchType, setSearchType] = useState(searchOptions[0]); @@ -167,6 +167,10 @@ type InsightMessage = [Node, Relationship, Node]; function convertToSearchTypeOutput(systemMessages: any[], searchType: string): string { + if (systemMessages.length > 0 && typeof(systemMessages[0]) === "string") { + return systemMessages[0]; + } + switch (searchType) { case 'INSIGHTS': return systemMessages.map((message: InsightMessage) => { @@ -181,6 +185,6 @@ function convertToSearchTypeOutput(systemMessages: any[], searchType: string): s case 'CHUNKS': return systemMessages.map((message: { text: string }) => message.text).join('\n'); default: - return ''; + return ""; } } diff --git a/cognee-frontend/src/ui/Partials/SettingsModal/Settings.tsx b/cognee-frontend/src/ui/Partials/SettingsModal/Settings.tsx index 08574bd6b..9d8b2ff75 100644 --- a/cognee-frontend/src/ui/Partials/SettingsModal/Settings.tsx +++ b/cognee-frontend/src/ui/Partials/SettingsModal/Settings.tsx @@ -21,7 +21,11 @@ interface SelectOption { interface SettingsForm extends HTMLFormElement { vectorDBUrl: HTMLInputElement; vectorDBApiKey: HTMLInputElement; + llmProvider: HTMLInputElement; + llmModel: HTMLInputElement; llmApiKey: HTMLInputElement; + llmEndpoint: HTMLInputElement; + llmApiVersion: HTMLInputElement; } const defaultProvider = { @@ -37,18 +41,16 @@ const defaultModel = { export default function Settings({ onDone = () => {}, submitButtonText = 'Save' }) { const [llmConfig, setLLMConfig] = useState<{ apiKey: string; - model: SelectOption; - models: { - [key: string]: SelectOption[]; - }; - provider: SelectOption; - providers: SelectOption[]; + model: string; + endpoint: string; + apiVersion: string; + provider: string; }>(); const [vectorDBConfig, setVectorDBConfig] = useState<{ url: string; apiKey: string; provider: SelectOption; - options: SelectOption[]; + providers: SelectOption[]; }>(); const { @@ -68,9 +70,11 @@ export default function Settings({ onDone = () => {}, submitButtonText = 'Save' }; const newLLMConfig = { - provider: llmConfig?.provider.value, - model: llmConfig?.model.value, + provider: formElements.llmProvider.value, + model: formElements.llmModel.value, apiKey: formElements.llmApiKey.value, + endpoint: formElements.llmEndpoint.value, + apiVersion: formElements.llmApiVersion.value, }; startSaving(); @@ -96,7 +100,7 @@ export default function Settings({ onDone = () => {}, submitButtonText = 'Save' if (config?.provider !== newVectorDBProvider) { return { ...config, - options: config?.options || [], + providers: config?.providers || [], provider: newVectorDBProvider, url: '', apiKey: '', @@ -106,43 +110,21 @@ export default function Settings({ onDone = () => {}, submitButtonText = 'Save' }); }, []); - const handleLLMProviderChange = useCallback((newLLMProvider: SelectOption) => { - setLLMConfig((config) => { - if (config?.provider !== newLLMProvider) { - return { - provider: newLLMProvider, - providers: config?.providers || [], - model: config?.models?.[newLLMProvider.value]?.[0] || defaultModel, - models: config?.models || {}, - apiKey: config?.apiKey || '', - }; - } - return config; - }); - }, []); - - const handleLLMModelChange = useCallback((newLLMModel: SelectOption) => { - setLLMConfig((config) => { - if (config?.model !== newLLMModel) { - return { - provider: config?.provider || defaultProvider, - providers: config?.providers || [], - model: newLLMModel, - models: config?.models || {}, - apiKey: config?.apiKey || '', - }; - } - return config; - }); - }, []); - useEffect(() => { const fetchConfig = async () => { const response = await fetch('/v1/settings'); const settings = await response.json(); + if (!settings.llm.provider) { + settings.llm.provider = settings.llm.providers[0].value; + } if (!settings.llm.model) { - settings.llm.model = settings.llm.models[settings.llm.provider.value][0]; + settings.llm.model = settings.llm.models[settings.llm.provider][0].value; + } + if (!settings.vectorDb.provider) { + settings.vectorDb.provider = settings.vectorDb.providers[0]; + } else { + settings.vectorDb.provider = settings.vectorDb.providers.find((provider: SelectOption) => provider.value === settings.vectorDb.provider); } setLLMConfig(settings.llm); setVectorDBConfig(settings.vectorDb); @@ -151,28 +133,39 @@ export default function Settings({ onDone = () => {}, submitButtonText = 'Save' }, []); return ( -
+ LLM provider: - + + + LLM model: - + + + + + + LLM endpoint: + + + + + + LLM API key: + + + + + + LLM API version: + + + - - - @@ -180,7 +173,7 @@ export default function Settings({ onDone = () => {}, submitButtonText = 'Save' Vector DB provider: diff --git a/cognee-frontend/src/ui/Partials/SignInForm/SignInForm.tsx b/cognee-frontend/src/ui/Partials/SignInForm/SignInForm.tsx index 24b5c6d30..a7477d126 100644 --- a/cognee-frontend/src/ui/Partials/SignInForm/SignInForm.tsx +++ b/cognee-frontend/src/ui/Partials/SignInForm/SignInForm.tsx @@ -67,13 +67,13 @@ export default function SignInForm({ onSignInSuccess = () => window.location.hre Email: - + Password: - + diff --git a/cognee-frontend/src/ui/Partials/Wizard/WizardContent/WizardContent.module.css b/cognee-frontend/src/ui/Partials/Wizard/WizardContent/WizardContent.module.css index 31e2d88fe..b9d6f2d4b 100644 --- a/cognee-frontend/src/ui/Partials/Wizard/WizardContent/WizardContent.module.css +++ b/cognee-frontend/src/ui/Partials/Wizard/WizardContent/WizardContent.module.css @@ -2,7 +2,7 @@ width: 100%; max-width: 400px; height: max-content; - background: linear-gradient(90deg, #D82EB5 0.52%, #9245FD 103.83%); + background: linear-gradient(90deg, #6510F4 0.52%, #0DFF00 103.83%); padding: 24px; margin: 0 auto; position: relative; diff --git a/cognee/api/v1/add/routers/get_add_router.py b/cognee/api/v1/add/routers/get_add_router.py index f96b6f477..a27c6c502 100644 --- a/cognee/api/v1/add/routers/get_add_router.py +++ b/cognee/api/v1/add/routers/get_add_router.py @@ -1,8 +1,10 @@ +from uuid import UUID from fastapi import Form, UploadFile, Depends from fastapi.responses import JSONResponse from fastapi import APIRouter -from typing import List +from typing import List, Optional import subprocess +from cognee.modules.data.methods import get_dataset from cognee.shared.logging_utils import get_logger import requests @@ -18,12 +20,23 @@ def get_add_router() -> APIRouter: @router.post("/", response_model=None) async def add( data: List[UploadFile], - datasetId: str = Form(...), + datasetId: Optional[UUID] = Form(default=None), + datasetName: Optional[str] = Form(default=None), user: User = Depends(get_authenticated_user), ): """This endpoint is responsible for adding data to the graph.""" from cognee.api.v1.add import add as cognee_add + if not datasetId and not datasetName: + raise ValueError("Either datasetId or datasetName must be provided.") + + if datasetId and not datasetName: + dataset = await get_dataset(user_id=user.id, dataset_id=datasetId) + try: + datasetName = dataset.name + except IndexError: + raise ValueError("No dataset found with the provided datasetName.") + try: if isinstance(data, str) and data.startswith("http"): if "github" in data: @@ -43,7 +56,7 @@ def get_add_router() -> APIRouter: return await cognee_add(file_data) else: - await cognee_add(data, datasetId, user=user) + await cognee_add(data, datasetName, user=user) except Exception as error: return JSONResponse(status_code=409, content={"error": str(error)}) diff --git a/cognee/api/v1/datasets/datasets.py b/cognee/api/v1/datasets/datasets.py index a6552d937..c81f9326c 100644 --- a/cognee/api/v1/datasets/datasets.py +++ b/cognee/api/v1/datasets/datasets.py @@ -1,3 +1,4 @@ +from uuid import UUID from cognee.modules.users.methods import get_default_user from cognee.modules.ingestion import discover_directory_datasets from cognee.modules.pipelines.operations.get_pipeline_status import get_pipeline_status @@ -26,7 +27,7 @@ class datasets: return await get_dataset_data(dataset.id) @staticmethod - async def get_status(dataset_ids: list[str]) -> dict: + async def get_status(dataset_ids: list[UUID]) -> dict: return await get_pipeline_status(dataset_ids) @staticmethod diff --git a/cognee/api/v1/datasets/routers/get_datasets_router.py b/cognee/api/v1/datasets/routers/get_datasets_router.py index e7325a713..48cd70d8d 100644 --- a/cognee/api/v1/datasets/routers/get_datasets_router.py +++ b/cognee/api/v1/datasets/routers/get_datasets_router.py @@ -59,13 +59,13 @@ def get_datasets_router() -> APIRouter: @router.delete( "/{dataset_id}", response_model=None, responses={404: {"model": ErrorResponseDTO}} ) - async def delete_dataset(dataset_id: str, user: User = Depends(get_authenticated_user)): + async def delete_dataset(dataset_id: UUID, user: User = Depends(get_authenticated_user)): from cognee.modules.data.methods import get_dataset, delete_dataset dataset = await get_dataset(user.id, dataset_id) if dataset is None: - raise EntityNotFoundError(message=f"Dataset ({dataset_id}) not found.") + raise EntityNotFoundError(message=f"Dataset ({str(dataset_id)}) not found.") await delete_dataset(dataset) @@ -75,7 +75,7 @@ def get_datasets_router() -> APIRouter: responses={404: {"model": ErrorResponseDTO}}, ) async def delete_data( - dataset_id: str, data_id: str, user: User = Depends(get_authenticated_user) + dataset_id: UUID, data_id: UUID, user: User = Depends(get_authenticated_user) ): from cognee.modules.data.methods import get_data, delete_data from cognee.modules.data.methods import get_dataset @@ -85,17 +85,17 @@ def get_datasets_router() -> APIRouter: # TODO: Handle situation differently if user doesn't have permission to access data? if dataset is None: - raise EntityNotFoundError(message=f"Dataset ({dataset_id}) not found.") + raise EntityNotFoundError(message=f"Dataset ({str(dataset_id)}) not found.") data = await get_data(user.id, data_id) if data is None: - raise EntityNotFoundError(message=f"Data ({data_id}) not found.") + raise EntityNotFoundError(message=f"Data ({str(data_id)}) not found.") await delete_data(data) @router.get("/{dataset_id}/graph", response_model=str) - async def get_dataset_graph(dataset_id: str, user: User = Depends(get_authenticated_user)): + async def get_dataset_graph(dataset_id: UUID, user: User = Depends(get_authenticated_user)): from cognee.shared.utils import render_graph from cognee.infrastructure.databases.graph import get_graph_engine @@ -119,7 +119,7 @@ def get_datasets_router() -> APIRouter: response_model=list[DataDTO], responses={404: {"model": ErrorResponseDTO}}, ) - async def get_dataset_data(dataset_id: str, user: User = Depends(get_authenticated_user)): + async def get_dataset_data(dataset_id: UUID, user: User = Depends(get_authenticated_user)): from cognee.modules.data.methods import get_dataset_data, get_dataset dataset = await get_dataset(user.id, dataset_id) @@ -127,7 +127,7 @@ def get_datasets_router() -> APIRouter: if dataset is None: return JSONResponse( status_code=404, - content=ErrorResponseDTO(f"Dataset ({dataset_id}) not found."), + content=ErrorResponseDTO(f"Dataset ({str(dataset_id)}) not found."), ) dataset_data = await get_dataset_data(dataset_id=dataset.id) @@ -139,7 +139,7 @@ def get_datasets_router() -> APIRouter: @router.get("/status", response_model=dict[str, PipelineRunStatus]) async def get_dataset_status( - datasets: Annotated[List[str], Query(alias="dataset")] = None, + datasets: Annotated[List[UUID], Query(alias="dataset")] = None, user: User = Depends(get_authenticated_user), ): from cognee.api.v1.datasets.datasets import datasets as cognee_datasets @@ -153,7 +153,7 @@ def get_datasets_router() -> APIRouter: @router.get("/{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) + dataset_id: UUID, data_id: UUID, user: User = Depends(get_authenticated_user) ): from cognee.modules.data.methods import get_data from cognee.modules.data.methods import get_dataset, get_dataset_data @@ -170,7 +170,7 @@ def get_datasets_router() -> APIRouter: if dataset_data is None: raise EntityNotFoundError(message=f"No data found in dataset ({dataset_id}).") - matching_data = [data for data in dataset_data if str(data.id) == data_id] + matching_data = [data for data in dataset_data if data.id == data_id] # Check if matching_data contains an element if len(matching_data) == 0: diff --git a/cognee/api/v1/users/routers/get_visualize_router.py b/cognee/api/v1/users/routers/get_visualize_router.py index d92c9689f..153bb5bfa 100644 --- a/cognee/api/v1/users/routers/get_visualize_router.py +++ b/cognee/api/v1/users/routers/get_visualize_router.py @@ -1,9 +1,6 @@ -from fastapi import Depends -from fastapi.responses import JSONResponse from fastapi import APIRouter +from fastapi.responses import HTMLResponse, JSONResponse from cognee.shared.logging_utils import get_logger -from cognee.modules.users.models import User -from cognee.modules.users.methods import get_authenticated_user logger = get_logger() @@ -11,16 +8,14 @@ logger = get_logger() def get_visualize_router() -> APIRouter: router = APIRouter() - @router.post("/", response_model=None) - async def visualize( - user: User = Depends(get_authenticated_user), - ): + @router.get("/", response_model=None) + async def visualize(): """This endpoint is responsible for adding data to the graph.""" from cognee.api.v1.visualize import visualize_graph try: html_visualization = await visualize_graph() - return html_visualization + return HTMLResponse(html_visualization) except Exception as error: return JSONResponse(status_code=409, content={"error": str(error)}) diff --git a/cognee/modules/settings/get_settings.py b/cognee/modules/settings/get_settings.py index 063c18971..876474559 100644 --- a/cognee/modules/settings/get_settings.py +++ b/cognee/modules/settings/get_settings.py @@ -18,8 +18,10 @@ class ModelName(Enum): class LLMConfig(BaseModel): api_key: str - model: ConfigChoice - provider: ConfigChoice + model: str + provider: str + endpoint: str + api_version: str models: dict[str, list[ConfigChoice]] providers: list[ConfigChoice] @@ -27,7 +29,7 @@ class LLMConfig(BaseModel): class VectorDBConfig(BaseModel): api_key: str url: str - provider: ConfigChoice + provider: str providers: list[ConfigChoice] @@ -82,19 +84,11 @@ def get_settings() -> SettingsDict: return SettingsDict.model_validate( dict( llm={ - "provider": { - "label": llm_config.llm_provider, - "value": llm_config.llm_provider, - } - if llm_config.llm_provider - else llm_providers[0], - "model": { - "value": llm_config.llm_model, - "label": llm_config.llm_model, - } - if llm_config.llm_model - else None, - "api_key": (llm_config.llm_api_key[:-10] + "**********") + "provider": llm_config.llm_provider, + "model": llm_config.llm_model, + "endpoint": llm_config.llm_endpoint, + "api_version": llm_config.llm_api_version, + "api_key": (llm_config.llm_api_key[0:10] + "*" * (len(llm_config.llm_api_key) - 10)) if llm_config.llm_api_key else None, "providers": llm_providers, @@ -150,12 +144,12 @@ def get_settings() -> SettingsDict: }, }, vector_db={ - "provider": { - "label": vector_config.vector_db_provider, - "value": vector_config.vector_db_provider.lower(), - }, + "provider": vector_config.vector_db_provider, "url": vector_config.vector_db_url, - "api_key": vector_config.vector_db_key, + "api_key": ( + vector_config.vector_db_key[0:10] + + "*" * (len(vector_config.vector_db_key) - 10) + ), "providers": vector_dbs, }, ) diff --git a/cognee/modules/settings/save_vector_db_config.py b/cognee/modules/settings/save_vector_db_config.py index 7c48435a8..44b917cf7 100644 --- a/cognee/modules/settings/save_vector_db_config.py +++ b/cognee/modules/settings/save_vector_db_config.py @@ -13,5 +13,7 @@ async def save_vector_db_config(vector_db_config: VectorDBConfig): vector_config = get_vectordb_config() vector_config.vector_db_url = vector_db_config.url - vector_config.vector_db_key = vector_db_config.api_key vector_config.vector_db_provider = vector_db_config.provider + + if "*****" not in vector_db_config.api_key and len(vector_db_config.api_key.strip()) > 0: + vector_config.vector_db_key = vector_db_config.api_key diff --git a/cognee/modules/users/permissions/methods/check_permission_on_documents.py b/cognee/modules/users/permissions/methods/check_permission_on_documents.py index b2386b06a..54c5f0c35 100644 --- a/cognee/modules/users/permissions/methods/check_permission_on_documents.py +++ b/cognee/modules/users/permissions/methods/check_permission_on_documents.py @@ -37,5 +37,5 @@ async def check_permission_on_documents(user: User, permission_type: str, docume if not has_permissions: raise PermissionDeniedError( - message=f"User {user.email} does not have {permission_type} permission on documents" + message=f"User {user.id} does not have {permission_type} permission on documents" ) diff --git a/docker-compose.yml b/docker-compose.yml index d9ad50d63..0e5195900 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,7 @@ services: - .:/app - /app/cognee-frontend/ # Ignore frontend code environment: + - DEBUG=false # Change to true if debugging - HOST=0.0.0.0 - ENVIRONMENT=local - PYTHONPATH=. @@ -18,30 +19,32 @@ services: - "host.docker.internal:host-gateway" ports: - 8000:8000 - # - 5678:5678 # Debugging + - 5678:5678 # Debugger port deploy: resources: limits: - cpus: "2.0" + cpus: "4.0" memory: 8GB # NOTE: Frontend is a work in progress and is not intended to be used by users yet. # If you want to use Cognee with a UI environment you can run the cognee-gui.py script or # integrate the Cognee MCP Server to Cursor / Claude Desktop / Visual Studio Code ( through Cline/Roo ) -# frontend: -# container_name: frontend -# build: -# context: ./cognee-frontend -# dockerfile: Dockerfile -# volumes: -# - ./cognee-frontend/src:/app/src -# - ./cognee-frontend/public:/app/public -# ports: -# - 3000:3000 -# # - 9229:9229 # Debugging -# networks: -# - cognee-network + frontend: + container_name: frontend + profiles: + - ui + build: + context: ./cognee-frontend + dockerfile: Dockerfile + volumes: + - ./cognee-frontend/src:/app/src + - ./cognee-frontend/public:/app/public + ports: + - 3000:3000 + # - 9229:9229 # Debugging + networks: + - cognee-network neo4j: image: neo4j:latest @@ -86,21 +89,20 @@ services: ports: - "3002:8000" - # UNCOMMENT IF USING POSTGRES - # postgres: - # image: pgvector/pgvector:pg17 - # container_name: postgres - # environment: - # POSTGRES_USER: cognee - # POSTGRES_PASSWORD: cognee - # POSTGRES_DB: cognee_db - # volumes: - # - postgres_data:/var/lib/postgresql/data - # ports: - # - 5432:5432 - # networks: - # - cognee-network - # UNCOMMENT THE VOLUES SECTION BELOW AS WELL TO USE POSTGRES + postgres: + image: pgvector/pgvector:pg17 + container_name: postgres + profiles: + - postgres + environment: + POSTGRES_USER: cognee + POSTGRES_PASSWORD: cognee + POSTGRES_DB: cognee_db + # - postgres_data:/var/lib/postgresql/data + ports: + - 5432:5432 + networks: + - cognee-network networks: cognee-network: @@ -108,5 +110,4 @@ networks: volumes: chromadb_data: -# UNCOMMENT IF USING POSTGRES -# postgres_data: + postgres_data: diff --git a/entrypoint.sh b/entrypoint.sh index edb198443..5874f7e51 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -4,8 +4,7 @@ set -e # Exit on error echo "Debug mode: $DEBUG" echo "Environment: $ENVIRONMENT" -# Run Alembic migrations with proper error handling - +# Run Alembic migrations with proper error handling. # Note on UserAlreadyExists error handling: # During database migrations, we attempt to create a default user. If this user # already exists (e.g., from a previous deployment or migration), it's not a @@ -30,7 +29,7 @@ echo "Starting Gunicorn" sleep 2 # Modified Gunicorn startup with error handling -if [ "$ENVIRONMENT" = "dev" ]; then +if [ "$ENVIRONMENT" = "dev" ] || [ "$ENVIRONMENT" = "local" ]; then if [ "$DEBUG" = "true" ]; then echo "Waiting for the debugger to attach..." exec python -m debugpy --wait-for-client --listen 0.0.0.0:5678 -m gunicorn -w 3 -k uvicorn.workers.UvicornWorker -t 30000 --bind=0.0.0.0:8000 --log-level debug --reload cognee.api.client:app