graphiti

getzepApache-2.0活跃维护

给 AI Agent 用的实时知识图谱构建框架,把对话和文档里的实体关系抽出来存成图,让 Agent 检索时能拿到带结构的长期记忆。

Build Real-Time Knowledge Graphs for AI Agents

v0.31.2发布于 2026-10-20 17:25 UTC32,708star +79 / 7 天3,359fork同步于 2026-11-10 11:21 UTC

怎么上手

由 README 提炼,执行前请确认
pip install graphiti-core
硬件要求按 README 说明

README 未说明显存或 GPU 要求;需自备图数据库(Neo4j 5.26、FalkorDB 1.1.2、Amazon Neptune 或已弃用的 Kuzu 0.11.2),Python 3.10 以上。

有 Docker 镜像
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

为 AI Agent 构建可追踪事实随时间变化的时间知识图谱框架

给 AI Agent 用的实时知识图谱构建框架,把对话和文档里的实体关系抽出来存成图,让 Agent 检索时能拿到带结构的长期记忆。

核心能力

  • 为每条事实记录生效与失效时间窗口
  • 所有派生事实可溯源到原始 episode
  • 支持语义、关键词与图遍历混合检索
  • 增量更新数据无需重建整张图
  • 用 Pydantic 模型自定义实体与边类型

容易踩的坑

默认使用 OpenAI 做 LLM 推理和嵌入,需先设置 OPENAI_API_KEY;需自行部署并运行图数据库,FalkorDB 可用 docker run -p 6379:6379 -p 3000:3000 -it --rm falkordb/falkordb:latest 启动;SEMAPHORE_LIMIT 默认 10,调高易触发 LLM 429 限流;Kuzu 已弃用,新项目应选 Neo4j 或 FalkorDB。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v0.31.2
  1. v0.31.2v0.31.2 - update certifi to mitigate eMudhra compromise最新正式版2026-10-20 · 2026-10-20 17:25 UTC

    What's Changed

    Full Changelog: https://github.com/getzep/graphiti/compare/v0.31.1...v0.31.2

  2. v0.31.12026-10-15 · 2026-10-15 15:02 UTC
    查看更新说明

    What's Changed

    Full Changelog: https://github.com/getzep/graphiti/compare/v0.31.0...v0.31.1

  3. v0.31.0v0.31.0 - gpt-6-luna as the default OpenAI model2026-10-14 · 2026-10-14 23:58 UTC
    查看更新说明

    What's Changed

    New Contributors

    Full Changelog: https://github.com/getzep/graphiti/compare/v0.30.2...v0.31.0

  4. v0.30.2v0.30.2 - FalkorDB updates2026-09-08 · 2026-09-08 20:38 UTC
    查看更新说明

    What's Changed

    New Contributors

    Full Changelog: https://github.com/getzep/graphiti/compare/v0.30.0...v0.30.2

  5. v0.30.0v0.30.1 - Neo4j Custom Database Fix, Search Fixes and Other Miscellaneous Fixes2026-09-01 · 2026-09-01 18:20 UTC
    查看更新说明

    Fixed: Neo4j queries now respect the configured database Neo4jDriver.execute_query() previously ignored the driver's database setting and ran all queries (including searches) against the server's home database, while session-based writes used the configured one (#1481, #851, #798). Queries are now correctly routed to the configured database, defaulting to neo4j. A per-call override is also supported via execute_query(..., database_="name").

    ⚠️ Behavior change for existing deployments:

    WHO IS AFFECTED: This only impacts self-hosted Neo4j Enterprise deployments (multi-database support is an Enterprise feature) where the database parameter was manually set to something other than neo4j in the Graphiti client, or where the server's default database was renamed. If you run a standard Neo4j setup with the default neo4j database, no action is needed.

    If your server's home database is not named neo4j and you don't pass database to the driver, queries now target neo4j instead of your home database — pass your database name explicitly to keep the old behavior. If you configured a custom database, reads now correctly target it. Data previously written via execute_query may reside in your home database and may need to be migrated.

    What's Changed

    New Contributors

    Full Changelog: https://github.com/getzep/graphiti/compare/v0.29.3...v0.30.0

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Lint Unit Tests MyPy Check

    GitHub Repo stars arXiv Release

    [!NOTE] We're Hiring! Build context graphs that power reliable, personalized, fast production AI agents. Come build with us — we're hiring Engineers and Developer Relations folks. View open roles.

    ⭐ Help us reach more developers and grow the Graphiti community. Star this repo!

     

    Graphiti is a framework for building and querying temporal context graphs for AI agents. Unlike static knowledge graphs, Graphiti's context graphs track how facts change over time, maintain provenance to source data, and support both prescribed and learned ontology — making them purpose-built for agents operating on evolving, real-world data.

    Unlike traditional retrieval-augmented generation (RAG) methods, Graphiti continuously integrates user interactions, structured and unstructured enterprise data, and external information into a coherent, queryable graph. The framework supports incremental data updates, efficient retrieval, and precise historical queries without requiring complete graph recomputation, making it suitable for developing interactive, context-aware AI applications.

    Use Graphiti to:

    • Build temporal knowledge graphs that evolve with every interaction — tracking what's true now and what was true before.
    • Represent rich, structured context instead of flat document chunks or raw event streams.
    • Query across time, meaning, and relationships with hybrid retrieval (semantic + keyword + graph traversal).

     

     

    What is a Context Graph?

    A context graph is a temporal graph of entities, relationships, and facts — like "Kendra loves Adidas shoes (as of March 2026)." Unlike traditional knowledge graphs, each fact in a context graph has a validity window: when it became true, and when (if ever) it was superseded. Entities evolve over time with updated summaries. Everything traces back to episodes — the raw data that produced it.

    What makes Graphiti unique is its ability to autonomously build context graphs from unstructured and structured data, handling changing relationships while preserving full temporal history.

    A context graph contains:

    ComponentWhat it stores
    Entities (nodes)People, products, policies, concepts — with summaries that evolve over time
    Facts / Relationships (edges)Triplets (Entity → Relationship → Entity) with temporal validity windows
    Episodes (provenance)Raw data as ingested — the ground truth stream. Every derived fact traces back here
    Custom Types (ontology)Developer-defined entity and edge types via Pydantic models

    Graphiti and Zep

    Graphiti is an open-source Python framework for building and querying temporal context graphs. You supply the graph database, LLM, and embedder, and you build the service around it: ingestion, tenancy, access control, and operations.

    Zep is the unified context layer for enterprises. Zep brings data from across a business into governed context graphs and serves that context to agents in production. Graphiti is the graph construction framework inside Zep. Konig, Zep's graph database service, stores and serves millions of context graphs with low-latency retrieval.

    Teams use both to give agents memory. Neither is an agent memory product: Graphiti is a framework for building graphs, and Zep unifies, governs, and serves an enterprise's context.

    Read our paper: Zep: A Temporal Knowledge Graph Architecture.

    Zep vs Graphiti

    AspectZepGraphiti
    What it isThe unified context layer for enterprisesAn open-source framework for building temporal context graphs
    ScopeUnifies data from across an enterprise into governed context and serves it to agentsBuilds and queries graphs inside your own application
    Context graphsManages millions of context graphs with governanceBuilds and queries the graphs you define
    Graph databaseKonig, Zep's graph database service, built for millions of context graphs with low-latency retrieval; no third-party graph database requiredBring your own: Neo4j, FalkorDB, or Amazon Neptune
    Users, threads, and ingestionBuilt-in users, threads, and ingestion for messages and business dataBuild your own
    Retrieval & performancePre-configured, production-ready retrieval with sub-200ms performance at scaleCustom implementation required; performance depends on your setup
    Developer toolsDashboard with graph visualization, debug logs, API logs; CLI; SDKs for Python, TypeScript, and GoBuild your own tools
    Enterprise featuresSLAs, support, security guaranteesSelf-managed
    DeploymentFully managed or in your cloud (BYOC)Self-hosted only

    When to choose which

    Choose Zep if you want an enterprise's context unified, governed, and served to agents in production, without building and operating that system yourself.

    Choose Graphiti if you are building temporal context graphs into your own system and will operate the graph database, retrieval, and surrounding service yourself.

    Why Graphiti?

    Traditional RAG approaches often rely on batch processing and static data summarization, making them inefficient for frequently changing data. Graphiti addresses these challenges by providing:

    • Temporal Fact Management: Facts have validity windows. When information changes, old facts are invalidated — not deleted. Query what's true now, or what was true at any point in time.
    • Episodes & Provenance: Every entity and relationship traces back to the episodes (raw data) that produced it. Full lineage from derived fact to source.
    • Prescribed & Learned Ontology: Define entity and edge types upfront via Pydantic models (prescribed), or let structure emerge from your data (learned). Start simple, evolve as patterns appear.
    • Incremental Graph Construction: New data integrates immediately without batch recomputation. The graph evolves in real-time as episodes are ingested.
    • Hybrid Retrieval: Combines semantic embeddings, keyword (BM25), and graph traversal for low-latency, high-precision queries without reliance on LLM summarization.
    • Scalability: Efficiently manages large datasets with parallel processing, pluggable graph backends, suitable for enterprise workloads.

    Graphiti vs. GraphRAG

    AspectGraphRAGGraphiti
    Primary UseStatic document summarizationDynamic, evolving temporal knowledge graphs
    Data HandlingBatch-oriented processingContinuous, incremental updates
    Knowledge StructureEntity clusters & community summariesTemporal context graph — entities, facts with validity windows, episodes, communities
    Retrieval MethodSequential LLM summarizationHybrid semantic, keyword, and graph-based search
    AdaptabilityLowHigh
    Temporal HandlingBasic timestamp trackingExplicit bi-temporal tracking with automatic fact invalidation
    Contradiction HandlingLLM-driven summarization judgmentsAutomatic fact invalidation with temporal history preserved
    Query LatencySeconds to tens of secondsTypically sub-second latency
    Custom Entity TypesNoYes, customizable via Pydantic models
    ScalabilityModerateHigh, optimized for large datasets

    Graphiti is specifically designed to address the challenges of dynamic and frequently updated datasets, making it particularly suitable for applications requiring real-time interaction and precise historical queries.

    Installation

    Requirements:

    • Python 3.10 or higher
    • Neo4j 5.26 / FalkorDB 1.1.2 / Amazon Neptune Database Cluster or Neptune Analytics Graph + Amazon OpenSearch Serverless collection (serves as the full text search backend) / Kuzu 0.11.2 (deprecated, see below)
    • OpenAI API key (Graphiti defaults to OpenAI for LLM inference and embedding)

    [!IMPORTANT] Graphiti works best with LLM services that support Structured Output (such as OpenAI, Anthropic, and Gemini). Using other services may result in incorrect output schemas and ingestion failures. This is particularly problematic when using smaller models.

    Optional:

    • Google Gemini, Anthropic, or Groq API key (for alternative LLM providers)

    [!TIP] The simplest way to install Neo4j is via Neo4j Desktop. It provides a user-friendly interface to manage Neo4j instances and databases. Alternatively, you can use FalkorDB on-premises via Docker and instantly start with the quickstart example:

    docker run -p 6379:6379 -p 3000:3000 -it --rm falkordb/falkordb:latest
    
    pip install graphiti-core
    

    or

    uv add graphiti-core
    

    Installing with FalkorDB Support

    If you plan to use FalkorDB as your graph database backend, install with the FalkorDB extra:

    pip install graphiti-core[falkordb]
    
    # or with uv
    uv add graphiti-core[falkordb]
    
    # or embedded version (requires Python 3.12+)
    pip install graphiti-core[falkordblite]
    # or with uv
    uv add graphiti-core[falkordblite]
    

    Installing with Kuzu Support

    [!WARNING] Kuzu is deprecated and will be removed in a future release — the upstream Kuzu project is no longer maintained. New projects should use Neo4j or FalkorDB. The driver still ships for now but emits a DeprecationWarning.

    If you plan to use Kuzu as your graph database backend, install with the Kuzu extra:

    pip install graphiti-core[kuzu]
    
    # or with uv
    uv add graphiti-core[kuzu]
    

    Installing with Amazon Neptune Support

    If you plan to use Amazon Neptune as your graph database backend, install with the Amazon Neptune extra:

    pip install graphiti-core[neptune]
    
    # or with uv
    uv add graphiti-core[neptune]
    

    You can also install optional LLM providers as extras:

    # Install with Anthropic support
    pip install graphiti-core[anthropic]
    
    # Install with Groq support
    pip install graphiti-core[groq]
    
    # Install with Google Gemini support
    pip install graphiti-core[google-genai]
    
    # Install with multiple providers
    pip install graphiti-core[anthropic,groq,google-genai]
    
    # Install with FalkorDB and LLM providers
    pip install graphiti-core[falkordb,anthropic,google-genai]
    
    # Install with Amazon Neptune
    pip install graphiti-core[neptune]
    

    Default to Low Concurrency; LLM Provider 429 Rate Limit Errors

    Graphiti's ingestion pipelines are designed for high concurrency. By default, concurrency is set low to avoid LLM Provider 429 Rate Limit Errors. If you find Graphiti slow, please increase concurrency as described below.

    Concurrency controlled by the SEMAPHORE_LIMIT environment variable. By default, SEMAPHORE_LIMIT is set to 10 concurrent operations to help prevent 429 rate limit errors from your LLM provider. If you encounter such errors, try lowering this value.

    If your LLM provider allows higher throughput, you can increase SEMAPHORE_LIMIT to boost episode ingestion performance.

    Quick Start

    [!IMPORTANT] Graphiti defaults to using OpenAI for LLM inference and embedding. Ensure that an OPENAI_API_KEY is set in your environment. Support for Anthropic, Gemini, and Groq is available, too. Other LLM providers — both hosted OpenAI-compatible APIs (DeepSeek, Together, OpenRouter, …) and local servers (Ollama, vLLM, llama.cpp, LM Studio) — may be used via their OpenAI-compatible endpoints; see Using Graphiti with OpenAI-compatible providers and local LLMs.

    For a complete working example, see the Quickstart Example in the examples directory. The quickstart demonstrates:

    1. Connecting to a Neo4j, Amazon Neptune, FalkorDB, or Kuzu database
    2. Initializing Graphiti indices and constraints
    3. Adding episodes to the graph (both text and structured JSON)
    4. Searching for relationships (edges) using hybrid search
    5. Reranking search results using graph distance
    6. Searching for nodes using predefined search recipes

    The example is fully documented with clear explanations of each functionality and includes a comprehensive README with setup instructions and next steps.

    Running with Docker Compose

    You can use Docker Compose to quickly start the required services:

    • Neo4j Docker:

      docker compose up
      

      This will start the Neo4j Docker service and related components.

    • FalkorDB Docker:

      docker compose --profile falkordb up
      

      This will start the FalkorDB Docker service and related components.

    Reference MCP and REST servers

    The mcp_server and server directories contain reference implementations of an MCP server and a REST server. These servers show how to put Graphiti behind a protocol. These servers are not production deployments.

    [!WARNING] The reference servers have no authentication, no authorization, and no prompt-injection protection. These omissions are intentional. Do not expose the reference servers to an untrusted network.

    The reference servers have these limits:

    • The servers do not authenticate callers. Any caller can read, change, or delete data in any group_id.
    • The servers do not detect or block prompt injection. The servers send episode content and tool input to the configured LLM without a filter.
    • The example Docker Compose files use default database credentials.

    Security reports about these limits are out of scope. Pull requests that add authentication, authorization, or prompt-injection filters to the reference servers are also out of scope. For more information, see the security policy scope.

    For a production deployment, use one of these options:

    • Use the graphiti-core library in your own service. Your service must supply authentication, authorization, tenant isolation, and input controls.
    • Use Zep, the unified context layer for enterprises, which is built on Graphiti. Zep is available as a managed service or in your own cloud (BYOC). For a comparison, see Zep vs Graphiti.

    MCP Server

    The mcp_server directory contains a reference Model Context Protocol (MCP) server for Graphiti. This server allows AI assistants to interact with Graphiti's context graph capabilities through the MCP protocol.

    Key features of the MCP server include:

    • Episode management (add, retrieve, delete)
    • Entity management and relationship handling
    • Semantic and hybrid search capabilities
    • Group management for organizing related data
    • Graph maintenance operations

    The MCP server can be deployed using Docker with Neo4j, making it easy to integrate Graphiti into your AI assistant workflows.

    For detailed setup instructions and usage examples, see the MCP server README.

    REST Service

    The server directory contains a reference REST service for the Graphiti API. The service uses FastAPI.

    Please see the server README for more information.

    Optional Environment Variables

    In addition to the Neo4j and OpenAi-compatible credentials, Graphiti also has a few optional environment variables. If you are using one of our supported models, such as Anthropic or Voyage models, the necessary environment variables must be set.

    Database Configuration

    Database names are configured directly in the driver constructors:

    • Neo4j: Database name defaults to neo4j (hardcoded in Neo4jDriver)
    • FalkorDB: Database name defaults to default_db (hardcoded in FalkorDriver)

    As of v0.17.0, if you need to customize your database configuration, you can instantiate a database driver and pass it to the Graphiti constructor using the graph_driver parameter.

    Neo4j with Custom Database Name
    from graphiti_core import Graphiti
    from graphiti_core.driver.neo4j_driver import Neo4jDriver
    
    # Create a Neo4j driver with custom database name
    driver = Neo4jDriver(
        uri="bolt://localhost:7687",
        user="neo4j",
        password="password",
        database="my_custom_database"  # Custom database name
    )
    
    # Pass the driver to Graphiti
    graphiti = Graphiti(graph_driver=driver)
    
    FalkorDB with Custom Database Name
    from graphiti_core import Graphiti
    from graphiti_core.driver.falkordb_driver import FalkorDriver
    
    # Create a FalkorDB driver with custom database name
    driver = FalkorDriver(
        host="localhost",
        port=6379,
        username="falkor_user",  # Optional
        password="falkor_password",  # Optional
        database="my_custom_graph"  # Custom database name
    )
    
    # Or use embedded FalkorDB Lite (requires Python 3.12+)
    # from redislite.async_falkordb_client import AsyncFalkorDB
    # falkordb_client = AsyncFalkorDB(dbfilename='/path/to/database.db')
    # driver = FalkorDriver(falkor_db=falkordb_client)
    
    # Pass the driver to Graphiti
    graphiti = Graphiti(graph_driver=driver)
    
    Kuzu

    [!WARNING] Kuzu is deprecated (upstream project unmaintained) and will be removed in a future release. Prefer Neo4j or FalkorDB.

    from graphiti_core import Graphiti
    from graphiti_core.driver.kuzu_driver import KuzuDriver
    
    # Create a Kuzu driver
    driver = KuzuDriver(db="/tmp/graphiti.kuzu")
    
    # Pass the driver to Graphiti
    graphiti = Graphiti(graph_driver=driver)
    
    Amazon Neptune
    from graphiti_core import Graphiti
    from graphiti_core.driver.neptune_driver import NeptuneDriver
    
    # Create a Neptune driver
    driver = NeptuneDriver(
        host='<NEPTUNE_ENDPOINT>',
        aoss_host='<AMAZON_OPENSEARCH_SERVERLESS_HOST>',
        port=8182,      # Optional, defaults to 8182
        aoss_port=443,  # Optional, defaults to 443
    )
    
    # Pass the driver to Graphiti
    graphiti = Graphiti(graph_driver=driver)
    

    Contributing a new graph backend? See Adding a graph driver.

    Using Graphiti with Azure OpenAI

    Graphiti supports Azure OpenAI for both LLM inference and embeddings using Azure's OpenAI v1 API compatibility layer.

    Quick Start

    from openai import AsyncOpenAI
    from graphiti_core import Graphiti
    from graphiti_core.llm_client.azure_openai_client import AzureOpenAILLMClient
    from graphiti_core.llm_client.config import LLMConfig
    from graphiti_core.embedder.azure_openai import AzureOpenAIEmbedderClient
    
    # Initialize Azure OpenAI client using the standard OpenAI client
    # with Azure's v1 API endpoint
    azure_client = AsyncOpenAI(
        base_url="https://your-resource-name.openai.azure.com/openai/v1/",
        api_key="your-api-key",
    )
    
    # Create LLM and Embedder clients
    llm_client = AzureOpenAILLMClient(
        azure_client=azure_client,
        config=LLMConfig(model="gpt-5-mini", small_model="gpt-5-mini")  # Your Azure deployment name
    )
    embedder_client = AzureOpenAIEmbedderClient(
        azure_client=azure_client,
        model="text-embedding-3-small"  # Your Azure embedding deployment name
    )
    
    # Initialize Graphiti with Azure OpenAI clients
    graphiti = Graphiti(
        "bolt://localhost:7687",
        "neo4j",
        "password",
        llm_client=llm_client,
        embedder=embedder_client,
    )
    
    # Now you can use Graphiti with Azure OpenAI
    

    Key Points:

    • Use the standard AsyncOpenAI client with Azure's v1 API endpoint format: https://your-resource-name.openai.azure.com/openai/v1/
    • The deployment names (e.g., gpt-5-mini, text-embedding-3-small) should match your Azure OpenAI deployment names
    • See examples/azure-openai/ for a complete working example

    Make sure to replace the placeholder values with your actual Azure OpenAI credentials and deployment names.

    Using Graphiti with Google Gemini

    Graphiti supports Google's Gemini models for LLM inference, embeddings, and cross-encoding/reranking. To use Gemini, you'll need to configure the LLM client, embedder, and the cross-encoder with your Google API key.

    Install Graphiti:

    uv add "graphiti-core[google-genai]"
    
    # or
    
    pip install "graphiti-core[google-genai]"
    
    from graphiti_core import Graphiti
    from graphiti_core.llm_client.gemini_client import GeminiClient, LLMConfig
    from graphiti_core.embedder.gemini import GeminiEmbedder, GeminiEmbedderConfig
    from graphiti_core.cross_encoder.gemini_reranker_client import GeminiRerankerClient
    
    # Google API key configuration
    api_key = "<your-google-api-key>"
    
    # Initialize Graphiti with Gemini clients
    graphiti = Graphiti(
        "bolt://localhost:7687",
        "neo4j",
        "password",
        llm_client=GeminiClient(
            config=LLMConfig(
                api_key=api_key,
                model="gemini-2.0-flash"
            )
        ),
        embedder=GeminiEmbedder(
            config=GeminiEmbedderConfig(
                api_key=api_key,
                embedding_model="embedding-001"
            )
        ),
        cross_encoder=GeminiRerankerClient(
            config=LLMConfig(
                api_key=api_key,
                model="gemini-2.5-flash-lite"
            )
        )
    )
    
    # Now you can use Graphiti with Google Gemini for all components
    

    The Gemini reranker uses the gemini-2.5-flash-lite model by default, which is optimized for cost-effective and low-latency classification tasks. It uses the same boolean classification approach as the OpenAI reranker, leveraging Gemini's log probabilities feature to rank passage relevance.

    Using Graphiti with OpenAI-compatible providers and local LLMs

    Graphiti can use any OpenAI-compatible /v1 endpoint for LLM inference via OpenAIGenericClient — both hosted providers (DeepSeek, Together, OpenRouter, Fireworks, etc.) and local servers (Ollama, vLLM, llama.cpp, LM Studio). Local servers are ideal for privacy-focused applications or avoiding API costs. The example below uses Ollama; for any other provider, point base_url at its endpoint and set the appropriate api_key and model.

    Note: Use OpenAIGenericClient (not OpenAIClient) for these endpoints. It is optimized for local models with a higher default max token limit (16K vs 8K) and handles structured outputs across compatible providers.

    Install the models:

    ollama pull deepseek-r1:7b # LLM
    ollama pull nomic-embed-text # embeddings
    
    from graphiti_core import Graphiti
    from graphiti_core.llm_client.config import LLMConfig
    from graphiti_core.llm_client.openai_generic_client import OpenAIGenericClient
    from graphiti_core.embedder.openai import OpenAIEmbedder, OpenAIEmbedderConfig
    from graphiti_core.cross_encoder.openai_reranker_client import OpenAIRerankerClient
    
    # Configure Ollama LLM client
    llm_config = LLMConfig(
        api_key="ollama",  # Ollama doesn't require a real API key, but some placeholder is needed
        model="deepseek-r1:7b",
        small_model="deepseek-r1:7b",
        base_url="http://localhost:11434/v1",  # Ollama's OpenAI-compatible endpoint
    )
    
    llm_client = OpenAIGenericClient(config=llm_config)
    
    # Initialize Graphiti with Ollama clients
    graphiti = Graphiti(
        "bolt://localhost:7687",
        "neo4j",
        "password",
        llm_client=llm_client,
        embedder=OpenAIEmbedder(
            config=OpenAIEmbedderConfig(
                api_key="ollama",  # Placeholder API key
                embedding_model="nomic-embed-text",
                embedding_dim=768,
                base_url="http://localhost:11434/v1",
            )
        ),
        cross_encoder=OpenAIRerankerClient(client=llm_client, config=llm_config),
    )
    
    # Now you can use Graphiti with local Ollama models
    

    Ensure Ollama is running (ollama serve) and that you have pulled the models you want to use.

    Structured output and small models

    Graphiti depends on structured (JSON) output for entity/edge extraction and deduplication, and works best with models and providers that reliably honor it (OpenAI, Anthropic, Gemini). Reliability varies across OpenAI-compatible providers and especially on smaller or local models, so OpenAIGenericClient exposes a structured_output_mode:

    • "json_schema" (default): requests native structured output via response_format. Best on capable models and providers that enforce the schema via constrained decoding.
    • "json_object": requests plain-JSON mode and injects the schema into the prompt instead. Use this for providers/models that don't reliably honor json_schema — including some local servers that accept the json_schema request but don't actually constrain output to it, where json_object can be more reliable.

    When using smaller or local models:

    • Prefer the most capable model you can run. Very small models frequently emit JSON that doesn't match the requested schema, which surfaces as extraction failures.
    • Responses wrapped in Markdown ```json code fences are stripped automatically.
    • Keep SEMAPHORE_LIMIT low (see above) — local servers and some providers have limited concurrency.

    Configurable Prompts

    Graphiti lets you override LLM prompt builders per client instance. Override callables must return ChatPrompt (system + user). Response schemas are fixed and not overridable:

    from graphiti_core import Graphiti
    from graphiti_core.prompts import ChatPrompt, SystemMessage, UserMessage, create_prompt_library
    
    def custom_extract_message(context: dict) -> ChatPrompt:
        return ChatPrompt(
            system=SystemMessage(content='Extract entities for my domain.'),
            user=UserMessage(content=str(context.get('episode_content', ''))),
        )
    
    prompt_library = create_prompt_library({
        'extract_nodes': {
            'extract_message': custom_extract_message,
        },
    })
    
    graphiti = Graphiti(..., prompt_library=prompt_library)
    

    Unspecified prompts keep the built-in defaults. Returning list[Message] from an override raises TypeError — migrate with return ChatPrompt(system=..., user=...). Unicode handling is applied via ChatPrompt.as_messages().

    The package-level prompt_library keeps the existing list[Message] API. The opt-in prompt customization API uses ChatPromptLibrary and DefaultChatPromptLibrary.

    For per-prompt routing across providers, pass an opt-in llm_runtime. Create one LLMTransport for each provider client. Each LLMModel binds a provider model ID to one transport. An unrouted prompt uses the default model. llm_runtime cannot be combined with llm_client or prompt_library. Response schemas stay fixed. You can configure prompt text and model routes:

    from typing import Literal
    
    from graphiti_core import Graphiti
    from graphiti_core.llm_client.anthropic_client import AnthropicClient
    from graphiti_core.llm_client import (
        LLMRuntime,
        LLMTransport,
        OpenAIClient,
        PromptRoutes,
    )
    
    OpenAIModels = Literal['gpt-5.1', 'gpt-5-nano']
    openai = LLMTransport[OpenAIModels](
        OpenAIClient(),
        models=['gpt-5.1', 'gpt-5-nano'],
    )
    
    AnthropicModels = Literal['claude-sonnet-5', 'claude-haiku-5-5']
    anthropic = LLMTransport[AnthropicModels](
        AnthropicClient(),
        models=['claude-sonnet-5', 'claude-haiku-5-5'],
    )
    
    main = openai.model('gpt-5.1')
    nano = openai.model('gpt-5-nano')
    haiku = anthropic.model('claude-haiku-5-5')
    runtime = LLMRuntime(
        model=main,
        routes=PromptRoutes(
            extract_nodes=PromptRoutes.ExtractNodes(extract_attributes=nano),
            dedupe_edges=PromptRoutes.DedupeEdges(
                resolve_edge=haiku,
            ),
        ),
    )
    
    graphiti = Graphiti(..., llm_runtime=runtime)
    

    LLMModel does not have a small_id field. The runtime passes model_size for legacy compatibility, but this value does not select a smaller model. The selected model ID controls provider calls. A routed prompt uses that model ID. An unrouted prompt uses the default model ID. Route prompts that need a smaller model to that model explicitly. Legacy calls without llm_runtime retain LLMConfig.small_model behavior.

    GLiNER2 binds model objects at initialization. It does not support per-prompt model routing. See spec/llm-runtime.md for the runtime API.

    Jev dedupe

    JevClient routes node dedupe and edge resolution to TypeSafe Jev. Set JEV_API_KEY before you create the client. The duplicate threshold defaults to 0.7. The contradiction threshold defaults to 0.8.

    Jev is a decision model. It answers typed questions with probabilities. It does not generate text. Use a general LLM as the default model. Route only dedupe_nodes.nodes and dedupe_edges.resolve_edge to Jev. Do not use Jev for extraction, summaries, or other generation tasks.

    TypeSafe hosts the Jev API. Graphiti sends dedupe prompt content to TypeSafe. See the FalkorDB Jev dedupe example for a runnable example.

    from graphiti_core import Graphiti
    from graphiti_core.llm_client import (
        JevClient,
        LLMRuntime,
        LLMTransport,
        OpenAIClient,
        PromptRoutes,
        jev_prompt_overrides,
    )
    
    openai = LLMTransport(OpenAIClient(), models=['gpt-6-luna'])
    jev = LLMTransport(JevClient(), models=['jev-latest'])
    jev_dedupe = jev.model('jev-latest', prompt_overrides=jev_prompt_overrides())
    
    runtime = LLMRuntime(
        model=openai.model('gpt-6-luna'),
        routes=PromptRoutes(
            dedupe_nodes=PromptRoutes.DedupeNodes(nodes=jev_dedupe),
            dedupe_edges=PromptRoutes.DedupeEdges(resolve_edge=jev_dedupe),
        ),
    )
    graphiti = Graphiti(..., llm_runtime=runtime)
    

    OpenAI Decisions dedupe

    OpenAIDecisionsClient routes node dedupe and edge resolution to the OpenAI Decisions API. Use a general LLM as the default model. A decision model answers typed questions with probabilities and does not generate text. Do not use it for extraction, summaries, or other generation tasks.

    See the OpenAI Decisions FalkorDB example for a runnable example.

    Documentation

    Telemetry

    Graphiti collects anonymous usage statistics to help us understand how the framework is being used and improve it for everyone. We believe transparency is important, so here's exactly what we collect and why.

    What We Collect

    When you initialize a Graphiti instance, we collect:

    • Anonymous identifier: A randomly generated UUID stored locally in ~/.cache/graphiti/telemetry_anon_id
    • System information: Operating system, Python version, and system architecture
    • Graphiti version: The version you're using
    • Configuration choices:
      • LLM provider type (OpenAI, Azure, Anthropic, etc.)
      • Database backend (Neo4j, FalkorDB, Kuzu, Amazon Neptune Database or Neptune Analytics)
      • Embedder provider (OpenAI, Azure, Voyage, etc.)

    What We Don't Collect

    We are committed to protecting your privacy. We never collect:

    • Personal information or identifiers
    • API keys or credentials
    • Your actual data, queries, or graph content
    • IP addresses or hostnames
    • File paths or system-specific information
    • Any content from your episodes, nodes, or edges

    Why We Collect This Data

    This information helps us:

    • Understand which configurations are most popular to prioritize support and testing
    • Identify which LLM and database providers to focus development efforts on
    • Track adoption patterns to guide our roadmap
    • Ensure compatibility across different Python versions and operating systems

    By sharing this anonymous information, you help us make Graphiti better for everyone in the community.

    View the Telemetry Code

    The Telemetry code may be found here.

    How to Disable Telemetry

    Telemetry is opt-out and can be disabled at any time. To disable telemetry collection:

    Option 1: Environment Variable

    export GRAPHITI_TELEMETRY_ENABLED=false
    

    Option 2: Set in your shell profile

    # For bash users (~/.bashrc or ~/.bash_profile)
    echo 'export GRAPHITI_TELEMETRY_ENABLED=false' >> ~/.bashrc
    
    # For zsh users (~/.zshrc)
    echo 'export GRAPHITI_TELEMETRY_ENABLED=false' >> ~/.zshrc
    

    Option 3: Set for a specific Python session

    import os
    
    os.environ['GRAPHITI_TELEMETRY_ENABLED'] = 'false'
    
    # Then initialize Graphiti as usual
    from graphiti_core import Graphiti
    
    graphiti = Graphiti(...)
    

    Telemetry is automatically disabled during test runs (when pytest is detected).

    Technical Details

    • Telemetry uses PostHog for anonymous analytics collection
    • All telemetry operations are designed to fail silently - they will never interrupt your application or affect Graphiti functionality
    • The anonymous ID is stored locally and is not tied to any personal information

    Contributing

    We encourage and appreciate all forms of contributions, whether it's code, documentation, addressing GitHub Issues, or helping others on GitHub. For detailed guidelines on code contributions, please refer to CONTRIBUTING.

    Support

    Open a GitHub issue to ask questions, report bugs, or discuss Graphiti.