$npx -y skills add neo4j-contrib/neo4j-skills --skill neo4j-genai-plugin-skillUse Neo4j GenAI Plugin ai.text.* functions and procedures for in-Cypher
| 1 | ## When to Use |
| 2 | - Generating embeddings inside Cypher without external Python (`ai.text.embed()`) |
| 3 | - Batch-embedding nodes/chunks during ingestion (`ai.text.embedBatch()`) |
| 4 | - Calling LLMs directly in Cypher for completions or GraphRAG (`ai.text.completion()`) |
| 5 | - Extracting structured JSON maps from LLM inside Cypher (`ai.text.structuredCompletion()`) |
| 6 | - Aggregating LLM summaries over grouped rows (`ai.text.aggregateCompletion()`) |
| 7 | - Stateful chat sessions in Cypher (`ai.text.chat()`) |
| 8 | - Counting tokens or chunking text by token limit (`ai.text.tokenCount()`, `ai.text.chunkByTokenLimit()`) |
| 9 | |
| 10 | ## When NOT to Use |
| 11 | - **Python-based GraphRAG pipelines** (VectorCypherRetriever, HybridCypherRetriever) → `neo4j-graphrag-skill` |
| 12 | - **Vector index CREATE / kNN search / SEARCH clause** → `neo4j-vector-index-skill` |
| 13 | - **GDS embeddings** (FastRP, Node2Vec) → `neo4j-gds-skill` |
| 14 | - **Fulltext / keyword search** → `neo4j-cypher-skill` |
| 15 | |
| 16 | --- |
| 17 | |
| 18 | ## Prerequisites |
| 19 | |
| 20 | **CYPHER 25 required** for all `ai.*` functions. Two ways to enable: |
| 21 | |
| 22 | ```cypher |
| 23 | // Per-query prefix (self-managed, no admin rights needed): |
| 24 | CYPHER 25 MATCH (n:Chunk) ... |
| 25 | |
| 26 | // Per-database default (admin; applies to all sessions): |
| 27 | ALTER DATABASE neo4j SET DEFAULT LANGUAGE CYPHER 25 |
| 28 | ``` |
| 29 | |
| 30 | **Installation:** |
| 31 | - **Aura**: GenAI plugin enabled by default — no action needed |
| 32 | - **Self-managed JAR**: copy plugin JAR to `plugins/` directory |
| 33 | - **Docker**: `--env NEO4J_PLUGINS='["genai"]'` |
| 34 | |
| 35 | --- |
| 36 | |
| 37 | ## Provider Config Quick Reference |
| 38 | |
| 39 | All `ai.text.*` functions accept a `configuration :: MAP` as last argument. |
| 40 | |
| 41 | | Provider string | Required keys | Notes | |
| 42 | |---|---|---| |
| 43 | | `'openai'` | `token`, `model` | `token` = OpenAI API key | |
| 44 | | `'azure-openai'` | `token`, `resource`, `model` | `token` = OAuth2 bearer; `resource` = Azure resource name | |
| 45 | | `'vertexai'` | `model`, `project`, `region`, `token` or `apiKey` | `publisher` defaults to `'google'` | |
| 46 | | `'bedrock-titan'` | `model`, `region`, `accessKeyId`, `secretAccessKey` | Embedding only | |
| 47 | | `'bedrock-nova'` | `model`, `region`, `accessKeyId`, `secretAccessKey` | Completion only | |
| 48 | |
| 49 | Optional for all: `vendorOptions :: MAP` passes provider-specific extras (e.g. `{ dimensions: 1024 }` for OpenAI). |
| 50 | |
| 51 | ❌ Never hardcode API key literals. ✅ Always use `$param` passed via driver parameters dict. |
| 52 | |
| 53 | Full provider config table → [references/providers.md](references/providers.md) |
| 54 | |
| 55 | --- |
| 56 | |
| 57 | ## Embedding |
| 58 | |
| 59 | ### Single embed [2025.11] |
| 60 | |
| 61 | ```cypher |
| 62 | CYPHER 25 |
| 63 | MATCH (c:Chunk) |
| 64 | WHERE c.embedding IS NULL |
| 65 | WITH c |
| 66 | CALL { |
| 67 | WITH c |
| 68 | SET c.embedding = ai.text.embed(c.text, 'openai', { |
| 69 | token: $openaiKey, |
| 70 | model: 'text-embedding-3-small' |
| 71 | }) |
| 72 | } IN TRANSACTIONS OF 500 ROWS |
| 73 | ``` |
| 74 | |
| 75 | `ai.text.embed()` returns `VECTOR` — directly storable and queryable in a vector index. |
| 76 | |
| 77 | ### Batch embed procedure [2025.11] |
| 78 | |
| 79 | ```cypher |
| 80 | CYPHER 25 |
| 81 | MATCH (c:Chunk) WHERE c.embedding IS NULL |
| 82 | WITH collect(c) AS chunks |
| 83 | UNWIND chunks AS c |
| 84 | WITH c.text AS text, c AS node |
| 85 | CALL ai.text.embedBatch(text, 'openai', { token: $openaiKey, model: 'text-embedding-3-small' }) |
| 86 | YIELD index, resource, vector |
| 87 | MATCH (c:Chunk {text: resource}) |
| 88 | SET c.embedding = vector |
| 89 | ``` |
| 90 | |
| 91 | Procedure signature: `CALL ai.text.embedBatch(resource, provider, config) YIELD index, resource, vector` |
| 92 | |
| 93 | ### List configured embed providers |
| 94 | |
| 95 | ```cypher |
| 96 | CYPHER 25 |
| 97 | CALL ai.text.embed.providers() |
| 98 | YIELD name, requiredConfigType, optionalConfigType, defaultConfig |
| 99 | RETURN name, requiredConfigType |
| 100 | ``` |
| 101 | |
| 102 | --- |
| 103 | |
| 104 | ## Text Completion [2025.11] |
| 105 | |
| 106 | ```cypher |
| 107 | CYPHER 25 |
| 108 | RETURN ai.text.completion( |
| 109 | 'Summarize: ' + $text, |
| 110 | 'openai', |
| 111 | { token: $openaiKey, model: 'gpt-4o-mini' } |
| 112 | ) AS summary |
| 113 | ``` |
| 114 | |
| 115 | Returns `STRING`. |
| 116 | |
| 117 | ### Aggregate completion — summarize across rows [2026.03] |
| 118 | |
| 119 | ```cypher |
| 120 | CYPHER 25 |
| 121 | MATCH (c:Chunk)-[:PART_OF]->(a:Article {id: $articleId}) |
| 122 | RETURN ai.text.aggregateCompletion( |
| 123 | c.text, |
| 124 | 'Summarize the following article chunks in 3 sentences', |
| 125 | 'openai', |
| 126 | { token: $openaiKey, model: 'gpt-4o-mini' } |
| 127 | ) AS summary |
| 128 | ``` |
| 129 | |
| 130 | `value` parameter = each row's STRING fed to the LLM. Uses `toString()` for non-string values. |
| 131 | |
| 132 | --- |
| 133 | |
| 134 | ## Pure-Cypher GraphRAG Pattern |
| 135 | |
| 136 | Embe |