@falkordb/text-to-cypher
v0.2.0
Published
Node.js bindings for FalkorDB text-to-cypher library - Convert natural language to Cypher queries
Maintainers
Readme
@falkordb/text-to-cypher
Node.js bindings for the FalkorDB text-to-cypher library - Convert natural language to Cypher queries using AI.
Features
- 🤖 AI-Powered: Convert natural language questions to Cypher queries using GPT-4, Claude, Gemini, and other AI models
- 🔍 Schema Discovery: Automatically discovers and analyzes graph database schemas
- ✅ Query Validation: Built-in validation to catch syntax errors before execution
- 🚀 High Performance: Native Rust implementation with Node.js bindings via NAPI-RS
- 🌍 Cross-Platform: Pre-built binaries for Linux, macOS, and Windows
- 📦 Zero Dependencies: No runtime dependencies required
Installation
npm install @falkordb/text-to-cypher📚 New to this library? Check out the Quick Start Guide for a 5-minute introduction!
Quick Start
const { TextToCypher } = require('@falkordb/text-to-cypher');
// Create a client
const client = new TextToCypher({
model: 'gpt-4o-mini',
apiKey: process.env.OPENAI_API_KEY,
falkordbConnection: 'falkor://localhost:6379'
});
// Convert text to Cypher and execute
async function main() {
const response = await client.textToCypher(
'movies',
'Find all actors who appeared in movies released after 2020'
);
console.log('Generated Query:', response.cypherQuery);
console.log('Result:', response.cypherResult);
console.log('Answer:', response.answer);
}
main().catch(console.error);API Reference
new TextToCypher(options)
Creates a new text-to-cypher client.
Parameters:
options.model(string): AI model to use (e.g.,'gpt-4o-mini','openai:local-model','anthropic:claude-3','gemini:gemini-2.0-flash-exp')options.apiKey(string): API key for the AI serviceoptions.falkordbConnection(string): FalkorDB connection string (e.g.,'falkor://localhost:6379')options.llmEndpoint(string, optional): Custom LLM provider endpoint/base URL for OpenAI-compatible local providers such as LM Studio (e.g.,'http://localhost:1234/v1')options.discoverUdfs(boolean, optional): Whentrue, discover the connected instance's user-defined functions (UDFs) viaGRAPH.UDF LISTand surface theirlibrary.functioncall targets to the model. Off by default. Client-level — applies totextToCypher,textToCypherWithMessages, andcypherOnly. Ignored whenudfsis provided.options.udfs(UdfLibraryInput[], optional): A caller-supplied UDF catalog to surface to the model. Takes precedence overdiscoverUdfs— use it when you already have the UDF list (e.g. fromGRAPH.UDF LIST) to avoid an extra discovery round-trip.
Example:
const client = new TextToCypher({
model: 'gpt-4o-mini',
apiKey: 'sk-...',
falkordbConnection: 'falkor://localhost:6379'
});For LM Studio or another OpenAI-compatible local server, pass the local endpoint:
const client = new TextToCypher({
model: 'openai::google/gemma-4-e4b',
apiKey: 'lm-studio',
falkordbConnection: 'falkor://localhost:6379',
llmEndpoint: 'http://localhost:1234/v1'
});To let generated Cypher call your instance's UDFs, either discover them automatically or pass a catalog you already have:
// Auto-discover (one GRAPH.UDF LIST during generation)
const client = new TextToCypher({
model: 'gpt-4o-mini',
apiKey: 'sk-...',
falkordbConnection: 'falkor://localhost:6379',
discoverUdfs: true
});
// Or supply a catalog you already fetched (no extra round-trip)
const client = new TextToCypher({
model: 'gpt-4o-mini',
apiKey: 'sk-...',
falkordbConnection: 'falkor://localhost:6379',
udfs: [{ name: 'geo', functions: [{ name: 'distance' }, { name: 'within' }] }]
});textToCypher(graphName, question)
Converts natural language to Cypher, executes the query, and generates a natural language answer.
Parameters:
graphName(string): Name of the graph to queryquestion(string): Natural language question
Returns: Promise<TextToCypherResponse>
Example:
const response = await client.textToCypher('movies', 'Who directed The Matrix?');
console.log(response.answer); // "The Matrix was directed by..."textToCypherWithMessages(graphName, messages)
Same as textToCypher but accepts multiple messages for conversation context.
Parameters:
graphName(string): Name of the graph to querymessages(Array): Array of conversation messages
Example:
const response = await client.textToCypherWithMessages('movies', [
{ role: 'user', content: 'Show me actors' },
{ role: 'assistant', content: 'Here are some actors...' },
{ role: 'user', content: 'Filter those who acted after 2020' }
]);cypherOnly(graphName, question)
Generates a Cypher query without executing it.
Parameters:
graphName(string): Name of the graphquestion(string): Natural language question
Returns: Promise<TextToCypherResponse> (with only schema and cypherQuery populated)
Example:
const response = await client.cypherOnly('movies', 'Find all actors');
console.log('Generated query:', response.cypherQuery);
// Use the query however you wantdiscoverSchema(graphName)
Discovers and returns the schema of a graph as JSON.
Parameters:
graphName(string): Name of the graph
Returns: Promise<string> (JSON string)
Example:
const schema = await client.discoverSchema('movies');
const schemaObj = JSON.parse(schema);
console.log('Nodes:', schemaObj.nodes);
console.log('Relationships:', schemaObj.relationships);Model Discovery
listModels()
Lists all available AI models across all supported providers.
Note: This method queries all provider APIs (OpenAI, Anthropic, Gemini, Ollama) and aggregates the results. Each provider's live results are merged with a small curated static catalog, so providers with a curated list still return their well-known models even when no matching API key is configured. Providers without a curated list (e.g. Ollama) only appear when reachable. Models are returned with provider prefixes (except OpenAI).
Returns: Promise<string[]> - Array of model names with provider prefixes where applicable
Example:
const models = await client.listModels();
console.log('All available models:', models);
// Output: [
// 'gpt-4o-mini', 'gpt-4o', 'gpt-4-turbo', // OpenAI (no prefix)
// 'anthropic::claude-sonnet-4-5', 'anthropic::claude-opus-4-5', // Anthropic
// 'gemini::gemini-2.5-pro', 'gemini::gemini-3-pro-preview', // Gemini
// 'ollama::llama3', 'ollama::mistral' // Ollama (if running)
// ]Non-OpenAI models are namespaced with a provider::model (double-colon) prefix in the
returned list. When passing a model to the constructor you can use either that form or the
shorter provider:model (single-colon) form — both are accepted (e.g.
'anthropic::claude-sonnet-4-5' and 'anthropic:claude-sonnet-4-5' are equivalent).
listModelsByProvider(provider)
Lists available AI models from a specific provider by querying the actual provider APIs.
Note: This method merges each provider's live model list with a small curated static catalog. Providers with a curated list (OpenAI, Anthropic, Gemini) still return their well-known models even when no matching API key is configured; an API key adds any additional models the provider reports live. Providers without a curated list (e.g. Ollama) are only returned when reachable.
Parameters:
provider(string): Provider name -'openai','anthropic','gemini', or'ollama'(case-insensitive)
Returns: Promise<string[]> - Array of model names (without provider prefixes)
Example:
// List OpenAI models
const openaiModels = await client.listModelsByProvider('openai');
console.log('OpenAI models:', openaiModels);
// Output: ['gpt-4o-mini', 'gpt-4o', 'gpt-4-turbo', ...]
// List Anthropic models
const anthropicModels = await client.listModelsByProvider('anthropic');
console.log('Anthropic models:', anthropicModels);
// Output: ['claude-sonnet-4-5', 'claude-opus-4-5', 'claude-haiku-4-5']
// List Gemini models
const geminiModels = await client.listModelsByProvider('gemini');
console.log('Gemini models:', geminiModels);
// Output: ['gemini-2.5-pro', 'gemini-3-pro-preview', ...]
// List Ollama models (requires Ollama running locally)
const ollamaModels = await client.listModelsByProvider('ollama');
console.log('Ollama models:', ollamaModels);Supported Providers
openai- OpenAI models (GPT-4, GPT-3.5, etc.)- Models can be used directly:
'gpt-4o-mini'
- Models can be used directly:
anthropic- Anthropic models (Claude variants)- Models require prefix when using:
'anthropic:claude-sonnet-4-5'
- Models require prefix when using:
gemini- Google Gemini models- Models require prefix when using:
'gemini:gemini-2.5-pro'
- Models require prefix when using:
ollama- Local Ollama models (if configured)- Models require prefix when using:
'ollama:llama3'
- Models require prefix when using:
See the examples/list-models.js file for a complete working example.
Types
TextToCypherResponse
interface TextToCypherResponse {
status: string; // "success" or "error"
schema?: string; // JSON schema of the graph
cypherQuery?: string; // Generated Cypher query
cypherResult?: string; // Query execution result
answer?: string; // Natural language answer
error?: string; // Error message if status is "error"
tokenUsage?: TokenUsage; // Aggregated LLM token usage (omitted when no tokens were spent)
}
interface TokenUsage {
promptTokens: number; // Total input (prompt) tokens across all LLM calls
completionTokens: number; // Total output (completion) tokens across all LLM calls
totalTokens: number; // Total tokens across all LLM calls
}tokenUsage aggregates the prompt, completion, and total tokens reported by the LLM
provider across every call made while serving a request (cypher generation, the final
answer, self-healing retries, and skill tool-call rounds). It is present on successful
responses and omitted when no tokens were consumed. Failed requests reject with an error,
so tokenUsage is not surfaced for failures.
See examples/token-usage.js for a complete working example.
Message
interface Message {
role: string; // "user", "assistant", or "system"
content: string; // Message content
}Supported AI Models
This library uses the genai crate and supports:
- OpenAI:
gpt-4o-mini,gpt-4o,gpt-4-turbo, etc. - Anthropic:
anthropic:claude-3-5-sonnet-20241022,anthropic:claude-3-opus-20240229 - Google Gemini:
gemini:gemini-2.0-flash-exp,gemini:gemini-1.5-pro
See genai documentation for a complete list.
Examples
Using with FalkorDB Browser
const { TextToCypher } = require('@falkordb/text-to-cypher');
// In your Express.js or other Node.js server
app.post('/api/text-to-cypher', async (req, res) => {
const { graphName, question } = req.body;
try {
const client = new TextToCypher({
model: 'gpt-4o-mini',
apiKey: process.env.OPENAI_API_KEY,
falkordbConnection: process.env.FALKORDB_CONNECTION
});
const response = await client.textToCypher(graphName, question);
res.json(response);
} catch (error) {
res.status(500).json({ error: error.message });
}
});TypeScript Usage
import { TextToCypher, ClientOptions, TextToCypherResponse } from '@falkordb/text-to-cypher';
const options: ClientOptions = {
model: 'gpt-4o-mini',
apiKey: process.env.OPENAI_API_KEY!,
falkordbConnection: 'falkor://localhost:6379'
};
const client = new TextToCypher(options);
const response: TextToCypherResponse = await client.textToCypher(
'movies',
'Find top 10 highest rated movies'
);
console.log(response.answer);Error Handling
try {
const response = await client.textToCypher('movies', 'Find all actors');
if (response.status === 'error') {
console.error('Error:', response.error);
} else {
console.log('Success:', response.answer);
}
} catch (error) {
console.error('Exception:', error.message);
}Tracking Token Usage
Each request aggregates the token counts from every LLM call it makes (cypher generation,
self-healing retries, skill tool-call rounds, and final answer generation) into
response.tokenUsage:
const response = await client.textToCypher('movies', 'How many actors are there?');
if (response.tokenUsage) {
console.log('Prompt tokens:', response.tokenUsage.promptTokens);
console.log('Completion tokens:', response.tokenUsage.completionTokens);
console.log('Total tokens:', response.tokenUsage.totalTokens);
}See examples/token-usage.js for a complete, runnable example.
Requirements
- Node.js >= 20
- FalkorDB instance running and accessible
- API key for your chosen AI provider (OpenAI, Anthropic, etc.)
Development
Building from Source
# Install dependencies
npm install
# Build the native module
npm run build
# Run tests
npm testPrerequisites for Building
- Rust toolchain (install from rustup.rs)
- Node.js >= 20
- C++ compiler (platform-specific)
Platform Support
Pre-built binaries are available for:
- Linux x64 (glibc and musl)
- Linux ARM64 (glibc and musl)
- macOS x64 (Intel)
- macOS ARM64 (Apple Silicon)
- Windows x64
Releasing
Versions are derived automatically from Git tags. To publish a new release:
- Create a GitHub release with a semver tag (e.g.,
v1.2.0) - The release workflow builds all platform binaries and publishes to npm
- The version in
package.json(0.0.0) is a placeholder — the release CI sets the real version from the tag
No manual package.json version edits are needed.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - see LICENSE file for details.
Related Projects
- text-to-cypher - The underlying Rust library
- falkordb-browser - FalkorDB web interface
- FalkorDB - Graph database
Support
Acknowledgments
Built with NAPI-RS - A framework for building compiled Node.js add-ons in Rust.
