Skip to content

[BUG] Cannot get minimal example to work with Ollama #868

@Powerkrieger

Description

@Powerkrieger

Bug Description

I tried setting up the quickstart example with the Ollama configuration from the README. I get a pydantic Field required error.

Steps to Reproduce

Provide a minimal code example that reproduces the issue:

import asyncio
import json
import logging
from datetime import datetime, timezone
from logging import INFO

from dotenv import load_dotenv
from graphiti_core import Graphiti
from graphiti_core.cross_encoder.openai_reranker_client import OpenAIRerankerClient
from graphiti_core.embedder.openai import OpenAIEmbedder, OpenAIEmbedderConfig
from graphiti_core.llm_client.config import LLMConfig
from graphiti_core.llm_client.openai_generic_client import OpenAIGenericClient
from graphiti_core.nodes import EpisodeType


async def main():
    # Configure logging
    logging.basicConfig(
        level=INFO,
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S',
    )
    logger = logging.getLogger(__name__)
    load_dotenv()

    # Configure Ollama LLM client
    llm_config = LLMConfig(
        api_key="abc",  # Ollama doesn't require a real API key
        model="deepseek-r1:7b",
        small_model="deepseek-r1:7b",
        base_url="http://xxx.xxx.xxx.xxx:11434/v1",  # Ollama provides this port
    )

    llm_client = OpenAIGenericClient(config=llm_config)
    try:
        # Initialize Graphiti with Ollama clients
        graphiti = Graphiti(
            "bolt://localhost:7687",
            "neo4j",
            "password",
            llm_client=llm_client,
            embedder=OpenAIEmbedder(
                config=OpenAIEmbedderConfig(
                    api_key="abc",
                    embedding_model="nomic-embed-text",
                    embedding_dim=768,
                    base_url="http://xxx.xxx.xxx.xxx:11434/v1",
                )
            ),
            cross_encoder=OpenAIRerankerClient(client=llm_client, config=llm_config),
        )

        await graphiti.build_indices_and_constraints()

        # Episodes list containing both text and JSON episodes
        episodes = [
            {
                'content': 'Kamala Harris is the Attorney General of California. She was previously '
                           'the district attorney for San Francisco.',
                'type': EpisodeType.text,
                'description': 'podcast transcript',
            },
            {
                'content': 'As AG, Harris was in office from January 3, 2011 – January 3, 2017',
                'type': EpisodeType.text,
                'description': 'podcast transcript',
            },
            {
                'content': {
                    'name': 'Gavin Newsom',
                    'position': 'Governor',
                    'state': 'California',
                    'previous_role': 'Lieutenant Governor',
                    'previous_location': 'San Francisco',
                },
                'type': EpisodeType.json,
                'description': 'podcast metadata',
            },
            {
                'content': {
                    'name': 'Gavin Newsom',
                    'position': 'Governor',
                    'term_start': 'January 7, 2019',
                    'term_end': 'Present',
                },
                'type': EpisodeType.json,
                'description': 'podcast metadata',
            },
        ]

        # Add episodes to the graph
        for i, episode in enumerate(episodes):
            await graphiti.add_episode(
                name=f'Freakonomics Radio {i}',
                episode_body=episode['content']
                if isinstance(episode['content'], str)
                else json.dumps(episode['content']),
                source=episode['type'],
                source_description=episode['description'],
                reference_time=datetime.now(timezone.utc),
            )
            print(f'Added episode: Freakonomics Radio {i} ({episode["type"].value})')

        # Perform a hybrid search combining semantic similarity and BM25 retrieval
        print("\nSearching for: 'Who was the California Attorney General?'")
        results = await graphiti.search('Who was the California Attorney General?')

        # Print search results
        print('\nSearch Results:')
        for result in results:
            print(f'UUID: {result.uuid}')
            print(f'Fact: {result.fact}')
            if hasattr(result, 'valid_at') and result.valid_at:
                print(f'Valid from: {result.valid_at}')
            if hasattr(result, 'invalid_at') and result.invalid_at:
                print(f'Valid until: {result.invalid_at}')
            print('---')


    # Now you can use Graphiti with local Ollama models
    finally:
        # Close the connection
        await graphiti.close()
        print('\nConnection closed')

if __name__ == "__main__":
    asyncio.run(main())

Expected Behavior

Small minimal Example where I can see that graphiti works.

Actual Behavior

Program crashes with Error, no entries in db.

Environment

  • Graphiti-core Version: 0.18.9
  • Python Version: 3.10.18
  • Operating System: Ubunut 24.04
  • Database Backend: e.g. Neo4j 5.26 (neo4j-desktop 2.0.3)
  • LLM Provider & Model: Ollama, deepseek-r1:8b, deepseek-r1:7b, deepseek-v2:236b

Installation Method

  • uv add

Error Messages/Traceback

2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX community_uuid IF NOT EXISTS FOR (e:Community) ON (e.uuid)` has no effect.} {description: `RANGE INDEX community_uuid FOR (e:Community) ON (e.uuid)` already exists.} {position: None} for query: 'CREATE INDEX community_uuid IF NOT EXISTS FOR (n:Community) ON (n.uuid)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX relation_uuid IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON (e.uuid)` has no effect.} {description: `RANGE INDEX relation_uuid FOR ()-[e:RELATES_TO]-() ON (e.uuid)` already exists.} {position: None} for query: 'CREATE INDEX relation_uuid IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON (e.uuid)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX episode_uuid IF NOT EXISTS FOR (e:Episodic) ON (e.uuid)` has no effect.} {description: `RANGE INDEX episode_uuid FOR (e:Episodic) ON (e.uuid)` already exists.} {position: None} for query: 'CREATE INDEX episode_uuid IF NOT EXISTS FOR (n:Episodic) ON (n.uuid)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX entity_uuid IF NOT EXISTS FOR (e:Entity) ON (e.uuid)` has no effect.} {description: `RANGE INDEX entity_uuid FOR (e:Entity) ON (e.uuid)` already exists.} {position: None} for query: 'CREATE INDEX entity_uuid IF NOT EXISTS FOR (n:Entity) ON (n.uuid)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX created_at_entity_index IF NOT EXISTS FOR (e:Entity) ON (e.created_at)` has no effect.} {description: `RANGE INDEX created_at_entity_index FOR (e:Entity) ON (e.created_at)` already exists.} {position: None} for query: 'CREATE INDEX created_at_entity_index IF NOT EXISTS FOR (n:Entity) ON (n.created_at)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX mention_uuid IF NOT EXISTS FOR ()-[e:MENTIONS]-() ON (e.uuid)` has no effect.} {description: `RANGE INDEX mention_uuid FOR ()-[e:MENTIONS]-() ON (e.uuid)` already exists.} {position: None} for query: 'CREATE INDEX mention_uuid IF NOT EXISTS FOR ()-[e:MENTIONS]-() ON (e.uuid)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX has_member_uuid IF NOT EXISTS FOR ()-[e:HAS_MEMBER]-() ON (e.uuid)` has no effect.} {description: `RANGE INDEX has_member_uuid FOR ()-[e:HAS_MEMBER]-() ON (e.uuid)` already exists.} {position: None} for query: 'CREATE INDEX has_member_uuid IF NOT EXISTS FOR ()-[e:HAS_MEMBER]-() ON (e.uuid)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX mention_group_id IF NOT EXISTS FOR ()-[e:MENTIONS]-() ON (e.group_id)` has no effect.} {description: `RANGE INDEX mention_group_id FOR ()-[e:MENTIONS]-() ON (e.group_id)` already exists.} {position: None} for query: 'CREATE INDEX mention_group_id IF NOT EXISTS FOR ()-[e:MENTIONS]-() ON (e.group_id)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX community_group_id IF NOT EXISTS FOR (e:Community) ON (e.group_id)` has no effect.} {description: `RANGE INDEX community_group_id FOR (e:Community) ON (e.group_id)` already exists.} {position: None} for query: 'CREATE INDEX community_group_id IF NOT EXISTS FOR (n:Community) ON (n.group_id)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX valid_at_episodic_index IF NOT EXISTS FOR (e:Episodic) ON (e.valid_at)` has no effect.} {description: `RANGE INDEX valid_at_episodic_index FOR (e:Episodic) ON (e.valid_at)` already exists.} {position: None} for query: 'CREATE INDEX valid_at_episodic_index IF NOT EXISTS FOR (n:Episodic) ON (n.valid_at)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX name_edge_index IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON (e.name)` has no effect.} {description: `RANGE INDEX name_edge_index FOR ()-[e:RELATES_TO]-() ON (e.name)` already exists.} {position: None} for query: 'CREATE INDEX name_edge_index IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON (e.name)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX relation_group_id IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON (e.group_id)` has no effect.} {description: `RANGE INDEX relation_group_id FOR ()-[e:RELATES_TO]-() ON (e.group_id)` already exists.} {position: None} for query: 'CREATE INDEX relation_group_id IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON (e.group_id)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX name_entity_index IF NOT EXISTS FOR (e:Entity) ON (e.name)` has no effect.} {description: `RANGE INDEX name_entity_index FOR (e:Entity) ON (e.name)` already exists.} {position: None} for query: 'CREATE INDEX name_entity_index IF NOT EXISTS FOR (n:Entity) ON (n.name)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX episode_group_id IF NOT EXISTS FOR (e:Episodic) ON (e.group_id)` has no effect.} {description: `RANGE INDEX episode_group_id FOR (e:Episodic) ON (e.group_id)` already exists.} {position: None} for query: 'CREATE INDEX episode_group_id IF NOT EXISTS FOR (n:Episodic) ON (n.group_id)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX created_at_episodic_index IF NOT EXISTS FOR (e:Episodic) ON (e.created_at)` has no effect.} {description: `RANGE INDEX created_at_episodic_index FOR (e:Episodic) ON (e.created_at)` already exists.} {position: None} for query: 'CREATE INDEX created_at_episodic_index IF NOT EXISTS FOR (n:Episodic) ON (n.created_at)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX entity_group_id IF NOT EXISTS FOR (e:Entity) ON (e.group_id)` has no effect.} {description: `RANGE INDEX entity_group_id FOR (e:Entity) ON (e.group_id)` already exists.} {position: None} for query: 'CREATE INDEX entity_group_id IF NOT EXISTS FOR (n:Entity) ON (n.group_id)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX created_at_edge_index IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON (e.created_at)` has no effect.} {description: `RANGE INDEX created_at_edge_index FOR ()-[e:RELATES_TO]-() ON (e.created_at)` already exists.} {position: None} for query: 'CREATE INDEX created_at_edge_index IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON (e.created_at)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX valid_at_edge_index IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON (e.valid_at)` has no effect.} {description: `RANGE INDEX valid_at_edge_index FOR ()-[e:RELATES_TO]-() ON (e.valid_at)` already exists.} {position: None} for query: 'CREATE INDEX valid_at_edge_index IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON (e.valid_at)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX invalid_at_edge_index IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON (e.invalid_at)` has no effect.} {description: `RANGE INDEX invalid_at_edge_index FOR ()-[e:RELATES_TO]-() ON (e.invalid_at)` already exists.} {position: None} for query: 'CREATE INDEX invalid_at_edge_index IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON (e.invalid_at)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE RANGE INDEX expired_at_edge_index IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON (e.expired_at)` has no effect.} {description: `RANGE INDEX expired_at_edge_index FOR ()-[e:RELATES_TO]-() ON (e.expired_at)` already exists.} {position: None} for query: 'CREATE INDEX expired_at_edge_index IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON (e.expired_at)'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE FULLTEXT INDEX episode_content IF NOT EXISTS FOR (e:Episodic) ON EACH [e.content, e.source, e.source_description, e.group_id]` has no effect.} {description: `FULLTEXT INDEX episode_content FOR (e:Episodic) ON EACH [e.content, e.source, e.source_description, e.group_id]` already exists.} {position: None} for query: 'CREATE FULLTEXT INDEX episode_content IF NOT EXISTS\n        FOR (e:Episodic) ON EACH [e.content, e.source, e.source_description, e.group_id]'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE FULLTEXT INDEX node_name_and_summary IF NOT EXISTS FOR (e:Entity) ON EACH [e.name, e.summary, e.group_id]` has no effect.} {description: `FULLTEXT INDEX node_name_and_summary FOR (e:Entity) ON EACH [e.name, e.summary, e.group_id]` already exists.} {position: None} for query: 'CREATE FULLTEXT INDEX node_name_and_summary IF NOT EXISTS\n        FOR (n:Entity) ON EACH [n.name, n.summary, n.group_id]'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE FULLTEXT INDEX community_name IF NOT EXISTS FOR (e:Community) ON EACH [e.name, e.group_id]` has no effect.} {description: `FULLTEXT INDEX community_name FOR (e:Community) ON EACH [e.name, e.group_id]` already exists.} {position: None} for query: 'CREATE FULLTEXT INDEX community_name IF NOT EXISTS\n        FOR (n:Community) ON EACH [n.name, n.group_id]'
2025-08-27 10:59:26 - neo4j.notifications - INFO - Received notification from DBMS server: {severity: INFORMATION} {code: Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists} {category: SCHEMA} {title: `CREATE FULLTEXT INDEX edge_name_and_fact IF NOT EXISTS FOR ()-[e:RELATES_TO]-() ON EACH [e.name, e.fact, e.group_id]` has no effect.} {description: `FULLTEXT INDEX edge_name_and_fact FOR ()-[e:RELATES_TO]-() ON EACH [e.name, e.fact, e.group_id]` already exists.} {position: None} for query: 'CREATE FULLTEXT INDEX edge_name_and_fact IF NOT EXISTS\n        FOR ()-[e:RELATES_TO]-() ON EACH [e.name, e.fact, e.group_id]'
2025-08-27 10:59:26 - neo4j.notifications - WARNING - Received notification from DBMS server: {severity: WARNING} {code: Neo.ClientNotification.Statement.UnknownPropertyKeyWarning} {category: UNRECOGNIZED} {title: The provided property key is not in the database} {description: One of the property names in your query is not available in the database, make sure you didn't misspell it or that the label is available when you run this statement in your application (the missing property name is: entity_edges)} {position: line: 17, column: 7, offset: 389} for query: '\n        MATCH (e:Episodic)\n        WHERE e.valid_at <= $reference_time\n        \nAND e.group_id IN $group_ids\nAND e.source = $source\n        RETURN\n        \n    e.content AS content,\n    e.created_at AS created_at,\n    e.valid_at AS valid_at,\n    e.uuid AS uuid,\n    e.name AS name,\n    e.group_id AS group_id,\n    e.source_description AS source_description,\n    e.source AS source,\n    e.entity_edges AS entity_edges\n\n        ORDER BY e.valid_at DESC\n        LIMIT $num_episodes\n        '
2025-08-27 10:59:29 - httpx - INFO - HTTP Request: POST http://xxx.xxx.xxx.xxx:11434/v1/chat/completions "HTTP/1.1 200 OK"
2025-08-27 10:59:29 - graphiti_core.llm_client.openai_generic_client - ERROR - Error in generating LLM response: Expecting ',' delimiter: line 32 column 2 (char 326)
2025-08-27 10:59:29 - graphiti_core.llm_client.openai_generic_client - WARNING - Retrying after application error (attempt 1/2): Expecting ',' delimiter: line 32 column 2 (char 326)
2025-08-27 10:59:31 - httpx - INFO - HTTP Request: POST http://xxx.xxx.xxx.xxx:11434/v1/chat/completions "HTTP/1.1 200 OK"

Connection closed
Traceback (most recent call last):
  File "/home/<user>/devel/src/git/graphiti/main.py", line 134, in <module>
    asyncio.run(main())
  File "/home/<user>/.local/share/uv/python/cpython-3.10.18-linux-x86_64-gnu/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/home/<user>/.local/share/uv/python/cpython-3.10.18-linux-x86_64-gnu/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
    return future.result()
  File "/home/<user>/devel/src/git/graphiti/main.py", line 93, in main
    await graphiti.add_episode(
  File "/home/<user>/devel/src/git/graphiti/.venv/lib/python3.10/site-packages/graphiti_core/graphiti.py", line 573, in add_episode
    raise e
  File "/home/<user>/devel/src/git/graphiti/.venv/lib/python3.10/site-packages/graphiti_core/graphiti.py", line 489, in add_episode
    extracted_nodes = await extract_nodes(
  File "/home/<user>/devel/src/git/graphiti/.venv/lib/python3.10/site-packages/graphiti_core/utils/maintenance/node_operations.py", line 129, in extract_nodes
    response_object = ExtractedEntities(**llm_response)
  File "/home/<user>/devel/src/git/graphiti/.venv/lib/python3.10/site-packages/pydantic/main.py", line 253, in __init__
    validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
pydantic_core._pydantic_core.ValidationError: 1 validation error for ExtractedEntities
extracted_entities
  Field required [type=missing, input_value={'defs': {'ExtractedEntit...ties', 'type': 'array'}}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.11/v/missing

Process finished with exit code 1

Configuration

see minimal code

Additional Context

  • Does this happen consistently or intermittently? consistently
  • Which component are you using? core

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions