llm-graph-builder: Turning PDFs and YouTube Links into a Neo4j Knowledge Graph
Neo4j graph construction from unstructured data using LLMs
At a glance
- What is it?
- Neo4j Labs ships a FastAPI and React application that pipes unstructured files through an LLM and writes the extracted entities into Neo4j. It is a working pipeline with a hard Neo4j 5.23 floor and a deployment story that splits cleanly in two.
- Who is it for?
- Adopt it if your source material is already sitting in S3, GCS, a local folder or YouTube and you want it inside a Neo4j 5.23 instance without writing the extraction chain yourself. Do not adopt it if you are on Neo4j Desktop with docker-compose, or if you need a fixed, auditable extraction schema, because the LLM decides the node and relationship shape.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly Jupyter Notebook, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap llm-graph-builder fills between a document folder and a property graph
Most teams that want a knowledge graph start with a pile of PDFs, a few web pages and a YouTube link, and no Cypher. Writing the extraction layer by hand means choosing a chunking strategy, prompting a model for entities and relationships, deduplicating what comes back, and then generating MERGE statements that do not explode the node count. llm-graph-builder packages that chain. The README describes the goal plainly: transform unstructured data such as PDFs, DOCs, TXTs, YouTube videos and web pages into a structured Knowledge Graph stored in Neo4j, using LLMs and LangChain. The audience is engineers who already have a Neo4j instance and want the ingestion path, not a research framework. Input sources are enumerated in the deployment section: local, YouTube, Wikipedia, AWS S3 and web by default, with Google Cloud Storage added by putting gcs into VITE_REACT_APP_SOURCES alongside a Google client ID. That list is the real scope statement. If your documents live somewhere not on it, you are writing an adapter.
What actually happens between upload and a written graph
The architecture is a two-process application. A FastAPI backend, started with uvicorn score:app, owns the LLM calls and the Neo4j writes. A React frontend, started with yarn run dev, owns source selection, model selection and chat. The backend reads Neo4j connection details from a .env file copied from backend/example.env, with NEO4J_URI, NEO4J_USERNAME, NEO4J_PASSWORD and NEO4J_DATABASE as the four keys that matter. Setting those four bypasses the login dialog, which tells you the normal path is a user typing credentials into the UI and the environment file is the automation escape hatch. Extraction is schema-aware rather than freeform: the README lists schema support as a feature, letting you use a custom schema or existing schemas configured in settings to generate graphs. That is the lever that separates a usable graph from a heap of loosely typed nodes, and it is also the part the README describes least. Visualization is delegated to Neo4j Bloom rather than built in. Chat runs against the populated database with metadata about the source of each response, and a standalone chat interface is available at the /chat-only route. Chat modes are configurable through VITE_CHAT_MODES, with vector, graph_vector, graph, fulltext, graph_vector_fulltext, entity_vector and global_vector all enabled by default.
The Neo4j 5.23 floor and the APOC dependency are not negotiable
The prerequisites section states Neo4j Database 5.23 or later with APOC installed. The reason is given and it is specific: the backend uses the Cypher variable-scope subquery syntax, CALL (variable) { ... }, which earlier 5.x releases such as 5.20 do not support. This is the kind of constraint that costs an afternoon if you skim it, because 5.20 is a recent release and the failure will surface as a Cypher parse error rather than a version warning. Neo4j Aura is supported, including the free tier, which is the lowest-friction way to satisfy the version requirement. APOC is a separate install and the README does not walk through it, so budget time for that on a self-managed instance. Python 3.12 or higher is required for a local or separate backend deployment, and the setup commands pin it explicitly with python3.12 -m venv venv. The full backend sequence is cd backend, create the venv, activate it, pip install -r requirements.txt, then uvicorn score:app --reload. The frontend sequence is cd frontend, yarn, yarn run dev, after copying frontend/example.env.
Embedding model selection flips on a single environment flag
This is the most consequential configuration decision in the project and it is easy to miss because it sits under a feature heading rather than a setup heading. With TRACK_USER_USAGE set to true, you also supply token tracking database credentials such as TOKEN_TRACKER_DB_URI and TOKEN_TRACKER_DB_USERNAME, and the embedding model is picked in the frontend under Graph Settings, Processing Configuration, Select Embedding Model. The choice is saved to the user profile and reused in later sessions. With TRACK_USER_USAGE set to false, the frontend selector is disabled and you set EMBEDDING_MODEL and EMBEDDING_PROVIDER in the backend .env file instead. If neither variable is set, the application defaults to a Sentence Transformer model. So the tracking flag does two unrelated jobs: it turns on per-user token accounting and it decides where the embedding model is configured. Supported embedding providers are OpenAI, Gemini, Amazon Titan and Sentence Transformers. Note the asymmetry: embedding models are chosen from a fixed provider list, while LLM support is wider and unevenly mature. OpenAI, Gemini and Diffbot are the primary list. Azure OpenAI, Anthropic, Fireworks, Groq, Amazon Bedrock, Ollama, Deepseek and other OpenAI-compatible base URL models are all marked as dev deployed version, which the README does not define further.
Where the deployment story breaks down
Two constraints deserve to be read before you plan anything. First, if you are using Neo4j Desktop you must deploy the backend and frontend separately, because docker-compose is not supported in that configuration. The compose path and the Desktop path are mutually exclusive, so a team standardised on Desktop loses the one-command setup. Second, the default docker-compose configuration enables only OpenAI and Diffbot. Gemini needs additional GCP configuration, and the mechanism for enabling other models is the VITE_LLM_MODELS_PROD variable, with the README showing a comma-separated example that mixes gemini_3.5_flash, openai_gpt_5.4_mini, diffbot and anthropic_claude_4.5_haiku. Anthropic models are configured through a separate key pattern, LLM_MODEL_CONFIG_ANTHROPIC_CLAUDE_4_7_OPUS, whose value pairs a model name with an API key reference. That naming convention implies one environment variable per model, which does not scale gracefully past a handful of models. The deeper limitation is structural. An LLM decides which nodes and relationships exist, so two runs over the same corpus with different models or prompts can produce different graphs. The custom schema feature is the mitigation, but the README does not document how strictly a schema constrains extraction. If you need a fixed, auditable output shape, verify that behaviour against your own documents before you build on it.
How it differs from an LLM framework you wire up yourself
LangChain is the obvious comparison point, and the project already depends on it. The difference is what each one hands you. LangChain gives you LLMChain, document loaders and a Neo4jGraph wrapper, and leaves the pipeline to you: you decide chunk size, write the extraction prompt, define the node and relationship types, handle duplicates across chunks, and write the Cypher. llm-graph-builder is that pipeline as an application, with a React UI for source selection and a FastAPI backend that owns the write path. The trade is control for speed. You cannot easily swap the chunking strategy or the extraction prompt, because those are not exposed as configuration in the material available. You get schema configuration, model selection, chat modes and input sources as the tuning surface. The other meaningful difference is operational: llm-graph-builder is a service you run with uvicorn and reach through a browser, not a library you import into an existing job. For a one-off batch conversion inside an existing data pipeline, a library is the better shape. For a team that wants a shared interface where analysts upload documents and query the resulting graph, the application shape is the point.
Licence, release cadence and what upgrades cost you
The repository is Apache-2.0, which permits commercial use and modification, and it includes a patent grant. That is a permissive licence, and it does not impose copyleft obligations on your own code. It also means no warranty and no support commitment from the maintainers, and Neo4j Labs projects are not the same thing as Neo4j's supported commercial products. This is not legal advice; check the licence text and your own counsel if the distinction matters to you. On cadence, the recent releases are v0.8.5 in February 2026, v0.8.6 in June 2026 and v0.8.7 in July 2026, with the last push to main in September 2026. The version numbers are still in the 0.8 range, which is a reasonable signal that interfaces and environment variable names can move between minor releases. The upgrade cost concentrates in two places: the frontend environment variables (VITE_LLM_MODELS_PROD, VITE_REACT_APP_SOURCES, VITE_CHAT_MODES) and the per-model backend keys. If you have hardcoded those into a deployment manifest, a minor bump can require editing them. The Neo4j 5.23 floor is the other cost that does not go away, since it is tied to Cypher syntax the backend emits rather than to a dependency you can pin down.
Editorial conclusion
Adopt it if your source material is already sitting in S3, GCS, a local folder or YouTube and you want it inside a Neo4j 5.23 instance without writing the extraction chain yourself. Do not adopt it if you are on Neo4j Desktop with docker-compose, or if you need a fixed, auditable extraction schema, because the LLM decides the node and relationship shape. Before committing, confirm your Neo4j version reports 5.23 or later and that APOC is installed, then decide whether TRACK_USER_USAGE is true or false, because that single flag determines whether the embedding model is chosen in the frontend or pinned in the backend .env file.
Community notes