From 6105731e708a84044c4d35cb262ca8a5e5ea0574 Mon Sep 17 00:00:00 2001 From: Santosh Bhavani Date: Fri, 12 Dec 2025 10:58:59 -0800 Subject: [PATCH] feat: Add Neo4j support to txt2kg Add Neo4j as an alternative graph database backend alongside ArangoDB. This includes updates to the frontend components, API routes, and docker-compose configuration for Neo4j integration. --- .../assets/deploy/compose/docker-compose.yml | 74 +++++++++++++------ .../assets/frontend/app/api/graph-db/route.ts | 5 ++ .../assets/frontend/app/api/settings/route.ts | 50 ++++++++++++- .../components/database-connection.tsx | 33 ++++++--- .../frontend/components/settings-modal.tsx | 17 ++++- .../assets/frontend/lib/backend-service.ts | 29 +++++--- .../txt2kg/assets/frontend/lib/client-init.ts | 16 ++-- .../assets/frontend/lib/graph-db-service.ts | 46 +++++++----- .../assets/frontend/lib/graph-db-util.ts | 37 +++++++--- .../assets/frontend/lib/remote-backend.ts | 11 +-- 10 files changed, 228 insertions(+), 90 deletions(-) diff --git a/nvidia/txt2kg/assets/deploy/compose/docker-compose.yml b/nvidia/txt2kg/assets/deploy/compose/docker-compose.yml index 07e9e7d..4fef8fa 100644 --- a/nvidia/txt2kg/assets/deploy/compose/docker-compose.yml +++ b/nvidia/txt2kg/assets/deploy/compose/docker-compose.yml @@ -7,7 +7,13 @@ services: ports: - '3001:3000' environment: - - ARANGODB_URL=http://arangodb:8529 + # Neo4j configuration (ARM64 compatible - works with 64KB pages) + - NEO4J_URI=bolt://neo4j:7687 + - NEO4J_USER=neo4j + - NEO4J_PASSWORD=password123 + - GRAPH_DB_TYPE=neo4j + # ArangoDB disabled - set to localhost to prevent DNS errors if accidentally accessed + - ARANGODB_URL=http://localhost:8529 - ARANGODB_DB=txt2kg - QDRANT_URL=http://qdrant:6333 - VECTOR_DB_TYPE=qdrant @@ -31,32 +37,47 @@ services: - txt2kg-network - pinecone-net depends_on: - - arangodb - - ollama + neo4j: + condition: service_healthy + ollama: + condition: service_started # Optional: sentence-transformers and entity-embeddings are only needed for vector search # Traditional graph search works without these services - arangodb: - image: arangodb:latest + + # Neo4j - ARM64 compatible graph database (works with 64KB page size kernel) + neo4j: + image: neo4j:5-community ports: - - '8529:8529' + - '7474:7474' # HTTP + - '7687:7687' # Bolt environment: - - ARANGO_NO_AUTH=1 + - NEO4J_AUTH=neo4j/password123 + - NEO4J_server_memory_heap_initial__size=512m + - NEO4J_server_memory_heap_max__size=2G volumes: - - arangodb_data:/var/lib/arangodb3 - - arangodb_apps_data:/var/lib/arangodb3-apps - arangodb-init: - image: arangodb:latest - depends_on: - arangodb: - condition: service_started - restart: on-failure - entrypoint: > - sh -c " - echo 'Waiting for ArangoDB to start...' && - sleep 10 && - echo 'Creating txt2kg database...' && - arangosh --server.endpoint tcp://arangodb:8529 --server.authentication false --javascript.execute-string 'try { db._createDatabase(\"txt2kg\"); console.log(\"Database txt2kg created successfully!\"); } catch(e) { if(e.message.includes(\"duplicate\")) { console.log(\"Database txt2kg already exists\"); } else { throw e; } }' - " + - neo4j_data:/data + - neo4j_logs:/logs + networks: + - default + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:7474 || exit 1"] + interval: 15s + timeout: 10s + retries: 10 + start_period: 60s + + # ArangoDB disabled - doesn't support ARM64 with 64KB page size + # Uncomment if using 4KB page kernel (linux-nvidia-6.14) + # arangodb: + # image: arangodb:latest + # ports: + # - '8529:8529' + # environment: + # - ARANGO_NO_AUTH=1 + # volumes: + # - arangodb_data:/var/lib/arangodb3 + # - arangodb_apps_data:/var/lib/arangodb3-apps ollama: build: context: ../services/ollama @@ -70,11 +91,14 @@ services: environment: - NVIDIA_VISIBLE_DEVICES=all # Make all GPUs visible to the container - NVIDIA_DRIVER_CAPABILITIES=compute,utility # Required capabilities for CUDA + - CUDA_VISIBLE_DEVICES=0 # Use first GPU - OLLAMA_FLASH_ATTENTION=1 # Enable flash attention for better performance - OLLAMA_KEEP_ALIVE=30m # Keep models loaded for 30 minutes - OLLAMA_NUM_PARALLEL=4 # Process 4 requests in parallel - DGX Spark has unified memory - OLLAMA_MAX_LOADED_MODELS=1 # Load only one model at a time to avoid VRAM contention - OLLAMA_KV_CACHE_TYPE=q8_0 # Reduce KV cache VRAM usage with minimal performance impact + - OLLAMA_GPU_LAYERS=-1 # Force all layers on GPU + - OLLAMA_LLM_LIBRARY=cuda # Force CUDA backend networks: - default restart: unless-stopped @@ -161,10 +185,12 @@ services: - vector-search volumes: - arangodb_data: - arangodb_apps_data: + neo4j_data: + neo4j_logs: ollama_data: qdrant_data: + # arangodb_data: + # arangodb_apps_data: networks: default: diff --git a/nvidia/txt2kg/assets/frontend/app/api/graph-db/route.ts b/nvidia/txt2kg/assets/frontend/app/api/graph-db/route.ts index 91bb57f..eb44784 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/graph-db/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/graph-db/route.ts @@ -88,13 +88,18 @@ async function ensureConnection(request?: NextRequest): Promise { * GET handler for retrieving graph data from the selected graph database */ export async function GET(request: NextRequest) { + console.log('[graph-db GET] Request received'); try { // Initialize with connection parameters + console.log('[graph-db GET] Ensuring connection...'); const graphDbType = await ensureConnection(request); + console.log(`[graph-db GET] Using database type: ${graphDbType}`); const graphDbService = getGraphDbService(graphDbType); // Get graph data from the database + console.log('[graph-db GET] Fetching graph data...'); const graphData = await graphDbService.getGraphData(); + console.log(`[graph-db GET] Got ${graphData.nodes.length} nodes, ${graphData.relationships.length} relationships`); // Transform to format expected by the frontend const nodes = graphData.nodes.map(node => ({ diff --git a/nvidia/txt2kg/assets/frontend/app/api/settings/route.ts b/nvidia/txt2kg/assets/frontend/app/api/settings/route.ts index 5875395..cbb25cd 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/settings/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/settings/route.ts @@ -17,8 +17,26 @@ import { NextRequest, NextResponse } from 'next/server'; import { GraphDBType } from '@/lib/graph-db-service'; -// In-memory storage for settings +// In-memory storage for settings - use lazy initialization for env vars +// because they're not available at build time, only at runtime let serverSettings: Record = {}; +let settingsInitialized = false; + +function ensureSettingsInitialized() { + if (!settingsInitialized) { + // Read environment variables at runtime, not build time + serverSettings = { + graph_db_type: process.env.GRAPH_DB_TYPE || 'arangodb', + neo4j_uri: process.env.NEO4J_URI || '', + neo4j_user: process.env.NEO4J_USER || process.env.NEO4J_USERNAME || '', + neo4j_password: process.env.NEO4J_PASSWORD || '', + arangodb_url: process.env.ARANGODB_URL || '', + arangodb_db: process.env.ARANGODB_DB || '', + }; + settingsInitialized = true; + console.log(`[SETTINGS] Initialized at runtime with GRAPH_DB_TYPE: "${serverSettings.graph_db_type}"`); + } +} /** * API Route to sync client settings with server environment variables @@ -27,13 +45,16 @@ let serverSettings: Record = {}; */ export async function POST(request: NextRequest) { try { + // Ensure settings are initialized from env vars first + ensureSettingsInitialized(); + const { settings } = await request.json(); if (!settings || typeof settings !== 'object') { return NextResponse.json({ error: 'Settings object is required' }, { status: 400 }); } - // Update server settings + // Update server settings (merge with existing) serverSettings = { ...serverSettings, ...settings }; // Log some important settings for debugging @@ -58,6 +79,9 @@ export async function POST(request: NextRequest) { */ export async function GET(request: NextRequest) { try { + // Ensure settings are initialized from env vars first + ensureSettingsInitialized(); + const url = new URL(request.url); const key = url.searchParams.get('key'); @@ -84,12 +108,32 @@ export async function GET(request: NextRequest) { * For use in other API routes */ export function getSetting(key: string): string | null { + ensureSettingsInitialized(); return serverSettings[key] || null; } /** * Get the currently selected graph database type + * Priority: serverSettings > environment variable > default 'arangodb' */ export function getGraphDbType(): GraphDBType { - return (serverSettings.graph_db_type as GraphDBType) || 'arangodb'; + // Ensure settings are initialized from runtime environment variables + ensureSettingsInitialized(); + + // Check serverSettings (initialized from env vars or updated by client) + if (serverSettings.graph_db_type) { + console.log(`[getGraphDbType] Returning: "${serverSettings.graph_db_type}"`); + return serverSettings.graph_db_type as GraphDBType; + } + + // Direct fallback to runtime environment variable + const envType = process.env.GRAPH_DB_TYPE; + if (envType) { + console.log(`[getGraphDbType] Returning from env: "${envType}"`); + return envType as GraphDBType; + } + + // Default to arangodb for backwards compatibility + console.log(`[getGraphDbType] Returning default: "arangodb"`); + return 'arangodb'; } \ No newline at end of file diff --git a/nvidia/txt2kg/assets/frontend/components/database-connection.tsx b/nvidia/txt2kg/assets/frontend/components/database-connection.tsx index 4ddaa35..27f30b4 100644 --- a/nvidia/txt2kg/assets/frontend/components/database-connection.tsx +++ b/nvidia/txt2kg/assets/frontend/components/database-connection.tsx @@ -57,24 +57,34 @@ export function DatabaseConnection({ className }: DatabaseConnectionProps) { setGraphError(null) try { - // Get database type from localStorage - const graphDbType = localStorage.getItem("graph_db_type") || "arangodb" + // Get database type from localStorage, fall back to fetching from server + let graphDbType = localStorage.getItem("graph_db_type") + if (!graphDbType) { + // Fetch server's default (from GRAPH_DB_TYPE env var) + try { + const settingsRes = await fetch('/api/settings') + const settingsData = await settingsRes.json() + graphDbType = settingsData.settings?.graph_db_type || 'neo4j' + } catch { + graphDbType = 'neo4j' + } + } setDbType(graphDbType === "arangodb" ? "ArangoDB" : "Neo4j") if (graphDbType === "neo4j") { - // Neo4j connection logic + // Neo4j connection logic - use the unified graph-db endpoint const dbUrl = localStorage.getItem("NEO4J_URL") const dbUsername = localStorage.getItem("NEO4J_USERNAME") const dbPassword = localStorage.getItem("NEO4J_PASSWORD") - // Add query parameters if credentials exist + // Add query parameters with type=neo4j const queryParams = new URLSearchParams() + queryParams.append("type", "neo4j") if (dbUrl) queryParams.append("url", dbUrl) if (dbUsername) queryParams.append("username", dbUsername) if (dbPassword) queryParams.append("password", dbPassword) - const queryString = queryParams.toString() - const endpoint = queryString ? `/api/neo4j?${queryString}` : '/api/neo4j' + const endpoint = `/api/graph-db?${queryParams.toString()}` const response = await fetch(endpoint) @@ -98,21 +108,21 @@ export function DatabaseConnection({ className }: DatabaseConnectionProps) { setConnectionUrl(dbUrl) } } else { - // ArangoDB connection logic + // ArangoDB connection logic - use the unified graph-db endpoint with type=arangodb const arangoUrl = localStorage.getItem("arango_url") || "http://localhost:8529" const arangoDb = localStorage.getItem("arango_db") || "txt2kg" const arangoUser = localStorage.getItem("arango_user") || "" const arangoPassword = localStorage.getItem("arango_password") || "" - // Add query parameters if credentials exist + // Add query parameters with type=arangodb const queryParams = new URLSearchParams() + queryParams.append("type", "arangodb") if (arangoUrl) queryParams.append("url", arangoUrl) if (arangoDb) queryParams.append("dbName", arangoDb) if (arangoUser) queryParams.append("username", arangoUser) if (arangoPassword) queryParams.append("password", arangoPassword) - const queryString = queryParams.toString() - const endpoint = queryString ? `/api/graph-db?${queryString}` : '/api/graph-db' + const endpoint = `/api/graph-db?${queryParams.toString()}` const response = await fetch(endpoint) @@ -144,7 +154,8 @@ export function DatabaseConnection({ className }: DatabaseConnectionProps) { // Disconnect from graph database const disconnectGraph = async () => { try { - const graphDbType = localStorage.getItem("graph_db_type") || "arangodb" + // Use current dbType state which was already determined from server/localStorage + const graphDbType = dbType === "Neo4j" ? "neo4j" : "arangodb" const endpoint = graphDbType === "neo4j" ? '/api/neo4j/disconnect' : '/api/graph-db/disconnect' const response = await fetch(endpoint, { diff --git a/nvidia/txt2kg/assets/frontend/components/settings-modal.tsx b/nvidia/txt2kg/assets/frontend/components/settings-modal.tsx index c05cbf8..a3c0805 100644 --- a/nvidia/txt2kg/assets/frontend/components/settings-modal.tsx +++ b/nvidia/txt2kg/assets/frontend/components/settings-modal.tsx @@ -171,9 +171,20 @@ export function SettingsModal() { setIsS3Connected(s3Connected) } - // Load graph DB type - const storedGraphDbType = localStorage.getItem("graph_db_type") || "arangodb" - setGraphDbType(storedGraphDbType as GraphDBType) + // Load graph DB type - fetch from server if not in localStorage + const storedGraphDbType = localStorage.getItem("graph_db_type") + if (storedGraphDbType) { + setGraphDbType(storedGraphDbType as GraphDBType) + } else { + // Fetch server's default (from GRAPH_DB_TYPE env var) + fetch('/api/settings') + .then(res => res.json()) + .then(data => { + const serverDefault = data.settings?.graph_db_type || 'neo4j' + setGraphDbType(serverDefault as GraphDBType) + }) + .catch(() => setGraphDbType('neo4j')) + } // Load Neo4j settings setNeo4jUrl(localStorage.getItem("neo4j_url") || "") diff --git a/nvidia/txt2kg/assets/frontend/lib/backend-service.ts b/nvidia/txt2kg/assets/frontend/lib/backend-service.ts index b2b34d1..ae49453 100644 --- a/nvidia/txt2kg/assets/frontend/lib/backend-service.ts +++ b/nvidia/txt2kg/assets/frontend/lib/backend-service.ts @@ -37,7 +37,15 @@ export class BackendService { private modelName: string = 'all-MiniLM-L6-v2'; private static instance: BackendService; private initialized: boolean = false; - private activeGraphDbType: GraphDBType = 'arangodb'; + private activeGraphDbType: GraphDBType | null = null; // Set at runtime, not build time + + private getRuntimeGraphDbType(): GraphDBType { + if (this.activeGraphDbType === null) { + this.activeGraphDbType = (process.env.GRAPH_DB_TYPE as GraphDBType) || 'arangodb'; + console.log(`[BackendService] Initialized activeGraphDbType at runtime: ${this.activeGraphDbType}`); + } + return this.activeGraphDbType; + } private constructor() { this.graphDBService = GraphDBService.getInstance(); @@ -64,16 +72,17 @@ export class BackendService { /** * Initialize the backend services - * @param graphDbType - Type of graph database to use (neo4j or arangodb) + * @param graphDbType - Type of graph database to use (defaults to GRAPH_DB_TYPE env var) */ - public async initialize(graphDbType: GraphDBType = 'arangodb'): Promise { - this.activeGraphDbType = graphDbType; + public async initialize(graphDbType?: GraphDBType): Promise { + const dbType = graphDbType || (process.env.GRAPH_DB_TYPE as GraphDBType) || 'arangodb'; + this.activeGraphDbType = dbType; // Initialize Graph Database if (!this.graphDBService.isInitialized()) { try { // Get the appropriate service based on type - const graphDbService = getGraphDbService(graphDbType); + const graphDbService = getGraphDbService(dbType); // Try to get settings from server settings API first let serverSettings: Record = {}; @@ -88,7 +97,7 @@ export class BackendService { console.log('Failed to load settings from server API, falling back to environment variables:', error); } - if (graphDbType === 'neo4j') { + if (dbType === 'neo4j') { // Get Neo4j credentials from server settings first, then fallback to environment const uri = serverSettings.neo4j_url || process.env.NEO4J_URI; const username = serverSettings.neo4j_user || process.env.NEO4J_USER || process.env.NEO4J_USERNAME; @@ -107,9 +116,9 @@ export class BackendService { console.log(`Using ArangoDB database: ${dbName}`); await this.graphDBService.initialize('arangodb', url, username, password); } - console.log(`${graphDbType} initialized successfully in backend service`); + console.log(`${dbType} initialized successfully in backend service`); } catch (error) { - console.error(`Failed to initialize ${graphDbType} in backend service:`, error); + console.error(`Failed to initialize ${dbType} in backend service:`, error); if (process.env.NODE_ENV === 'development') { console.log('Development mode: Continuing despite graph database initialization error'); } else { @@ -151,7 +160,7 @@ export class BackendService { * Get the active graph database type */ public getGraphDbType(): GraphDBType { - return this.activeGraphDbType; + return this.getRuntimeGraphDbType(); } /** @@ -253,7 +262,7 @@ export class BackendService { const filteredKeywords = keywords.filter(kw => !this.isStopWord(kw)); // If using ArangoDB, use its native graph traversal capabilities - if (this.activeGraphDbType === 'arangodb') { + if (this.getRuntimeGraphDbType() === 'arangodb') { console.log(`Using ArangoDB native graph traversal for keywords: ${filteredKeywords.join(', ')}`); try { diff --git a/nvidia/txt2kg/assets/frontend/lib/client-init.ts b/nvidia/txt2kg/assets/frontend/lib/client-init.ts index 1ef1d35..01ca4ff 100644 --- a/nvidia/txt2kg/assets/frontend/lib/client-init.ts +++ b/nvidia/txt2kg/assets/frontend/lib/client-init.ts @@ -22,18 +22,17 @@ /** * Initialize default database settings if not already set * Called before syncing with server to ensure defaults are available + * NOTE: Don't set graph_db_type here - let server's GRAPH_DB_TYPE env var control it */ export function initializeDefaultSettings() { if (typeof window === 'undefined') { return; // Only run on client side } - // Set default graph DB type to ArangoDB if not set - if (!localStorage.getItem('graph_db_type')) { - localStorage.setItem('graph_db_type', 'arangodb'); - } - - // Set default ArangoDB settings if not set + // Don't set graph_db_type default - let it be controlled by server's GRAPH_DB_TYPE env var + // The server will use its environment variable if no client setting is provided + + // Set default connection settings only (not the database type selection) if (!localStorage.getItem('arango_url')) { localStorage.setItem('arango_url', 'http://localhost:8529'); } @@ -41,6 +40,11 @@ export function initializeDefaultSettings() { if (!localStorage.getItem('arango_db')) { localStorage.setItem('arango_db', 'txt2kg'); } + + // Set default Neo4j settings + if (!localStorage.getItem('neo4j_url')) { + localStorage.setItem('neo4j_url', 'bolt://localhost:7687'); + } } /** diff --git a/nvidia/txt2kg/assets/frontend/lib/graph-db-service.ts b/nvidia/txt2kg/assets/frontend/lib/graph-db-service.ts index 8a0f839..2a1201b 100644 --- a/nvidia/txt2kg/assets/frontend/lib/graph-db-service.ts +++ b/nvidia/txt2kg/assets/frontend/lib/graph-db-service.ts @@ -26,7 +26,7 @@ export type GraphDBType = 'neo4j' | 'arangodb'; export class GraphDBService { private neo4jService: Neo4jService; private arangoDBService: ArangoDBService; - private activeDBType: GraphDBType = 'arangodb'; // Default to ArangoDB + private activeDBType: GraphDBType | null = null; // Set at runtime, not build time private static instance: GraphDBService; private constructor() { @@ -34,6 +34,17 @@ export class GraphDBService { this.arangoDBService = ArangoDBService.getInstance(); } + /** + * Get the active DB type, reading from env at runtime if not set + */ + private getActiveDBType(): GraphDBType { + if (this.activeDBType === null) { + this.activeDBType = (process.env.GRAPH_DB_TYPE as GraphDBType) || 'arangodb'; + console.log(`[GraphDBService] Initialized activeDBType at runtime: ${this.activeDBType}`); + } + return this.activeDBType; + } + /** * Get the singleton instance of GraphDBService */ @@ -46,24 +57,25 @@ export class GraphDBService { /** * Initialize the graph database with the specified type - * @param dbType - Type of graph database to use + * @param dbType - Type of graph database to use (defaults to GRAPH_DB_TYPE env var) * @param uri - Connection URL * @param username - Database username * @param password - Database password */ - public async initialize(dbType: GraphDBType = 'arangodb', uri?: string, username?: string, password?: string): Promise { - this.activeDBType = dbType; + public async initialize(dbType?: GraphDBType, uri?: string, username?: string, password?: string): Promise { + const graphDbType = dbType || (process.env.GRAPH_DB_TYPE as GraphDBType) || 'arangodb'; + this.activeDBType = graphDbType; try { - if (dbType === 'neo4j') { + if (graphDbType === 'neo4j') { this.neo4jService.initialize(uri, username, password); console.log('Neo4j initialized successfully'); - } else if (dbType === 'arangodb') { + } else if (graphDbType === 'arangodb') { await this.arangoDBService.initialize(uri, undefined, username, password); console.log('ArangoDB initialized successfully'); } } catch (error) { - console.error(`Failed to initialize ${dbType}:`, error); + console.error(`Failed to initialize ${graphDbType}:`, error); throw error; } } @@ -79,14 +91,14 @@ export class GraphDBService { * Get the active graph database type */ public getDBType(): GraphDBType { - return this.activeDBType; + return this.getActiveDBType(); } /** * Check if the active database is initialized */ public isInitialized(): boolean { - if (this.activeDBType === 'neo4j') { + if (this.getActiveDBType() === 'neo4j') { return this.neo4jService.isInitialized(); } else { return this.arangoDBService.isInitialized(); @@ -97,7 +109,7 @@ export class GraphDBService { * Import triples into the active graph database */ public async importTriples(triples: { subject: string; predicate: string; object: string }[]): Promise { - if (this.activeDBType === 'neo4j') { + if (this.getActiveDBType() === 'neo4j') { await this.neo4jService.importTriples(triples); } else { await this.arangoDBService.importTriples(triples); @@ -121,7 +133,7 @@ export class GraphDBService { [key: string]: any }>; }> { - if (this.activeDBType === 'neo4j') { + if (this.getActiveDBType() === 'neo4j') { return await this.neo4jService.getGraphData(); } else { return await this.arangoDBService.getGraphData(); @@ -142,7 +154,7 @@ export class GraphDBService { resultCount: number; } ): Promise { - if (this.activeDBType === 'neo4j') { + if (this.getActiveDBType() === 'neo4j') { await this.neo4jService.logQuery(query, queryMode, metrics); } else { await this.arangoDBService.logQuery(query, queryMode, metrics); @@ -153,7 +165,7 @@ export class GraphDBService { * Get query logs from the active graph database */ public async getQueryLogs(limit: number = 100): Promise { - if (this.activeDBType === 'neo4j') { + if (this.getActiveDBType() === 'neo4j') { return await this.neo4jService.getQueryLogs(limit); } else { return await this.arangoDBService.getQueryLogs(limit); @@ -164,7 +176,7 @@ export class GraphDBService { * Close the connection to the active graph database */ public async close(): Promise { - if (this.activeDBType === 'neo4j') { + if (this.getActiveDBType() === 'neo4j') { this.neo4jService.close(); } else { this.arangoDBService.close(); @@ -175,7 +187,7 @@ export class GraphDBService { * Get info about the active graph database driver */ public getDriverInfo(): Record { - if (this.activeDBType === 'neo4j') { + if (this.getActiveDBType() === 'neo4j') { return this.neo4jService.getDriverInfo(); } else { return this.arangoDBService.getDriverInfo(); @@ -197,7 +209,7 @@ export class GraphDBService { confidence: number; depth?: number; }>> { - if (this.activeDBType === 'arangodb') { + if (this.getActiveDBType() === 'arangodb') { return await this.arangoDBService.graphTraversal(keywords, maxDepth, maxResults); } else { // Neo4j doesn't have this method yet, return empty array @@ -210,7 +222,7 @@ export class GraphDBService { * Clear all data from the active graph database */ public async clearDatabase(): Promise { - if (this.activeDBType === 'neo4j') { + if (this.getActiveDBType() === 'neo4j') { // TODO: Implement Neo4j clear database functionality throw new Error('Clear database functionality not implemented for Neo4j'); } else { diff --git a/nvidia/txt2kg/assets/frontend/lib/graph-db-util.ts b/nvidia/txt2kg/assets/frontend/lib/graph-db-util.ts index 84752d1..c4c6dc7 100644 --- a/nvidia/txt2kg/assets/frontend/lib/graph-db-util.ts +++ b/nvidia/txt2kg/assets/frontend/lib/graph-db-util.ts @@ -18,20 +18,34 @@ import { GraphDBService, GraphDBType } from './graph-db-service'; import { Neo4jService } from './neo4j'; import { ArangoDBService } from './arangodb'; +/** + * Get the default graph database type from environment or fallback to arangodb + * Note: This is called at runtime, not build time, so process.env should be available + */ +function getDefaultGraphDbType(): GraphDBType { + const envType = process.env.GRAPH_DB_TYPE; + console.log(`[graph-db-util] getDefaultGraphDbType: env=${envType}`); + return (envType as GraphDBType) || 'arangodb'; +} + /** * Get the appropriate graph database service based on the graph database type. * This is useful for API routes that need direct access to a specific graph database. * - * @param graphDbType - The type of graph database to use + * @param graphDbType - The type of graph database to use (defaults to GRAPH_DB_TYPE env var) */ -export function getGraphDbService(graphDbType: GraphDBType = 'arangodb') { - if (graphDbType === 'neo4j') { +export function getGraphDbService(graphDbType?: GraphDBType) { + const dbType = graphDbType || getDefaultGraphDbType(); + + if (dbType === 'neo4j') { return Neo4jService.getInstance(); - } else if (graphDbType === 'arangodb') { + } else if (dbType === 'arangodb') { return ArangoDBService.getInstance(); } else { - // Default to ArangoDB - return ArangoDBService.getInstance(); + // Default based on environment + return getDefaultGraphDbType() === 'neo4j' + ? Neo4jService.getInstance() + : ArangoDBService.getInstance(); } } @@ -39,12 +53,13 @@ export function getGraphDbService(graphDbType: GraphDBType = 'arangodb') { * Initialize the graph database directly (not using GraphDBService). * This is useful for API routes that need direct access to a specific graph database. * - * @param graphDbType - The type of graph database to use + * @param graphDbType - The type of graph database to use (defaults to GRAPH_DB_TYPE env var) */ -export async function initializeGraphDb(graphDbType: GraphDBType = 'arangodb'): Promise { - const service = getGraphDbService(graphDbType); +export async function initializeGraphDb(graphDbType?: GraphDBType): Promise { + const dbType = graphDbType || getDefaultGraphDbType(); + const service = getGraphDbService(dbType); - if (graphDbType === 'neo4j') { + if (dbType === 'neo4j') { // Get Neo4j credentials from environment const uri = process.env.NEO4J_URI; const username = process.env.NEO4J_USER || process.env.NEO4J_USERNAME; @@ -54,7 +69,7 @@ export async function initializeGraphDb(graphDbType: GraphDBType = 'arangodb'): if (service instanceof Neo4jService) { service.initialize(uri, username, password); } - } else if (graphDbType === 'arangodb') { + } else if (dbType === 'arangodb') { // Get ArangoDB credentials from environment const url = process.env.ARANGODB_URL; const dbName = process.env.ARANGODB_DB; diff --git a/nvidia/txt2kg/assets/frontend/lib/remote-backend.ts b/nvidia/txt2kg/assets/frontend/lib/remote-backend.ts index bf9618e..d28641c 100644 --- a/nvidia/txt2kg/assets/frontend/lib/remote-backend.ts +++ b/nvidia/txt2kg/assets/frontend/lib/remote-backend.ts @@ -60,14 +60,15 @@ export class RemoteBackendService { /** * Initialize the remote backend with all required services - * @param graphDbType - Type of graph database to use + * @param graphDbType - Type of graph database to use (defaults to GRAPH_DB_TYPE env var) */ - public async initialize(graphDbType: GraphDBType = 'arangodb'): Promise { - console.log('Initializing remote backend...'); + public async initialize(graphDbType?: GraphDBType): Promise { + const dbType = graphDbType || (process.env.GRAPH_DB_TYPE as GraphDBType) || 'arangodb'; + console.log(`Initializing remote backend with ${dbType}...`); // Initialize Graph Database - await this.graphDBService.initialize(graphDbType); - console.log(`${graphDbType} service initialized`); + await this.graphDBService.initialize(dbType); + console.log(`${dbType} service initialized`); // Initialize Pinecone await this.pineconeService.initialize();