From 373591c46f47ac63c95cf1e19c2d06c7cd542848 Mon Sep 17 00:00:00 2001 From: GitLab CI Date: Tue, 2 Dec 2025 19:43:52 +0000 Subject: [PATCH] chore: Regenerate all playbooks --- nvidia/txt2kg/README.md | 5 +- nvidia/txt2kg/assets/.dockerignore | 43 +- nvidia/txt2kg/assets/deploy/app/Dockerfile | 86 ++- .../app/arangodb-init/create-database.js | 16 + .../assets/deploy/app/arangodb-init/init.sh | 16 + .../txt2kg/assets/deploy/app/pinecone-init.sh | 16 + .../txt2kg/assets/deploy/app/qdrant-init.sh | 68 ++ .../assets/deploy/compose/docker-compose.yml | 92 ++- .../assets/deploy/services/gnn_model/app.py | 16 + .../services/gnn_model/client_example.py | 16 + .../deploy/services/gnn_model/train_export.py | 16 + .../assets/deploy/services/gpu-viz/Dockerfile | 1 + .../assets/deploy/services/gpu-viz/README.md | 77 +- .../services/gpu-viz/local_gpu_viz_service.py | 16 + .../services/gpu-viz/pygraphistry_service.py | 728 ++++++++++++++++++ .../gpu-viz/remote_gpu_rendering_service.py | 16 + .../remote_webgpu_clustering_service.py | 16 + .../remote_webgpu_clustering_service_cupy.py | 16 + .../deploy/services/gpu-viz/requirements.txt | 2 + .../gpu-viz/semantic_clustering_service.py | 16 + .../services/gpu-viz/simple_webgpu_test.py | 16 + .../gpu-viz/start_remote_gpu_services.sh | 16 + .../gpu-viz/stop_remote_gpu_services.sh | 16 + .../services/gpu-viz/unified_gpu_service.py | 306 ++++---- .../gpu-viz/webgl_rendering_enhancement.py | 16 + .../assets/deploy/services/ollama/Dockerfile | 2 +- .../ollama/clear_cache_and_restart.sh | 16 + .../deploy/services/ollama/entrypoint.sh | 16 + .../services/sentence-transformers/app.py | 16 + .../deploy/services/vllm/build_image.sh | 16 + .../deploy/services/vllm/launch_server.sh | 16 + .../deploy/services/vllm/run_benchmark.sh | 16 + .../deploy/services/vllm/run_container.sh | 16 + .../assets/deploy/services/vllm/start-vllm.sh | 16 + .../examples/download_biorxiv_dataset.py | 16 + .../examples/download_cc_biorxiv_dataset.py | 16 + .../app/.static/3d-force-graph-mock.js | 16 + .../assets/frontend/app/api/backend/route.ts | 16 + .../assets/frontend/app/api/config/route.ts | 16 + .../frontend/app/api/embeddings/route.ts | 34 +- .../frontend/app/api/enhanced-query/route.ts | 16 + .../frontend/app/api/extract-triples/route.ts | 22 +- .../frontend/app/api/fix-query-logs/route.ts | 16 + .../frontend/app/api/graph-data/route.ts | 16 + .../frontend/app/api/graph-db/clear/route.ts | 16 + .../app/api/graph-db/disconnect/route.ts | 16 + .../assets/frontend/app/api/graph-db/route.ts | 16 + .../app/api/graph-db/triples/route.ts | 26 + .../frontend/app/api/graph-query-llm/route.ts | 66 ++ .../assets/frontend/app/api/metrics/route.ts | 84 +- .../app/api/neo4j/disconnect/route.ts | 16 + .../assets/frontend/app/api/neo4j/route.ts | 16 + .../frontend/app/api/neo4j/triples/route.ts | 16 + .../frontend/app/api/ollama/batch/route.ts | 16 + .../assets/frontend/app/api/ollama/route.ts | 16 + .../frontend/app/api/ollama/test/route.ts | 16 + .../app/api/pinecone-diag/clear/route.ts | 20 +- .../api/pinecone-diag/create-index/route.ts | 20 +- .../app/api/pinecone-diag/stats/route.ts | 20 +- .../app/api/process-document/route.ts | 16 + .../pygraphistry/generate/[taskId]/route.ts | 16 + .../app/api/pygraphistry/generate/route.ts | 16 + .../app/api/pygraphistry/health/route.ts | 16 + .../app/api/pygraphistry/stats/route.ts | 16 + .../app/api/pygraphistry/visualize/route.ts | 16 + .../frontend/app/api/query-log/add/route.ts | 16 + .../frontend/app/api/query-log/route.ts | 16 + .../frontend/app/api/query-log/test/route.ts | 16 + .../assets/frontend/app/api/query/route.ts | 16 + .../frontend/app/api/rag-query/route.ts | 27 +- .../remote-webgpu-stream/[sessionId]/route.ts | 16 + .../app/api/remote-webgpu/[...path]/route.ts | 16 + .../app/api/sentence-embeddings/route.ts | 20 +- .../assets/frontend/app/api/settings/route.ts | 16 + .../frontend/app/api/stop-embeddings/route.ts | 16 + .../frontend/app/api/stop-processing/route.ts | 16 + .../frontend/app/api/store-documents/route.ts | 16 + .../frontend/app/api/test-proxy/route.ts | 16 + .../app/api/unified-gpu/capabilities/route.ts | 16 + .../app/api/unified-gpu/visualize/route.ts | 16 + .../assets/frontend/app/api/vllm/route.ts | 16 + .../app/components/documents-list.tsx | 16 + .../frontend/app/document-data/page.tsx | 16 + .../txt2kg/assets/frontend/app/graph/page.tsx | 16 + .../assets/frontend/app/graph3d/page.tsx | 16 + nvidia/txt2kg/assets/frontend/app/layout.tsx | 19 +- nvidia/txt2kg/assets/frontend/app/page.tsx | 16 + .../assets/frontend/app/rag/metrics/page.tsx | 17 + .../txt2kg/assets/frontend/app/rag/page.tsx | 267 +++++-- .../frontend/app/test-large-graph/page.tsx | 16 + .../frontend/app/test-million-nodes/page.tsx | 16 + .../app/test-webgpu-clustering/page.tsx | 16 + .../frontend/components/advanced-options.tsx | 16 + .../frontend/components/api-key-prompt.tsx | 16 + .../frontend/components/client-init.tsx | 16 + .../components/database-connection.tsx | 251 ++++-- .../frontend/components/document-actions.tsx | 16 + .../components/document-processor.tsx | 16 + .../components/document-selection.tsx | 83 +- .../frontend/components/documents-table.tsx | 16 + .../frontend/components/dynamic-graph.tsx | 16 + .../components/embeddings-generator.tsx | 31 +- .../enhanced-graph-visualization.tsx | 113 +-- .../frontend/components/fallback-graph.tsx | 16 + .../components/force-graph-wrapper.tsx | 55 +- .../frontend/components/graph-actions.tsx | 53 +- .../frontend/components/graph-data-form.tsx | 16 + .../frontend/components/graph-toolbar.tsx | 16 + .../components/graph-visualization.tsx | 16 + .../assets/frontend/components/info-modal.tsx | 19 +- .../components/knowledge-graph-viewer.tsx | 16 + .../components/llm-selector-compact.tsx | 183 +++++ .../frontend/components/local-gpu-viewer.tsx | 16 + .../frontend/components/model-selector.tsx | 28 +- .../frontend/components/nemotron-chat.tsx | 16 + .../components/nemotron-model-hook.tsx | 16 + .../frontend/components/neo4j-connection.tsx | 16 + .../frontend/components/nvidia-icon.tsx | 16 + .../frontend/components/nvidia-logo.tsx | 16 + .../frontend/components/ollama-connection.tsx | 16 + .../components/pinecone-connection.tsx | 52 +- .../components/prompt-configuration.tsx | 20 +- .../components/pygraphistry-viewer.tsx | 16 + .../assets/frontend/components/rag-query.tsx | 94 ++- .../frontend/components/remote-gpu-viewer.tsx | 16 + .../frontend/components/s3-connection.tsx | 16 + .../components/s3-upload-container.tsx | 16 + .../assets/frontend/components/s3-upload.tsx | 16 + .../frontend/components/settings-modal.tsx | 16 + .../frontend/components/tabs/ConfigureTab.tsx | 19 +- .../frontend/components/tabs/EditTab.tsx | 16 + .../frontend/components/tabs/UploadTab.tsx | 16 + .../frontend/components/tabs/VisualizeTab.tsx | 16 + .../frontend/components/theme-provider.tsx | 16 + .../frontend/components/theme-toggle.tsx | 16 + .../frontend/components/triple-editor.tsx | 16 + .../frontend/components/triple-viewer.tsx | 16 + .../frontend/components/ui/alert-dialog.tsx | 16 + .../assets/frontend/components/ui/alert.tsx | 16 + .../assets/frontend/components/ui/avatar.tsx | 16 + .../assets/frontend/components/ui/badge.tsx | 16 + .../assets/frontend/components/ui/button.tsx | 16 + .../assets/frontend/components/ui/card.tsx | 16 + .../frontend/components/ui/checkbox.tsx | 16 + .../frontend/components/ui/collapsible.tsx | 16 + .../assets/frontend/components/ui/dialog.tsx | 16 + .../frontend/components/ui/dropdown-menu.tsx | 16 + .../assets/frontend/components/ui/input.tsx | 16 + .../assets/frontend/components/ui/label.tsx | 16 + .../frontend/components/ui/ollama-icon.tsx | 16 + .../frontend/components/ui/pagination.tsx | 16 + .../assets/frontend/components/ui/popover.tsx | 16 + .../frontend/components/ui/progress.tsx | 16 + .../frontend/components/ui/radio-group.tsx | 16 + .../frontend/components/ui/scroll-area.tsx | 16 + .../assets/frontend/components/ui/select.tsx | 16 + .../frontend/components/ui/separator.tsx | 16 + .../assets/frontend/components/ui/sheet.tsx | 16 + .../assets/frontend/components/ui/sidebar.tsx | 16 + .../frontend/components/ui/skeleton.tsx | 16 + .../assets/frontend/components/ui/slider.tsx | 16 + .../assets/frontend/components/ui/spinner.tsx | 16 + .../assets/frontend/components/ui/switch.tsx | 16 + .../assets/frontend/components/ui/table.tsx | 16 + .../assets/frontend/components/ui/tabs.tsx | 16 + .../frontend/components/ui/textarea.tsx | 16 + .../assets/frontend/components/ui/toast.tsx | 16 + .../assets/frontend/components/ui/toaster.tsx | 16 + .../frontend/components/ui/toggle-group.tsx | 16 + .../assets/frontend/components/ui/toggle.tsx | 16 + .../assets/frontend/components/ui/tooltip.tsx | 16 + .../frontend/components/ui/use-mobile.tsx | 16 + .../frontend/components/ui/use-toast.ts | 16 + .../components/unified-gpu-viewer.tsx | 16 + .../frontend/components/upload-documents.tsx | 16 + .../frontend/components/webgpu-3d-viewer.tsx | 111 +-- .../components/webrtc-graph-viewer.tsx | 16 + .../frontend/contexts/document-context.tsx | 62 +- .../frontend/hooks/use-keyboard-shortcuts.ts | 16 + .../assets/frontend/hooks/use-mobile.tsx | 16 + .../assets/frontend/hooks/use-shift-select.ts | 16 + .../txt2kg/assets/frontend/hooks/use-toast.ts | 16 + .../assets/frontend/lib/arangodb-loader.ts | 16 + nvidia/txt2kg/assets/frontend/lib/arangodb.ts | 283 ++++++- .../assets/frontend/lib/backend-service.ts | 286 ++++++- .../txt2kg/assets/frontend/lib/client-init.ts | 16 + .../txt2kg/assets/frontend/lib/embeddings.ts | 20 +- .../assets/frontend/lib/graph-db-service.ts | 40 + .../assets/frontend/lib/graph-db-util.ts | 16 + .../assets/frontend/lib/langchain-service.ts | 26 +- .../txt2kg/assets/frontend/lib/llm-service.ts | 16 + nvidia/txt2kg/assets/frontend/lib/neo4j.ts | 16 + nvidia/txt2kg/assets/frontend/lib/pinecone.ts | 16 + nvidia/txt2kg/assets/frontend/lib/qdrant.ts | 704 +++++++++++++++++ .../assets/frontend/lib/query-logger.ts | 28 +- nvidia/txt2kg/assets/frontend/lib/rag.ts | 263 +++++-- .../assets/frontend/lib/remote-backend.ts | 24 +- .../assets/frontend/lib/text-processor.ts | 184 ++++- nvidia/txt2kg/assets/frontend/lib/utils.ts | 16 + nvidia/txt2kg/assets/frontend/next.config.mjs | 2 + nvidia/txt2kg/assets/frontend/next.env.d.ts | 16 + nvidia/txt2kg/assets/frontend/package.json | 4 +- .../txt2kg/assets/frontend/tailwind.config.ts | 16 + nvidia/txt2kg/assets/frontend/types/graph.ts | 16 + .../frontend/types/next-navigation.d.ts | 16 + .../utils/remote-webgpu-clustering.ts | 16 + .../assets/frontend/utils/s3-storage.ts | 16 + .../assets/frontend/utils/text-processing.ts | 16 + .../frontend/utils/webgpu-clustering.ts | 16 + nvidia/txt2kg/assets/scripts/benchmark_llm.py | 16 + .../assets/scripts/gnn/arangodb_txt2kg.py | 16 + .../assets/scripts/gnn/preprocess_data.py | 16 + .../assets/scripts/gnn/train_test_gnn.py | 16 + .../assets/scripts/kg_extraction_benchmark.py | 16 + .../txt2kg/assets/scripts/setup-pinecone.js | 16 + .../assets/scripts/test-graph-transformer.js | 16 + nvidia/txt2kg/assets/start.sh | 43 ++ nvidia/txt2kg/assets/stop.sh | 100 +++ 218 files changed, 7001 insertions(+), 872 deletions(-) create mode 100644 nvidia/txt2kg/assets/deploy/app/qdrant-init.sh create mode 100644 nvidia/txt2kg/assets/deploy/services/gpu-viz/pygraphistry_service.py create mode 100644 nvidia/txt2kg/assets/frontend/app/api/graph-query-llm/route.ts create mode 100644 nvidia/txt2kg/assets/frontend/components/llm-selector-compact.tsx create mode 100644 nvidia/txt2kg/assets/frontend/lib/qdrant.ts create mode 100755 nvidia/txt2kg/assets/stop.sh diff --git a/nvidia/txt2kg/README.md b/nvidia/txt2kg/README.md index 5f63781..320e58e 100644 --- a/nvidia/txt2kg/README.md +++ b/nvidia/txt2kg/README.md @@ -54,8 +54,9 @@ The setup includes: - Document processing time scales with document size and complexity - **Rollback**: Stop and remove Docker containers, delete downloaded models if needed -- **Last Updated**: 11/19/2025 - - Updated GPU Visualization Service +- **Last Updated**: 12/02/2025 + - Knowledge graph search with multi-hop graph traversal + - Improved UI/UX ## Instructions diff --git a/nvidia/txt2kg/assets/.dockerignore b/nvidia/txt2kg/assets/.dockerignore index e3638a5..54ae452 100644 --- a/nvidia/txt2kg/assets/.dockerignore +++ b/nvidia/txt2kg/assets/.dockerignore @@ -1,3 +1,44 @@ +# Dependencies node_modules +.pnpm-store +**/node_modules +**/.pnpm-store + +# Next.js build outputs .next -.git \ No newline at end of file +out +**/.next +**/out + +# Git +.git +.gitignore +**/.git + +# Logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* + +# IDE +.vscode +.idea +*.swp +*.swo +.DS_Store + +# Testing +coverage +__tests__ +*.test.ts +*.test.tsx +*.spec.ts +*.spec.tsx + +# Misc +.env.local +.env.*.local +README.md +.eslintcache \ No newline at end of file diff --git a/nvidia/txt2kg/assets/deploy/app/Dockerfile b/nvidia/txt2kg/assets/deploy/app/Dockerfile index 8e0f786..ba47645 100644 --- a/nvidia/txt2kg/assets/deploy/app/Dockerfile +++ b/nvidia/txt2kg/assets/deploy/app/Dockerfile @@ -1,48 +1,74 @@ -# Use the official Node.js image from the Docker Hub -FROM node:18-slim - -# Set environment variables to avoid interactive prompts -ENV DEBIAN_FRONTEND=noninteractive -ENV NPM_CONFIG_YES=true -ENV PNPM_HOME=/pnpm -ENV PATH="$PNPM_HOME:$PATH" - -# Set the working directory +# Optimized multi-stage Dockerfile for faster builds +# Stage 1: Dependencies +FROM node:18-slim AS deps WORKDIR /app -# Install pnpm globally with --force and yes flags +# Install pnpm RUN npm install -g pnpm --force --yes -# Copy package files ONLY (for better Docker layer caching) -# Copy package.json (required) and pnpm-lock.yaml (optional) -COPY ./frontend/package.json ./ -COPY ./frontend/pnpm-lock.yaml* ./ - -# Copy the scripts directory (needed for setup-pinecone) +# Copy dependency files +COPY ./frontend/package.json ./frontend/pnpm-lock.yaml* ./ COPY ./scripts/ /scripts/ -# Update the setup-pinecone.js path in package.json +# Update the setup-pinecone.js path RUN sed -i 's|"setup-pinecone": "node ../scripts/setup-pinecone.js"|"setup-pinecone": "node /scripts/setup-pinecone.js"|g' package.json -# Install project dependencies (this layer will be cached if package files don't change) -# Use --no-frozen-lockfile as fallback if lockfile is missing or out of sync -RUN pnpm config set auto-install-peers true && \ +# Install dependencies with cache mount for faster rebuilds +RUN --mount=type=cache,target=/root/.local/share/pnpm/store \ + pnpm config set auto-install-peers true && \ if [ -f pnpm-lock.yaml ]; then \ - echo "Lock file found, installing with frozen lockfile..." && \ - (pnpm install --no-optional --frozen-lockfile || pnpm install --no-optional --no-frozen-lockfile); \ + pnpm install --no-optional --frozen-lockfile || pnpm install --no-optional --no-frozen-lockfile; \ else \ - echo "No lock file found, installing without frozen lockfile..." && \ pnpm install --no-optional --no-frozen-lockfile; \ fi -# Copy the rest of the frontend files +# Stage 2: Builder +FROM node:18-slim AS builder +WORKDIR /app + +# Install pnpm +RUN npm install -g pnpm --force --yes + +# Copy node_modules from deps stage +COPY --from=deps /app/node_modules ./node_modules +COPY --from=deps /app/package.json ./package.json +COPY --from=deps /scripts /scripts + +# Copy source code COPY ./frontend/ ./ -# Build the application -RUN pnpm build +# Set build environment variables +ENV NEXT_TELEMETRY_DISABLED 1 +ENV NODE_ENV production + +# Build with cache mount for Next.js cache +RUN --mount=type=cache,target=/app/.next/cache \ + pnpm build + +# Stage 3: Production runtime +FROM node:18-slim AS runner +WORKDIR /app + +ENV NODE_ENV production +ENV NEXT_TELEMETRY_DISABLED 1 + +# Create non-root user for security +RUN addgroup --system --gid 1001 nodejs && \ + adduser --system --uid 1001 nextjs + +# Copy necessary files from builder +COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +# Create data directory for query logs with proper permissions +RUN mkdir -p /app/data && chown -R nextjs:nodejs /app/data + +USER nextjs -# Expose the port the app runs on EXPOSE 3000 -# Start the application -CMD ["pnpm", "start"] \ No newline at end of file +ENV PORT 3000 +ENV HOSTNAME "0.0.0.0" + +CMD ["node", "server.js"] diff --git a/nvidia/txt2kg/assets/deploy/app/arangodb-init/create-database.js b/nvidia/txt2kg/assets/deploy/app/arangodb-init/create-database.js index 57c0812..b3f3ec4 100644 --- a/nvidia/txt2kg/assets/deploy/app/arangodb-init/create-database.js +++ b/nvidia/txt2kg/assets/deploy/app/arangodb-init/create-database.js @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// // ArangoDB initialization script to create the txt2kg database // This script is executed automatically when the ArangoDB container starts diff --git a/nvidia/txt2kg/assets/deploy/app/arangodb-init/init.sh b/nvidia/txt2kg/assets/deploy/app/arangodb-init/init.sh index 196fd19..62bd1cd 100755 --- a/nvidia/txt2kg/assets/deploy/app/arangodb-init/init.sh +++ b/nvidia/txt2kg/assets/deploy/app/arangodb-init/init.sh @@ -1,4 +1,20 @@ #!/bin/bash +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# set -e # Wait for ArangoDB to be ready diff --git a/nvidia/txt2kg/assets/deploy/app/pinecone-init.sh b/nvidia/txt2kg/assets/deploy/app/pinecone-init.sh index 86eb49c..aea4f33 100755 --- a/nvidia/txt2kg/assets/deploy/app/pinecone-init.sh +++ b/nvidia/txt2kg/assets/deploy/app/pinecone-init.sh @@ -1,4 +1,20 @@ #!/bin/sh +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# # Script to initialize Pinecone index at container startup echo "Initializing Pinecone index..." diff --git a/nvidia/txt2kg/assets/deploy/app/qdrant-init.sh b/nvidia/txt2kg/assets/deploy/app/qdrant-init.sh new file mode 100644 index 0000000..b4d4fd4 --- /dev/null +++ b/nvidia/txt2kg/assets/deploy/app/qdrant-init.sh @@ -0,0 +1,68 @@ +#!/bin/sh +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Script to initialize Qdrant collection at container startup +echo "Initializing Qdrant collection..." + +# Wait for the Qdrant service to become available +echo "Waiting for Qdrant service to start..." +max_attempts=30 +attempt=1 + +while [ $attempt -le $max_attempts ]; do + if curl -s http://qdrant:6333/healthz > /dev/null; then + echo "Qdrant service is up!" + break + fi + echo "Waiting for Qdrant service (attempt $attempt/$max_attempts)..." + attempt=$((attempt + 1)) + sleep 2 +done + +if [ $attempt -gt $max_attempts ]; then + echo "Timed out waiting for Qdrant service" + exit 1 +fi + +# Check if collection already exists +echo "Checking if collection 'entity-embeddings' exists..." +COLLECTION_EXISTS=$(curl -s http://qdrant:6333/collections/entity-embeddings | grep -c '"status":"ok"' || echo "0") + +if [ "$COLLECTION_EXISTS" -gt "0" ]; then + echo "Collection 'entity-embeddings' already exists, skipping creation" +else + # Create the collection + echo "Creating collection 'entity-embeddings'..." + curl -X PUT "http://qdrant:6333/collections/entity-embeddings" \ + -H "Content-Type: application/json" \ + -d '{ + "vectors": { + "size": 384, + "distance": "Cosine" + } + }' + + if [ $? -eq 0 ]; then + echo "βœ… Collection 'entity-embeddings' created successfully" + else + echo "❌ Failed to create collection" + exit 1 + fi +fi + +echo "Qdrant initialization complete" diff --git a/nvidia/txt2kg/assets/deploy/compose/docker-compose.yml b/nvidia/txt2kg/assets/deploy/compose/docker-compose.yml index 5916938..07e9e7d 100644 --- a/nvidia/txt2kg/assets/deploy/compose/docker-compose.yml +++ b/nvidia/txt2kg/assets/deploy/compose/docker-compose.yml @@ -1,3 +1,4 @@ + services: app: build: @@ -8,12 +9,18 @@ services: environment: - ARANGODB_URL=http://arangodb:8529 - ARANGODB_DB=txt2kg + - QDRANT_URL=http://qdrant:6333 + - VECTOR_DB_TYPE=qdrant - LANGCHAIN_TRACING_V2=true + - SENTENCE_TRANSFORMER_URL=http://sentence-transformers:80 + - MODEL_NAME=all-MiniLM-L6-v2 + - EMBEDDINGS_API_URL=http://sentence-transformers:80 - GRPC_SSL_CIPHER_SUITES=HIGH+ECDSA:HIGH+aRSA - NODE_TLS_REJECT_UNAUTHORIZED=0 - OLLAMA_BASE_URL=http://ollama:11434/v1 - OLLAMA_MODEL=llama3.1:8b - REMOTE_WEBGPU_SERVICE_URL=http://txt2kg-remote-webgpu:8083 + - NVIDIA_API_KEY=${NVIDIA_API_KEY:-} # Node.js timeout configurations for large model processing - NODE_OPTIONS=--max-http-header-size=80000 - UV_THREADPOOL_SIZE=128 @@ -22,9 +29,12 @@ services: networks: - default - txt2kg-network + - pinecone-net depends_on: - arangodb - ollama + # Optional: sentence-transformers and entity-embeddings are only needed for vector search + # Traditional graph search works without these services arangodb: image: arangodb:latest ports: @@ -58,16 +68,13 @@ services: volumes: - ollama_data:/root/.ollama environment: + - NVIDIA_VISIBLE_DEVICES=all # Make all GPUs visible to the container + - NVIDIA_DRIVER_CAPABILITIES=compute,utility # Required capabilities for CUDA - OLLAMA_FLASH_ATTENTION=1 # Enable flash attention for better performance - OLLAMA_KEEP_ALIVE=30m # Keep models loaded for 30 minutes - - OLLAMA_CUDA=1 # Enable CUDA acceleration - - OLLAMA_LLM_LIBRARY=cuda # Use CUDA library for LLM operations - - OLLAMA_NUM_PARALLEL=1 # Process one request at a time for 70B models + - 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=999 # Use maximum GPU layers - - OLLAMA_GPU_MEMORY_FRACTION=0.9 # Use 90% of GPU memory - - CUDA_VISIBLE_DEVICES=0 # Use GPU 0 (change to 'all' for multi-GPU) networks: - default restart: unless-stopped @@ -79,19 +86,90 @@ services: count: all capabilities: [gpu] healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:11434/api/tags"] + test: ["CMD", "ollama", "list"] interval: 30s timeout: 10s retries: 3 start_period: 60s + + # Optional services for vector search (NOT required for traditional graph search) + # Traditional graph search works with just: app, arangodb, and ollama + sentence-transformers: + build: + context: ../services/sentence-transformers + dockerfile: Dockerfile + ports: + - '8000:80' + environment: + - MODEL_NAME=all-MiniLM-L6-v2 + networks: + - default + restart: unless-stopped + profiles: + - vector-search # Only start with: docker compose --profile vector-search up + qdrant: + image: qdrant/qdrant:latest + container_name: qdrant + ports: + - "6333:6333" + - "6334:6334" + volumes: + - qdrant_data:/qdrant/storage + networks: + - pinecone-net + restart: unless-stopped + profiles: + - vector-search # Only start with: docker compose --profile vector-search up + qdrant-init: + image: curlimages/curl:latest + depends_on: + - qdrant + restart: "no" + entrypoint: /bin/sh + command: + - -c + - | + echo 'Waiting for Qdrant to start...' + sleep 5 + echo 'Checking if entity-embeddings collection exists...' + RESPONSE=$(curl -s http://qdrant:6333/collections/entity-embeddings) + if echo "$RESPONSE" | grep -q '"status":"ok"'; then + echo 'entity-embeddings collection already exists' + else + echo 'Creating collection entity-embeddings...' + curl -X PUT http://qdrant:6333/collections/entity-embeddings \ + -H 'Content-Type: application/json' \ + -d '{"vectors":{"size":384,"distance":"Cosine"}}' + echo '' + echo 'entity-embeddings collection created successfully' + fi + echo 'Checking if document-embeddings collection exists...' + RESPONSE=$(curl -s http://qdrant:6333/collections/document-embeddings) + if echo "$RESPONSE" | grep -q '"status":"ok"'; then + echo 'document-embeddings collection already exists' + else + echo 'Creating collection document-embeddings...' + curl -X PUT http://qdrant:6333/collections/document-embeddings \ + -H 'Content-Type: application/json' \ + -d '{"vectors":{"size":384,"distance":"Cosine"}}' + echo '' + echo 'document-embeddings collection created successfully' + fi + networks: + - pinecone-net + profiles: + - vector-search volumes: arangodb_data: arangodb_apps_data: ollama_data: + qdrant_data: networks: default: driver: bridge txt2kg-network: driver: bridge + pinecone-net: + name: pinecone diff --git a/nvidia/txt2kg/assets/deploy/services/gnn_model/app.py b/nvidia/txt2kg/assets/deploy/services/gnn_model/app.py index fc89eef..5b79d1f 100644 --- a/nvidia/txt2kg/assets/deploy/services/gnn_model/app.py +++ b/nvidia/txt2kg/assets/deploy/services/gnn_model/app.py @@ -1,4 +1,20 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# import os import torch diff --git a/nvidia/txt2kg/assets/deploy/services/gnn_model/client_example.py b/nvidia/txt2kg/assets/deploy/services/gnn_model/client_example.py index 18659a7..da0e7e8 100644 --- a/nvidia/txt2kg/assets/deploy/services/gnn_model/client_example.py +++ b/nvidia/txt2kg/assets/deploy/services/gnn_model/client_example.py @@ -1,4 +1,20 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# import requests import json diff --git a/nvidia/txt2kg/assets/deploy/services/gnn_model/train_export.py b/nvidia/txt2kg/assets/deploy/services/gnn_model/train_export.py index fb76c49..1600644 100644 --- a/nvidia/txt2kg/assets/deploy/services/gnn_model/train_export.py +++ b/nvidia/txt2kg/assets/deploy/services/gnn_model/train_export.py @@ -1,4 +1,20 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# import os import argparse diff --git a/nvidia/txt2kg/assets/deploy/services/gpu-viz/Dockerfile b/nvidia/txt2kg/assets/deploy/services/gpu-viz/Dockerfile index 2d12aff..5f2ac1c 100644 --- a/nvidia/txt2kg/assets/deploy/services/gpu-viz/Dockerfile +++ b/nvidia/txt2kg/assets/deploy/services/gpu-viz/Dockerfile @@ -23,6 +23,7 @@ RUN pip install --no-cache-dir -r requirements.txt # Copy the service code COPY unified_gpu_service.py . +COPY pygraphistry_service.py . # Create a non-root user for security (using a different UID to avoid conflicts) RUN useradd -m -u 1001 appuser && chown -R appuser:appuser /app diff --git a/nvidia/txt2kg/assets/deploy/services/gpu-viz/README.md b/nvidia/txt2kg/assets/deploy/services/gpu-viz/README.md index 9851501..c6fd1d9 100644 --- a/nvidia/txt2kg/assets/deploy/services/gpu-viz/README.md +++ b/nvidia/txt2kg/assets/deploy/services/gpu-viz/README.md @@ -9,11 +9,12 @@ This directory contains optional GPU-accelerated graph visualization services th ## πŸ“¦ Available Services ### 1. Unified GPU Service (`unified_gpu_service.py`) -Provides **Local GPU (cuGraph)** and **CPU (NetworkX)** processing in a single FastAPI service. +Combines **PyGraphistry Cloud** and **Local GPU (cuGraph)** processing into a single FastAPI service. **Processing Modes:** | Mode | Description | Requirements | |------|-------------|--------------| +| **PyGraphistry Cloud** | Interactive GPU embeds in browser | API credentials | | **Local GPU (cuGraph)** | Full GPU processing on your hardware | NVIDIA GPU + cuGraph | | **Local CPU** | NetworkX fallback processing | None | @@ -26,8 +27,9 @@ Local GPU processing service with WebSocket support for real-time updates. ## πŸ› οΈ Setup ### Prerequisites -- NVIDIA GPU with CUDA support (for GPU mode) +- NVIDIA GPU with CUDA support (for GPU modes) - RAPIDS cuGraph (for local GPU processing) +- PyGraphistry account (for cloud mode) ### Installation @@ -92,8 +94,9 @@ Response: ```json { "processing_modes": { - "local_gpu": {"available": true, "description": "Local GPU processing with cuGraph/RAPIDS"}, - "local_cpu": {"available": true, "description": "Local CPU fallback processing with NetworkX"} + "pygraphistry_cloud": {"available": true, "description": "..."}, + "local_gpu": {"available": true, "description": "..."}, + "local_cpu": {"available": true, "description": "..."} }, "has_rapids": true, "gpu_available": true @@ -105,18 +108,33 @@ Response: The txt2kg frontend includes built-in components for GPU visualization: - `UnifiedGPUViewer`: Connects to unified GPU service +- `PyGraphistryViewer`: Direct PyGraphistry cloud integration - `ForceGraphWrapper`: Three.js WebGPU visualization (default) ### Using GPU Services in Frontend The frontend has API routes that can connect to these services: +- `/api/pygraphistry/*`: PyGraphistry integration - `/api/unified-gpu/*`: Unified GPU service integration To use these services, ensure they are running separately and configure the frontend environment variables accordingly. -### Processing Graph Data +### Mode-Specific Processing ```javascript +// PyGraphistry Cloud mode +const response = await fetch('/api/unified-gpu/visualize', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + graph_data: { nodes, links }, + processing_mode: 'pygraphistry_cloud', + layout_type: 'force', + clustering: true, + gpu_acceleration: true + }) +}) + // Local GPU mode const response = await fetch('/api/unified-gpu/visualize', { method: 'POST', @@ -129,20 +147,15 @@ const response = await fetch('/api/unified-gpu/visualize', { compute_centrality: true }) }) - -// Local CPU mode -const response = await fetch('/api/unified-gpu/visualize', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - graph_data: { nodes, links }, - processing_mode: 'local_cpu' - }) -}) ``` ## πŸ”§ Configuration Options +### PyGraphistry Cloud Mode +- `layout_type`: "force", "circular", "hierarchical" +- `gpu_acceleration`: true/false +- `clustering`: true/false + ### Local GPU Mode - `layout_algorithm`: "force_atlas2", "spectral", "fruchterman_reingold" - `clustering_algorithm`: "leiden", "louvain", "spectral" @@ -159,7 +172,8 @@ const response = await fetch('/api/unified-gpu/visualize', { "processed_nodes": [...], "processed_edges": [...], "processing_mode": "local_gpu", - "layout_positions": {...}, + "embed_url": "https://hub.graphistry.com/...", // Only for cloud mode + "layout_positions": {...}, // Only for local GPU mode "clusters": {...}, "centrality": {...}, "stats": { @@ -173,17 +187,18 @@ const response = await fetch('/api/unified-gpu/visualize', { } ``` -## πŸš€ Benefits +## πŸš€ Benefits of Unified Approach ### βœ… Advantages - **Single service** - One port, one deployment - **Mode switching** - Choose best processing per graph - **Fallback handling** - Graceful degradation if GPU unavailable - **Consistent API** - Same interface for all modes -- **No GPL dependencies** - All dependencies are permissively licensed +- **Better testing** - Easy comparison between modes ### 🎯 Use Cases -- **Local GPU**: Private data, large-scale processing, GPU-accelerated algorithms +- **PyGraphistry Cloud**: Sharing visualizations, demos, production embeds +- **Local GPU**: Private data, large-scale processing, custom algorithms - **Local CPU**: Development, testing, small graphs ## πŸ› Troubleshooting @@ -197,6 +212,16 @@ nvidia-smi python -c "import cudf, cugraph; print('RAPIDS OK')" ``` +### PyGraphistry Credentials +```bash +# Verify credentials are set +echo $GRAPHISTRY_PERSONAL_KEY +echo $GRAPHISTRY_SECRET_KEY + +# Test connection +python -c "import graphistry; graphistry.register(personal_key_id='$GRAPHISTRY_PERSONAL_KEY', personal_key_secret='$GRAPHISTRY_SECRET_KEY'); print('PyGraphistry OK')" +``` + ### Service Health ```bash curl http://localhost:8080/api/health @@ -204,13 +229,7 @@ curl http://localhost:8080/api/health ## πŸ“ˆ Performance Tips -1. **Large graphs (>100k nodes)**: Use `local_gpu` mode with RAPIDS cuGraph -2. **Development**: Use `local_cpu` mode for speed and simplicity -3. **Mixed workloads**: Switch modes dynamically based on graph size and GPU availability - -## πŸ“ License Compliance - -This service has been updated to remove all GPL-licensed dependencies: -- ❌ Removed: `igraph` (GPL v2+) -- ❌ Removed: `graphistry` with `compute_igraph` (uses igraph internally) -- βœ… Uses only: NetworkX (BSD), cuGraph (Apache 2.0), NumPy (BSD), pandas (BSD) \ No newline at end of file +1. **Large graphs (>100k nodes)**: Use `local_gpu` mode +2. **Sharing/demos**: Use `pygraphistry_cloud` mode +3. **Development**: Use `local_cpu` mode for speed +4. **Mixed workloads**: Switch modes dynamically based on graph size \ No newline at end of file diff --git a/nvidia/txt2kg/assets/deploy/services/gpu-viz/local_gpu_viz_service.py b/nvidia/txt2kg/assets/deploy/services/gpu-viz/local_gpu_viz_service.py index 34197fe..359891c 100644 --- a/nvidia/txt2kg/assets/deploy/services/gpu-viz/local_gpu_viz_service.py +++ b/nvidia/txt2kg/assets/deploy/services/gpu-viz/local_gpu_viz_service.py @@ -1,3 +1,19 @@ +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# import os import json import numpy as np diff --git a/nvidia/txt2kg/assets/deploy/services/gpu-viz/pygraphistry_service.py b/nvidia/txt2kg/assets/deploy/services/gpu-viz/pygraphistry_service.py new file mode 100644 index 0000000..cb88bfb --- /dev/null +++ b/nvidia/txt2kg/assets/deploy/services/gpu-viz/pygraphistry_service.py @@ -0,0 +1,728 @@ +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import graphistry +import pandas as pd +import numpy as np +from typing import Dict, List, Any, Optional +import asyncio +import json +from datetime import datetime +import logging +from fastapi import FastAPI, HTTPException, BackgroundTasks +from pydantic import BaseModel +import uvicorn +import os +import time +from concurrent.futures import ThreadPoolExecutor +import networkx as nx +from enum import Enum + +# Configure logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# Initialize PyGraphistry +def init_graphistry(): + """Initialize PyGraphistry with GPU acceleration""" + try: + # Set up authentication - check for different credential types + api_key = os.getenv('GRAPHISTRY_API_KEY') + personal_key = os.getenv('GRAPHISTRY_PERSONAL_KEY') + secret_key = os.getenv('GRAPHISTRY_SECRET_KEY') + username = os.getenv('GRAPHISTRY_USERNAME') + password = os.getenv('GRAPHISTRY_PASSWORD') + + if personal_key and secret_key: + # Configure for cloud API with personal key and secret + graphistry.register( + api=3, + protocol="https", + server="hub.graphistry.com", + personal_key_id=personal_key, + personal_key_secret=secret_key + ) + logger.info("PyGraphistry initialized with personal key/secret for cloud GPU acceleration") + return True + elif api_key: + # Configure for cloud API with API key + graphistry.register(api=3, protocol="https", server="hub.graphistry.com", api_key=api_key) + logger.info("PyGraphistry initialized with API key for cloud GPU acceleration") + return True + elif username and password: + # Configure for cloud API with username/password + graphistry.register(api=3, protocol="https", server="hub.graphistry.com", + username=username, password=password) + logger.info("PyGraphistry initialized with username/password for cloud GPU acceleration") + return True + else: + # Configure for local mode + graphistry.register(api=3) + logger.info("PyGraphistry initialized in local CPU mode") + return True + + except Exception as e: + logger.error(f"Failed to initialize PyGraphistry: {e}") + return False + +class GraphPattern(str, Enum): + RANDOM = "random" + SCALE_FREE = "scale-free" + SMALL_WORLD = "small-world" + CLUSTERED = "clustered" + HIERARCHICAL = "hierarchical" + GRID = "grid" + +class GraphData(BaseModel): + nodes: List[Dict[str, Any]] + links: List[Dict[str, Any]] + +class GraphGenerationRequest(BaseModel): + num_nodes: int + pattern: GraphPattern = GraphPattern.SCALE_FREE + avg_degree: Optional[int] = 5 + num_clusters: Optional[int] = 100 + small_world_k: Optional[int] = 6 + small_world_p: Optional[float] = 0.1 + grid_dimensions: Optional[List[int]] = [100, 100] + seed: Optional[int] = None + +class VisualizationRequest(BaseModel): + graph_data: GraphData + layout_type: Optional[str] = "force" + gpu_acceleration: Optional[bool] = True + clustering: Optional[bool] = False + node_size_attribute: Optional[str] = None + node_color_attribute: Optional[str] = None + edge_weight_attribute: Optional[str] = None + +class GraphGenerationStatus(BaseModel): + task_id: str + status: str # "running", "completed", "failed" + progress: float + message: str + result: Optional[Dict[str, Any]] = None + error: Optional[str] = None + +class LargeGraphGenerator: + """Optimized graph generation using NetworkX and NumPy for performance""" + + @staticmethod + def generate_random_graph(num_nodes: int, avg_degree: int = 5, seed: Optional[int] = None) -> GraphData: + """Generate random graph using ErdΕ‘s–RΓ©nyi model""" + if seed: + np.random.seed(seed) + + # Calculate edge probability for desired average degree + p = avg_degree / (num_nodes - 1) + + # Use NetworkX for efficient generation + G = nx.erdos_renyi_graph(num_nodes, p, seed=seed) + + return LargeGraphGenerator._networkx_to_graphdata(G) + + @staticmethod + def generate_scale_free_graph(num_nodes: int, m: int = 3, seed: Optional[int] = None) -> GraphData: + """Generate scale-free graph using BarabΓ‘si–Albert model""" + G = nx.barabasi_albert_graph(num_nodes, m, seed=seed) + return LargeGraphGenerator._networkx_to_graphdata(G) + + @staticmethod + def generate_small_world_graph(num_nodes: int, k: int = 6, p: float = 0.1, seed: Optional[int] = None) -> GraphData: + """Generate small-world graph using Watts-Strogatz model""" + G = nx.watts_strogatz_graph(num_nodes, k, p, seed=seed) + return LargeGraphGenerator._networkx_to_graphdata(G) + + @staticmethod + def generate_clustered_graph(num_nodes: int, num_clusters: int = 100, seed: Optional[int] = None) -> GraphData: + """Generate clustered graph with intra and inter-cluster connections""" + if seed: + np.random.seed(seed) + + cluster_size = num_nodes // num_clusters + G = nx.Graph() + + # Add nodes with cluster information + for i in range(num_nodes): + cluster_id = i // cluster_size + G.add_node(i, cluster=cluster_id) + + # Generate intra-cluster edges + intra_prob = 0.1 + for cluster in range(num_clusters): + cluster_start = cluster * cluster_size + cluster_end = min(cluster_start + cluster_size, num_nodes) + cluster_nodes = list(range(cluster_start, cluster_end)) + + # Create subgraph for cluster + cluster_subgraph = nx.erdos_renyi_graph(len(cluster_nodes), intra_prob) + + # Add edges to main graph with proper node mapping + for edge in cluster_subgraph.edges(): + G.add_edge(cluster_nodes[edge[0]], cluster_nodes[edge[1]]) + + # Generate inter-cluster edges + inter_prob = 0.001 + for i in range(num_nodes): + for j in range(i + 1, num_nodes): + if G.nodes[i].get('cluster') != G.nodes[j].get('cluster'): + if np.random.random() < inter_prob: + G.add_edge(i, j) + + return LargeGraphGenerator._networkx_to_graphdata(G) + + @staticmethod + def generate_hierarchical_graph(num_nodes: int, branching_factor: int = 3, seed: Optional[int] = None) -> GraphData: + """Generate hierarchical (tree-like) graph""" + G = nx.random_tree(num_nodes, seed=seed) + + # Add some cross-links to make it more interesting + if seed: + np.random.seed(seed) + + # Add 10% additional edges for cross-connections + num_additional_edges = max(1, num_nodes // 10) + nodes = list(G.nodes()) + + for _ in range(num_additional_edges): + u, v = np.random.choice(nodes, 2, replace=False) + if not G.has_edge(u, v): + G.add_edge(u, v) + + return LargeGraphGenerator._networkx_to_graphdata(G) + + @staticmethod + def generate_grid_graph(dimensions: List[int], seed: Optional[int] = None) -> GraphData: + """Generate 2D or 3D grid graph""" + if len(dimensions) == 2: + G = nx.grid_2d_graph(dimensions[0], dimensions[1]) + elif len(dimensions) == 3: + G = nx.grid_graph(dimensions) + else: + raise ValueError("Grid dimensions must be 2D or 3D") + + # Convert coordinate tuples to integer node IDs + mapping = {node: i for i, node in enumerate(G.nodes())} + G = nx.relabel_nodes(G, mapping) + + return LargeGraphGenerator._networkx_to_graphdata(G) + + @staticmethod + def _networkx_to_graphdata(G: nx.Graph) -> GraphData: + """Convert NetworkX graph to GraphData format""" + nodes = [] + links = [] + + # Convert nodes + for node_id in G.nodes(): + node_data = G.nodes[node_id] + node = { + "id": f"n{node_id}", + "name": f"Node {node_id}", + "val": np.random.randint(1, 11), + "degree": G.degree(node_id) + } + + # Add cluster information if available + if 'cluster' in node_data: + node['group'] = f"cluster_{node_data['cluster']}" + else: + node['group'] = f"group_{node_id % 10}" + + nodes.append(node) + + # Convert edges + for edge in G.edges(): + link = { + "source": f"n{edge[0]}", + "target": f"n{edge[1]}", + "name": f"link_{edge[0]}_{edge[1]}", + "weight": np.random.uniform(0.1, 5.0) + } + links.append(link) + + return GraphData(nodes=nodes, links=links) + +class PyGraphistryService: + def __init__(self): + self.initialized = init_graphistry() + self.generation_tasks = {} # Store background tasks + self.executor = ThreadPoolExecutor(max_workers=4) + + async def generate_graph_async(self, request: GraphGenerationRequest, task_id: str): + """Generate graph asynchronously""" + try: + self.generation_tasks[task_id] = GraphGenerationStatus( + task_id=task_id, + status="running", + progress=0.0, + message="Starting graph generation..." + ) + + start_time = time.time() + + # Update progress + self.generation_tasks[task_id].progress = 10.0 + self.generation_tasks[task_id].message = f"Generating {request.pattern.value} graph with {request.num_nodes} nodes..." + + # Generate graph based on pattern + if request.pattern == GraphPattern.RANDOM: + graph_data = LargeGraphGenerator.generate_random_graph( + request.num_nodes, request.avg_degree, request.seed + ) + elif request.pattern == GraphPattern.SCALE_FREE: + m = min(request.avg_degree, request.num_nodes - 1) if request.avg_degree else 3 + graph_data = LargeGraphGenerator.generate_scale_free_graph( + request.num_nodes, m, request.seed + ) + elif request.pattern == GraphPattern.SMALL_WORLD: + graph_data = LargeGraphGenerator.generate_small_world_graph( + request.num_nodes, + request.small_world_k or 6, + request.small_world_p or 0.1, + request.seed + ) + elif request.pattern == GraphPattern.CLUSTERED: + graph_data = LargeGraphGenerator.generate_clustered_graph( + request.num_nodes, request.num_clusters or 100, request.seed + ) + elif request.pattern == GraphPattern.HIERARCHICAL: + graph_data = LargeGraphGenerator.generate_hierarchical_graph( + request.num_nodes, seed=request.seed + ) + elif request.pattern == GraphPattern.GRID: + # Calculate grid dimensions for given number of nodes + if request.grid_dimensions: + dimensions = request.grid_dimensions + else: + side_length = int(np.sqrt(request.num_nodes)) + dimensions = [side_length, side_length] + graph_data = LargeGraphGenerator.generate_grid_graph(dimensions, request.seed) + else: + raise ValueError(f"Unknown graph pattern: {request.pattern}") + + # Update progress + self.generation_tasks[task_id].progress = 80.0 + self.generation_tasks[task_id].message = "Computing graph statistics..." + + # Calculate statistics + generation_time = time.time() - start_time + stats = { + "node_count": len(graph_data.nodes), + "edge_count": len(graph_data.links), + "generation_time": generation_time, + "density": len(graph_data.links) / (len(graph_data.nodes) * (len(graph_data.nodes) - 1) / 2) if len(graph_data.nodes) > 1 else 0, + "avg_degree": 2 * len(graph_data.links) / len(graph_data.nodes) if len(graph_data.nodes) > 0 else 0, + "pattern": request.pattern.value, + "parameters": request.model_dump() + } + + # Complete task + self.generation_tasks[task_id].status = "completed" + self.generation_tasks[task_id].progress = 100.0 + self.generation_tasks[task_id].message = f"Generated {stats['node_count']} nodes and {stats['edge_count']} edges in {generation_time:.2f}s" + self.generation_tasks[task_id].result = { + "graph_data": graph_data.model_dump(), + "stats": stats + } + + logger.info(f"Graph generation completed for task {task_id}: {stats}") + + except Exception as e: + logger.error(f"Graph generation failed for task {task_id}: {e}") + self.generation_tasks[task_id].status = "failed" + self.generation_tasks[task_id].error = str(e) + self.generation_tasks[task_id].message = f"Generation failed: {e}" + + async def start_graph_generation(self, request: GraphGenerationRequest) -> str: + """Start graph generation as background task""" + task_id = f"gen_{int(time.time() * 1000)}" + + # Run generation in thread pool to avoid blocking + loop = asyncio.get_event_loop() + loop.run_in_executor( + self.executor, + lambda: asyncio.run(self.generate_graph_async(request, task_id)) + ) + + return task_id + + def get_generation_status(self, task_id: str) -> Optional[GraphGenerationStatus]: + """Get status of graph generation task""" + return self.generation_tasks.get(task_id) + + async def process_graph_data(self, request: VisualizationRequest) -> Dict[str, Any]: + """Process graph data with PyGraphistry GPU acceleration""" + try: + if not self.initialized: + raise HTTPException(status_code=500, detail="PyGraphistry not initialized") + + # Convert to pandas DataFrames for PyGraphistry + nodes_df = pd.DataFrame(request.graph_data.nodes) + edges_df = pd.DataFrame(request.graph_data.links) + + # Ensure required columns exist + if 'id' not in nodes_df.columns: + nodes_df['id'] = nodes_df.index + if 'source' not in edges_df.columns or 'target' not in edges_df.columns: + raise HTTPException(status_code=400, detail="Links must have source and target columns") + + logger.info(f"Processing graph with {len(nodes_df)} nodes and {len(edges_df)} edges") + + # Create PyGraphistry graph object + try: + g = graphistry.edges(edges_df, 'source', 'target').nodes(nodes_df, 'id') + logger.info(f"Created PyGraphistry graph object") + except Exception as e: + logger.error(f"Failed to create PyGraphistry graph: {e}") + raise HTTPException(status_code=500, detail=f"Graph creation failed: {e}") + + # Apply GPU-accelerated processing + if request.gpu_acceleration: + g = await self._apply_gpu_acceleration(g, request) + + # Apply clustering if requested + if request.clustering: + g = await self._apply_clustering(g) + + # Generate layout + g = await self._generate_layout(g, request.layout_type) + + # Extract processed data + try: + processed_nodes = g._nodes.to_dict('records') if g._nodes is not None else nodes_df.to_dict('records') + processed_edges = g._edges.to_dict('records') if g._edges is not None else edges_df.to_dict('records') + logger.info(f"Extracted {len(processed_nodes)} nodes and {len(processed_edges)} edges") + except Exception as e: + logger.warning(f"Data extraction failed, using original data: {e}") + processed_nodes = nodes_df.to_dict('records') + processed_edges = edges_df.to_dict('records') + + # Generate embedding URL for interactive visualization + embed_url = None + local_viz_data = None + + try: + embed_url = g.plot(render=False) + logger.info(f"Generated PyGraphistry embed URL: {embed_url}") + except Exception as e: + logger.warning(f"Could not generate embed URL (likely running in local mode): {e}") + + # Create local visualization data as fallback + try: + local_viz_data = self._create_local_viz_data(g, processed_nodes, processed_edges) + logger.info("Generated local visualization data as fallback") + except Exception as viz_e: + logger.warning(f"Could not generate local visualization data: {viz_e}") + + return { + "processed_nodes": processed_nodes, + "processed_edges": processed_edges, + "embed_url": embed_url, + "local_viz_data": local_viz_data, + "stats": { + "node_count": len(processed_nodes), + "edge_count": len(processed_edges), + "gpu_accelerated": request.gpu_acceleration, + "clustered": request.clustering, + "layout_type": request.layout_type, + "has_embed_url": embed_url is not None, + "has_local_viz": local_viz_data is not None + }, + "timestamp": datetime.now().isoformat() + } + + except Exception as e: + logger.error(f"Error processing graph data: {e}") + raise HTTPException(status_code=500, detail=str(e)) + + async def _apply_gpu_acceleration(self, g, request: VisualizationRequest): + """Apply GPU acceleration using PyGraphistry's vector processing""" + try: + if not request.gpu_acceleration: + logger.info("GPU acceleration disabled by request") + return g + + logger.info("=== GPU ACCELERATION ATTEMPT ===") + logger.info(f"PyGraphistry object type: {type(g)}") + logger.info(f"Available methods: {[method for method in dir(g) if not method.startswith('_')]}") + + # Check what GPU methods are actually available + has_compute_igraph = hasattr(g, 'compute_igraph') + has_umap = hasattr(g, 'umap') + logger.info(f"Has compute_igraph: {has_compute_igraph}") + logger.info(f"Has UMAP: {has_umap}") + + gpu_operations_successful = 0 + total_gpu_operations = 0 + + # Compute centrality measures if available + total_gpu_operations += 1 + try: + if has_compute_igraph and len(g._nodes) < 50000: # Limit for performance + logger.info("Attempting PageRank computation...") + g = g.compute_igraph('pagerank', out_col='pagerank') + logger.info("βœ“ SUCCESS: Computed PageRank centrality with GPU") + gpu_operations_successful += 1 + else: + reason = "too many nodes" if len(g._nodes) >= 50000 else "compute_igraph not available" + logger.warning(f"βœ— SKIPPED: PageRank computation ({reason})") + except Exception as e: + logger.warning(f"βœ— FAILED: PageRank computation failed: {e}") + + # Apply UMAP for node positioning if available and beneficial + total_gpu_operations += 1 + try: + if has_umap and len(g._nodes) > 100 and len(g._nodes) < 10000: + logger.info("Attempting UMAP for node positioning...") + g = g.umap() + logger.info("βœ“ SUCCESS: Applied UMAP for node positioning") + gpu_operations_successful += 1 + else: + reason = ("UMAP not available" if not has_umap else + "too few nodes" if len(g._nodes) <= 100 else "too many nodes") + logger.warning(f"βœ— SKIPPED: UMAP processing ({reason})") + except Exception as e: + logger.warning(f"βœ— FAILED: UMAP processing failed: {e}") + + logger.info(f"=== GPU ACCELERATION SUMMARY ===") + logger.info(f"GPU operations successful: {gpu_operations_successful}/{total_gpu_operations}") + logger.info(f"GPU utilization: {(gpu_operations_successful/total_gpu_operations)*100:.1f}%") + + return g + except Exception as e: + logger.warning(f"GPU acceleration failed completely, falling back to CPU: {e}") + return g + + async def _apply_clustering(self, g): + """Apply GPU-accelerated clustering""" + try: + logger.info("=== CLUSTERING ATTEMPT ===") + + # Use PyGraphistry's built-in clustering if available + if hasattr(g, 'compute_igraph') and len(g._nodes) < 20000: # Limit for performance + logger.info("Attempting Leiden community detection...") + try: + g = g.compute_igraph('community_leiden', out_col='cluster') + logger.info("βœ“ SUCCESS: Applied Leiden community detection") + return g + except Exception as e: + logger.warning(f"βœ— FAILED: Leiden clustering failed: {e}") + logger.info("Attempting Louvain community detection as fallback...") + try: + g = g.compute_igraph('community_louvain', out_col='cluster') + logger.info("βœ“ SUCCESS: Applied Louvain community detection") + return g + except Exception as e2: + logger.warning(f"βœ— FAILED: Louvain clustering also failed: {e2}") + else: + reason = "too many nodes" if len(g._nodes) >= 20000 else "compute_igraph not available" + logger.warning(f"βœ— SKIPPED: Clustering ({reason})") + + logger.info("=== CLUSTERING SUMMARY: No clustering applied ===") + return g + except Exception as e: + logger.warning(f"Clustering failed completely: {e}") + return g + + async def _generate_layout(self, g, layout_type: str = "force"): + """Generate layout using PyGraphistry's algorithms""" + try: + logger.info(f"Generating {layout_type} layout") + + # Only apply layout computation for reasonable graph sizes + if len(g._nodes) > 50000: + logger.info("Skipping layout computation for very large graph") + return g + + if hasattr(g, 'compute_igraph'): + try: + if layout_type == "force": + g = g.compute_igraph('layout_fruchterman_reingold', out_cols=['x', 'y']) + logger.info("Applied Fruchterman-Reingold force layout") + elif layout_type == "circular": + g = g.compute_igraph('layout_circle', out_cols=['x', 'y']) + logger.info("Applied circular layout") + elif layout_type == "hierarchical": + g = g.compute_igraph('layout_sugiyama', out_cols=['x', 'y']) + logger.info("Applied hierarchical layout") + else: + # Default to force-directed + g = g.compute_igraph('layout_fruchterman_reingold', out_cols=['x', 'y']) + logger.info("Applied default force layout") + except Exception as e: + logger.warning(f"Layout computation failed: {e}") + else: + logger.info("Layout computation not available, using default positioning") + + return g + except Exception as e: + logger.warning(f"Layout generation failed: {e}") + return g + + def _create_local_viz_data(self, g, processed_nodes: List[Dict], processed_edges: List[Dict]) -> Dict[str, Any]: + """Create local visualization data when embed URL cannot be generated""" + try: + # Extract layout positions if available + positions = {} + if g._nodes is not None and 'x' in g._nodes.columns and 'y' in g._nodes.columns: + for _, row in g._nodes.iterrows(): + node_id = row.get('id', row.name) + positions[str(node_id)] = { + 'x': float(row['x']) if pd.notna(row['x']) else 0, + 'y': float(row['y']) if pd.notna(row['y']) else 0 + } + + # Add cluster information if available + clusters = {} + if g._nodes is not None and 'cluster' in g._nodes.columns: + for _, row in g._nodes.iterrows(): + node_id = row.get('id', row.name) + if pd.notna(row['cluster']): + clusters[str(node_id)] = int(row['cluster']) + + # Create enhanced nodes with layout and cluster info + enhanced_nodes = [] + for node in processed_nodes: + enhanced_node = node.copy() + node_id = str(node.get('id', '')) + + if node_id in positions: + enhanced_node.update(positions[node_id]) + + if node_id in clusters: + enhanced_node['cluster'] = clusters[node_id] + + enhanced_nodes.append(enhanced_node) + + return { + "nodes": enhanced_nodes, + "edges": processed_edges, + "positions": positions, + "clusters": clusters, + "layout_computed": len(positions) > 0, + "clusters_computed": len(clusters) > 0 + } + + except Exception as e: + logger.error(f"Failed to create local visualization data: {e}") + return { + "nodes": processed_nodes, + "edges": processed_edges, + "positions": {}, + "clusters": {}, + "layout_computed": False, + "clusters_computed": False + } + + async def get_graph_stats(self, graph_data: GraphData) -> Dict[str, Any]: + """Get GPU-accelerated graph statistics""" + try: + nodes_df = pd.DataFrame(graph_data.nodes) + edges_df = pd.DataFrame(graph_data.links) + + g = graphistry.edges(edges_df, 'source', 'target').nodes(nodes_df, 'id') + + # Compute various graph metrics using GPU acceleration + stats = { + "node_count": len(nodes_df), + "edge_count": len(edges_df), + "density": len(edges_df) / (len(nodes_df) * (len(nodes_df) - 1)) if len(nodes_df) > 1 else 0, + "timestamp": datetime.now().isoformat() + } + + # Add centrality measures if possible + try: + if len(nodes_df) < 10000 and hasattr(g, 'compute_igraph'): # Only for reasonably sized graphs + g_with_metrics = g.compute_igraph('pagerank', out_col='pagerank') + + if g_with_metrics._nodes is not None and 'pagerank' in g_with_metrics._nodes.columns: + pagerank_data = g_with_metrics._nodes['pagerank'].to_list() + stats.update({ + "avg_pagerank": float(np.mean(pagerank_data)), + "max_pagerank": float(np.max(pagerank_data)) + }) + logger.info("Computed PageRank statistics") + except Exception as e: + logger.warning(f"Could not compute centrality measures: {e}") + + return stats + + except Exception as e: + logger.error(f"Error computing graph stats: {e}") + raise HTTPException(status_code=500, detail=str(e)) + +# FastAPI app +app = FastAPI(title="PyGraphistry GPU Visualization Service", version="1.0.0") +service = PyGraphistryService() + +@app.post("/api/generate") +async def generate_graph(request: GraphGenerationRequest): + """Start graph generation as background task""" + if request.num_nodes > 1000000: + raise HTTPException(status_code=400, detail="Maximum 1 million nodes allowed") + + task_id = await service.start_graph_generation(request) + return {"task_id": task_id, "status": "started"} + +@app.get("/api/generate/{task_id}") +async def get_generation_status(task_id: str): + """Get status of graph generation task""" + status = service.get_generation_status(task_id) + if not status: + raise HTTPException(status_code=404, detail="Task not found") + return status + +@app.post("/api/visualize") +async def visualize_graph(request: VisualizationRequest): + """Process graph data with PyGraphistry GPU acceleration""" + return await service.process_graph_data(request) + +@app.post("/api/stats") +async def get_graph_statistics(graph_data: GraphData): + """Get GPU-accelerated graph statistics""" + return await service.get_graph_stats(graph_data) + +@app.get("/api/health") +async def health_check(): + """Health check endpoint""" + return { + "status": "healthy", + "pygraphistry_initialized": service.initialized, + "timestamp": datetime.now().isoformat() + } + +@app.get("/api/patterns") +async def get_available_patterns(): + """Get list of available graph generation patterns""" + return { + "patterns": [ + { + "name": pattern.value, + "description": { + GraphPattern.RANDOM: "Random graph using ErdΕ‘s–RΓ©nyi model", + GraphPattern.SCALE_FREE: "Scale-free graph using BarabΓ‘si–Albert model", + GraphPattern.SMALL_WORLD: "Small-world graph using Watts-Strogatz model", + GraphPattern.CLUSTERED: "Clustered graph with community structure", + GraphPattern.HIERARCHICAL: "Hierarchical tree-like graph with cross-links", + GraphPattern.GRID: "2D or 3D grid graph" + }[pattern] + } for pattern in GraphPattern + ] + } + +if __name__ == "__main__": + uvicorn.run(app, host="0.0.0.0", port=8080) \ No newline at end of file diff --git a/nvidia/txt2kg/assets/deploy/services/gpu-viz/remote_gpu_rendering_service.py b/nvidia/txt2kg/assets/deploy/services/gpu-viz/remote_gpu_rendering_service.py index 7b820df..5145bec 100644 --- a/nvidia/txt2kg/assets/deploy/services/gpu-viz/remote_gpu_rendering_service.py +++ b/nvidia/txt2kg/assets/deploy/services/gpu-viz/remote_gpu_rendering_service.py @@ -1,4 +1,20 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# """ Remote GPU Rendering Service diff --git a/nvidia/txt2kg/assets/deploy/services/gpu-viz/remote_webgpu_clustering_service.py b/nvidia/txt2kg/assets/deploy/services/gpu-viz/remote_webgpu_clustering_service.py index ec16754..4582191 100644 --- a/nvidia/txt2kg/assets/deploy/services/gpu-viz/remote_webgpu_clustering_service.py +++ b/nvidia/txt2kg/assets/deploy/services/gpu-viz/remote_webgpu_clustering_service.py @@ -1,4 +1,20 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# """ Remote WebGPU Clustering Service - CuPy Version with Semantic Clustering diff --git a/nvidia/txt2kg/assets/deploy/services/gpu-viz/remote_webgpu_clustering_service_cupy.py b/nvidia/txt2kg/assets/deploy/services/gpu-viz/remote_webgpu_clustering_service_cupy.py index a1a5cd5..2f69d46 100644 --- a/nvidia/txt2kg/assets/deploy/services/gpu-viz/remote_webgpu_clustering_service_cupy.py +++ b/nvidia/txt2kg/assets/deploy/services/gpu-viz/remote_webgpu_clustering_service_cupy.py @@ -1,4 +1,20 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# """ Remote WebGPU Clustering Service - CuPy Version diff --git a/nvidia/txt2kg/assets/deploy/services/gpu-viz/requirements.txt b/nvidia/txt2kg/assets/deploy/services/gpu-viz/requirements.txt index a1e53d8..ef16d7a 100644 --- a/nvidia/txt2kg/assets/deploy/services/gpu-viz/requirements.txt +++ b/nvidia/txt2kg/assets/deploy/services/gpu-viz/requirements.txt @@ -1,3 +1,4 @@ +graphistry>=0.32.0 pandas>=2.0.0 numpy>=1.24.0 fastapi>=0.104.0 @@ -6,6 +7,7 @@ pydantic>=2.0.0 networkx>=3.0 # For efficient graph generation algorithms # cudf, cuml, cugraph are already included in PyG container # cupy>=12.0.0 # Already included in PyG container +igraph>=0.10.0 # For additional graph algorithms scikit-learn>=1.3.0 # For additional ML features requests>=2.31.0 aiofiles>=23.0.0 diff --git a/nvidia/txt2kg/assets/deploy/services/gpu-viz/semantic_clustering_service.py b/nvidia/txt2kg/assets/deploy/services/gpu-viz/semantic_clustering_service.py index ea1733c..667d284 100644 --- a/nvidia/txt2kg/assets/deploy/services/gpu-viz/semantic_clustering_service.py +++ b/nvidia/txt2kg/assets/deploy/services/gpu-viz/semantic_clustering_service.py @@ -1,3 +1,19 @@ +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# """ Semantic Clustering Service for Knowledge Graphs Groups nodes by semantic similarity of names, types, and content rather than just spatial coordinates diff --git a/nvidia/txt2kg/assets/deploy/services/gpu-viz/simple_webgpu_test.py b/nvidia/txt2kg/assets/deploy/services/gpu-viz/simple_webgpu_test.py index 6da720f..3e683f0 100644 --- a/nvidia/txt2kg/assets/deploy/services/gpu-viz/simple_webgpu_test.py +++ b/nvidia/txt2kg/assets/deploy/services/gpu-viz/simple_webgpu_test.py @@ -1,4 +1,20 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# """ Simple WebGPU clustering test service Minimal implementation to test basic functionality diff --git a/nvidia/txt2kg/assets/deploy/services/gpu-viz/start_remote_gpu_services.sh b/nvidia/txt2kg/assets/deploy/services/gpu-viz/start_remote_gpu_services.sh index cafd438..c0d61a1 100755 --- a/nvidia/txt2kg/assets/deploy/services/gpu-viz/start_remote_gpu_services.sh +++ b/nvidia/txt2kg/assets/deploy/services/gpu-viz/start_remote_gpu_services.sh @@ -1,4 +1,20 @@ #!/bin/bash +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# # Start Remote GPU Rendering Services # This script starts the custom remote GPU rendering service as an alternative to PyGraphistry cloud diff --git a/nvidia/txt2kg/assets/deploy/services/gpu-viz/stop_remote_gpu_services.sh b/nvidia/txt2kg/assets/deploy/services/gpu-viz/stop_remote_gpu_services.sh index 8901987..a2502e9 100755 --- a/nvidia/txt2kg/assets/deploy/services/gpu-viz/stop_remote_gpu_services.sh +++ b/nvidia/txt2kg/assets/deploy/services/gpu-viz/stop_remote_gpu_services.sh @@ -1,4 +1,20 @@ #!/bin/bash +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# # Stop Remote GPU Rendering Services diff --git a/nvidia/txt2kg/assets/deploy/services/gpu-viz/unified_gpu_service.py b/nvidia/txt2kg/assets/deploy/services/gpu-viz/unified_gpu_service.py index 624e583..3107ceb 100644 --- a/nvidia/txt2kg/assets/deploy/services/gpu-viz/unified_gpu_service.py +++ b/nvidia/txt2kg/assets/deploy/services/gpu-viz/unified_gpu_service.py @@ -1,8 +1,25 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# """ Unified GPU Graph Visualization Service -Provides local GPU processing with cuGraph and CPU fallback with NetworkX. +Combines PyGraphistry cloud processing and local GPU processing with cuGraph +into a single FastAPI service for maximum flexibility. """ import os @@ -22,6 +39,9 @@ from concurrent.futures import ThreadPoolExecutor import networkx as nx from enum import Enum +# PyGraphistry imports +import graphistry + # GPU-accelerated imports (available in NVIDIA PyG container) try: import cudf @@ -48,6 +68,7 @@ logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) class ProcessingMode(str, Enum): + PYGRAPHISTRY_CLOUD = "pygraphistry_cloud" LOCAL_GPU = "local_gpu" LOCAL_CPU = "local_cpu" @@ -75,7 +96,12 @@ class GraphGenerationRequest(BaseModel): class UnifiedVisualizationRequest(BaseModel): graph_data: GraphData - processing_mode: ProcessingMode = ProcessingMode.LOCAL_GPU + processing_mode: ProcessingMode = ProcessingMode.PYGRAPHISTRY_CLOUD + + # PyGraphistry Cloud options + layout_type: Optional[str] = "force" + gpu_acceleration: Optional[bool] = True + clustering: Optional[bool] = False # Local GPU options layout_algorithm: Optional[str] = "force_atlas2" @@ -90,144 +116,8 @@ class GraphGenerationStatus(BaseModel): result: Optional[Dict[str, Any]] = None error: Optional[str] = None -class LargeGraphGenerator: - """Optimized graph generation using NetworkX and NumPy for performance""" - - @staticmethod - def generate_random_graph(num_nodes: int, avg_degree: int = 5, seed: Optional[int] = None) -> GraphData: - """Generate random graph using ErdΕ‘s–RΓ©nyi model""" - if seed: - np.random.seed(seed) - - # Calculate edge probability for desired average degree - p = avg_degree / (num_nodes - 1) - - # Use NetworkX for efficient generation - G = nx.erdos_renyi_graph(num_nodes, p, seed=seed) - - return LargeGraphGenerator._networkx_to_graphdata(G) - - @staticmethod - def generate_scale_free_graph(num_nodes: int, m: int = 3, seed: Optional[int] = None) -> GraphData: - """Generate scale-free graph using BarabΓ‘si–Albert model""" - G = nx.barabasi_albert_graph(num_nodes, m, seed=seed) - return LargeGraphGenerator._networkx_to_graphdata(G) - - @staticmethod - def generate_small_world_graph(num_nodes: int, k: int = 6, p: float = 0.1, seed: Optional[int] = None) -> GraphData: - """Generate small-world graph using Watts-Strogatz model""" - G = nx.watts_strogatz_graph(num_nodes, k, p, seed=seed) - return LargeGraphGenerator._networkx_to_graphdata(G) - - @staticmethod - def generate_clustered_graph(num_nodes: int, num_clusters: int = 100, seed: Optional[int] = None) -> GraphData: - """Generate clustered graph with intra and inter-cluster connections""" - if seed: - np.random.seed(seed) - - cluster_size = num_nodes // num_clusters - G = nx.Graph() - - # Add nodes with cluster information - for i in range(num_nodes): - cluster_id = i // cluster_size - G.add_node(i, cluster=cluster_id) - - # Generate intra-cluster edges - intra_prob = 0.1 - for cluster in range(num_clusters): - cluster_start = cluster * cluster_size - cluster_end = min(cluster_start + cluster_size, num_nodes) - cluster_nodes = list(range(cluster_start, cluster_end)) - - # Create subgraph for cluster - cluster_subgraph = nx.erdos_renyi_graph(len(cluster_nodes), intra_prob) - - # Add edges to main graph with proper node mapping - for edge in cluster_subgraph.edges(): - G.add_edge(cluster_nodes[edge[0]], cluster_nodes[edge[1]]) - - # Generate inter-cluster edges - inter_prob = 0.001 - for i in range(num_nodes): - for j in range(i + 1, num_nodes): - if G.nodes[i].get('cluster') != G.nodes[j].get('cluster'): - if np.random.random() < inter_prob: - G.add_edge(i, j) - - return LargeGraphGenerator._networkx_to_graphdata(G) - - @staticmethod - def generate_hierarchical_graph(num_nodes: int, branching_factor: int = 3, seed: Optional[int] = None) -> GraphData: - """Generate hierarchical (tree-like) graph""" - G = nx.random_tree(num_nodes, seed=seed) - - # Add some cross-links to make it more interesting - if seed: - np.random.seed(seed) - - # Add 10% additional edges for cross-connections - num_additional_edges = max(1, num_nodes // 10) - nodes = list(G.nodes()) - - for _ in range(num_additional_edges): - u, v = np.random.choice(nodes, 2, replace=False) - if not G.has_edge(u, v): - G.add_edge(u, v) - - return LargeGraphGenerator._networkx_to_graphdata(G) - - @staticmethod - def generate_grid_graph(dimensions: List[int], seed: Optional[int] = None) -> GraphData: - """Generate 2D or 3D grid graph""" - if len(dimensions) == 2: - G = nx.grid_2d_graph(dimensions[0], dimensions[1]) - elif len(dimensions) == 3: - G = nx.grid_graph(dimensions) - else: - raise ValueError("Grid dimensions must be 2D or 3D") - - # Convert coordinate tuples to integer node IDs - mapping = {node: i for i, node in enumerate(G.nodes())} - G = nx.relabel_nodes(G, mapping) - - return LargeGraphGenerator._networkx_to_graphdata(G) - - @staticmethod - def _networkx_to_graphdata(G: nx.Graph) -> GraphData: - """Convert NetworkX graph to GraphData format""" - nodes = [] - links = [] - - # Convert nodes - for node_id in G.nodes(): - node_data = G.nodes[node_id] - node = { - "id": f"n{node_id}", - "name": f"Node {node_id}", - "val": np.random.randint(1, 11), - "degree": G.degree(node_id) - } - - # Add cluster information if available - if 'cluster' in node_data: - node['group'] = f"cluster_{node_data['cluster']}" - else: - node['group'] = f"group_{node_id % 10}" - - nodes.append(node) - - # Convert edges - for edge in G.edges(): - link = { - "source": f"n{edge[0]}", - "target": f"n{edge[1]}", - "name": f"link_{edge[0]}_{edge[1]}", - "weight": np.random.uniform(0.1, 5.0) - } - links.append(link) - - return GraphData(nodes=nodes, links=links) +# Import graph generation classes (keeping existing code) +from pygraphistry_service import LargeGraphGenerator, init_graphistry class LocalGPUProcessor: """GPU-accelerated graph processing using cuGraph""" @@ -333,10 +223,109 @@ class LocalGPUProcessor: logger.error(f"GPU centrality computation failed: {e}") return {} -class UnifiedGPUService: - """Unified service offering local GPU and CPU processing""" +class PyGraphistryProcessor: + """PyGraphistry cloud processing (existing functionality)""" def __init__(self): + self.initialized = init_graphistry() + + async def process_graph_data(self, request: UnifiedVisualizationRequest) -> Dict[str, Any]: + """Process graph data with PyGraphistry GPU acceleration""" + try: + if not self.initialized: + raise HTTPException(status_code=500, detail="PyGraphistry not initialized") + + # Convert to pandas DataFrames for PyGraphistry + nodes_df = pd.DataFrame(request.graph_data.nodes) + edges_df = pd.DataFrame(request.graph_data.links) + + # Ensure required columns exist + if 'id' not in nodes_df.columns: + nodes_df['id'] = nodes_df.index + if 'source' not in edges_df.columns or 'target' not in edges_df.columns: + raise HTTPException(status_code=400, detail="Links must have source and target columns") + + logger.info(f"Processing graph with {len(nodes_df)} nodes and {len(edges_df)} edges") + + # Create PyGraphistry graph object + g = graphistry.edges(edges_df, 'source', 'target').nodes(nodes_df, 'id') + + # Apply GPU-accelerated processing + if request.gpu_acceleration: + g = await self._apply_gpu_acceleration(g, request) + + # Apply clustering if requested + if request.clustering: + g = await self._apply_clustering(g) + + # Generate layout + g = await self._generate_layout(g, request.layout_type) + + # Extract processed data + processed_nodes = g._nodes.to_dict('records') if g._nodes is not None else nodes_df.to_dict('records') + processed_edges = g._edges.to_dict('records') if g._edges is not None else edges_df.to_dict('records') + + # Generate embedding URL for interactive visualization + embed_url = None + local_viz_data = None + + try: + embed_url = g.plot(render=False) + logger.info(f"Generated PyGraphistry embed URL: {embed_url}") + except Exception as e: + logger.warning(f"Could not generate embed URL (likely running in local mode): {e}") + + # Create local visualization data as fallback + try: + local_viz_data = self._create_local_viz_data(g, processed_nodes, processed_edges) + logger.info("Generated local visualization data as fallback") + except Exception as viz_e: + logger.warning(f"Could not generate local visualization data: {viz_e}") + + return { + "processed_nodes": processed_nodes, + "processed_edges": processed_edges, + "embed_url": embed_url, + "local_viz_data": local_viz_data, + "processing_mode": ProcessingMode.PYGRAPHISTRY_CLOUD, + "stats": { + "node_count": len(processed_nodes), + "edge_count": len(processed_edges), + "gpu_accelerated": request.gpu_acceleration, + "clustered": request.clustering, + "layout_type": request.layout_type, + "has_embed_url": embed_url is not None, + "has_local_viz": local_viz_data is not None + }, + "timestamp": datetime.now().isoformat() + } + + except Exception as e: + logger.error(f"Error processing graph data: {e}") + raise HTTPException(status_code=500, detail=str(e)) + + # ... (include other PyGraphistry methods from original service) + async def _apply_gpu_acceleration(self, g, request): + # Implementation from original service + pass + + async def _apply_clustering(self, g): + # Implementation from original service + pass + + async def _generate_layout(self, g, layout_type): + # Implementation from original service + pass + + def _create_local_viz_data(self, g, processed_nodes, processed_edges): + # Implementation from original service + pass + +class UnifiedGPUService: + """Unified service offering both PyGraphistry cloud and local GPU processing""" + + def __init__(self): + self.pygraphistry_processor = PyGraphistryProcessor() self.local_gpu_processor = LocalGPUProcessor() self.generation_tasks = {} self.executor = ThreadPoolExecutor(max_workers=4) @@ -345,8 +334,12 @@ class UnifiedGPUService: async def process_graph(self, request: UnifiedVisualizationRequest) -> Dict[str, Any]: """Process graph with selected processing mode""" - if request.processing_mode == ProcessingMode.LOCAL_GPU: + if request.processing_mode == ProcessingMode.PYGRAPHISTRY_CLOUD: + return await self.pygraphistry_processor.process_graph_data(request) + + elif request.processing_mode == ProcessingMode.LOCAL_GPU: return await self._process_with_local_gpu(request) + else: # LOCAL_CPU return await self._process_with_local_cpu(request) @@ -458,7 +451,7 @@ service = UnifiedGPUService() @app.post("/api/visualize") async def visualize_graph(request: UnifiedVisualizationRequest): - """Process graph with unified service (supports local GPU and CPU modes)""" + """Process graph with unified service (supports all processing modes)""" result = await service.process_graph(request) # Broadcast to connected WebSocket clients @@ -485,13 +478,17 @@ async def get_capabilities(): """Get GPU capabilities and available processing modes""" return { "processing_modes": { + "pygraphistry_cloud": { + "available": service.pygraphistry_processor.initialized, + "description": "PyGraphistry cloud GPU processing with interactive embeds" + }, "local_gpu": { "available": HAS_RAPIDS, "description": "Local GPU processing with cuGraph/RAPIDS" }, "local_cpu": { "available": True, - "description": "Local CPU fallback processing with NetworkX" + "description": "Local CPU fallback processing" } }, "has_rapids": HAS_RAPIDS, @@ -543,6 +540,7 @@ async def health_check(): """Health check endpoint""" return { "status": "healthy", + "pygraphistry_initialized": service.pygraphistry_processor.initialized, "local_gpu_available": HAS_RAPIDS, "torch_geometric": HAS_TORCH_GEOMETRIC, "timestamp": datetime.now().isoformat() @@ -573,6 +571,7 @@ async def get_visualization_page():
@@ -757,8 +756,23 @@ def startup_diagnostics(): else: print("⚠ PyTorch Geometric not available") + # Check PyGraphistry credentials + print("Checking PyGraphistry credentials...") + personal_key = os.getenv('GRAPHISTRY_PERSONAL_KEY') + secret_key = os.getenv('GRAPHISTRY_SECRET_KEY') + api_key = os.getenv('GRAPHISTRY_API_KEY') + + if personal_key and secret_key: + print("βœ“ PyGraphistry personal key/secret found") + elif api_key: + print("βœ“ PyGraphistry API key found") + else: + print("⚠ No PyGraphistry credentials found - cloud mode will be limited") + print(" Set GRAPHISTRY_PERSONAL_KEY + GRAPHISTRY_SECRET_KEY for full cloud features") + print("") print("🎯 Available Processing Modes:") + print(" ☁️ PyGraphistry Cloud - Interactive GPU embeds (requires credentials)") print(" πŸš€ Local GPU (cuGraph) - Full local GPU processing") print(" πŸ’» Local CPU - NetworkX fallback") print("") @@ -772,4 +786,4 @@ def startup_diagnostics(): if __name__ == "__main__": startup_diagnostics() - uvicorn.run(app, host="0.0.0.0", port=8080) + uvicorn.run(app, host="0.0.0.0", port=8080) \ No newline at end of file diff --git a/nvidia/txt2kg/assets/deploy/services/gpu-viz/webgl_rendering_enhancement.py b/nvidia/txt2kg/assets/deploy/services/gpu-viz/webgl_rendering_enhancement.py index 0b49a9c..c887783 100644 --- a/nvidia/txt2kg/assets/deploy/services/gpu-viz/webgl_rendering_enhancement.py +++ b/nvidia/txt2kg/assets/deploy/services/gpu-viz/webgl_rendering_enhancement.py @@ -1,3 +1,19 @@ +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# # WebGL-Enhanced Remote GPU Rendering Service # Using Three.js for GPU-accelerated visualization diff --git a/nvidia/txt2kg/assets/deploy/services/ollama/Dockerfile b/nvidia/txt2kg/assets/deploy/services/ollama/Dockerfile index e3e76d8..efdad5f 100644 --- a/nvidia/txt2kg/assets/deploy/services/ollama/Dockerfile +++ b/nvidia/txt2kg/assets/deploy/services/ollama/Dockerfile @@ -1,4 +1,4 @@ -FROM ollama/ollama:latest +FROM ollama/ollama:0.12.6 # Copy the entrypoint script COPY entrypoint.sh /entrypoint.sh diff --git a/nvidia/txt2kg/assets/deploy/services/ollama/clear_cache_and_restart.sh b/nvidia/txt2kg/assets/deploy/services/ollama/clear_cache_and_restart.sh index 9721e92..dc17a69 100755 --- a/nvidia/txt2kg/assets/deploy/services/ollama/clear_cache_and_restart.sh +++ b/nvidia/txt2kg/assets/deploy/services/ollama/clear_cache_and_restart.sh @@ -1,5 +1,21 @@ #!/bin/bash # +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# # Clear buffer cache and restart Ollama to fix unified memory detection # This script addresses the issue where Ollama can't see full GPU memory # due to buffer cache not being reclaimable in unified memory systems diff --git a/nvidia/txt2kg/assets/deploy/services/ollama/entrypoint.sh b/nvidia/txt2kg/assets/deploy/services/ollama/entrypoint.sh index 6959cf3..425ff96 100644 --- a/nvidia/txt2kg/assets/deploy/services/ollama/entrypoint.sh +++ b/nvidia/txt2kg/assets/deploy/services/ollama/entrypoint.sh @@ -1,4 +1,20 @@ #!/bin/bash +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# set -e # Start Ollama server in the background diff --git a/nvidia/txt2kg/assets/deploy/services/sentence-transformers/app.py b/nvidia/txt2kg/assets/deploy/services/sentence-transformers/app.py index 1f3cbc0..de9f914 100644 --- a/nvidia/txt2kg/assets/deploy/services/sentence-transformers/app.py +++ b/nvidia/txt2kg/assets/deploy/services/sentence-transformers/app.py @@ -1,3 +1,19 @@ +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# from flask import Flask, request, jsonify from sentence_transformers import SentenceTransformer import os diff --git a/nvidia/txt2kg/assets/deploy/services/vllm/build_image.sh b/nvidia/txt2kg/assets/deploy/services/vllm/build_image.sh index 4c902d8..fc50dcc 100755 --- a/nvidia/txt2kg/assets/deploy/services/vllm/build_image.sh +++ b/nvidia/txt2kg/assets/deploy/services/vllm/build_image.sh @@ -1,4 +1,20 @@ #!/bin/bash +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# # Use latest stable vLLM release for better compute capability 12.1 support # Clone the vLLM GitHub repo and use latest stable release. diff --git a/nvidia/txt2kg/assets/deploy/services/vllm/launch_server.sh b/nvidia/txt2kg/assets/deploy/services/vllm/launch_server.sh index e89640c..a9a09ae 100755 --- a/nvidia/txt2kg/assets/deploy/services/vllm/launch_server.sh +++ b/nvidia/txt2kg/assets/deploy/services/vllm/launch_server.sh @@ -1,4 +1,20 @@ #!/bin/bash +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# # Launch vLLM with NVIDIA Triton Inference Server optimized build # This should have proper support for compute capability 12.1 (DGX Spark) diff --git a/nvidia/txt2kg/assets/deploy/services/vllm/run_benchmark.sh b/nvidia/txt2kg/assets/deploy/services/vllm/run_benchmark.sh index 43208e7..795d287 100755 --- a/nvidia/txt2kg/assets/deploy/services/vllm/run_benchmark.sh +++ b/nvidia/txt2kg/assets/deploy/services/vllm/run_benchmark.sh @@ -1,4 +1,20 @@ #!/bin/bash +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# # vLLM Llama3 8B Benchmark Runner # Uses NVIDIA vLLM container for optimal performance diff --git a/nvidia/txt2kg/assets/deploy/services/vllm/run_container.sh b/nvidia/txt2kg/assets/deploy/services/vllm/run_container.sh index a56cb18..feb81bf 100755 --- a/nvidia/txt2kg/assets/deploy/services/vllm/run_container.sh +++ b/nvidia/txt2kg/assets/deploy/services/vllm/run_container.sh @@ -1,4 +1,20 @@ #!/bin/bash +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# # Follow the official vLLM tutorial run_container.sh exactly docker run -e HF_TOKEN="$HF_TOKEN" -e HF_HOME="$HF_HOME" --ipc=host --gpus all --entrypoint "/bin/bash" --rm -it vllm/vllm-openai:deploy diff --git a/nvidia/txt2kg/assets/deploy/services/vllm/start-vllm.sh b/nvidia/txt2kg/assets/deploy/services/vllm/start-vllm.sh index 4b27093..f0140a8 100755 --- a/nvidia/txt2kg/assets/deploy/services/vllm/start-vllm.sh +++ b/nvidia/txt2kg/assets/deploy/services/vllm/start-vllm.sh @@ -1,4 +1,20 @@ #!/bin/bash +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# # vLLM startup script with NVFP4 quantization support for Llama 4 Scout # Optimized for NVIDIA Blackwell and Hopper architectures diff --git a/nvidia/txt2kg/assets/examples/download_biorxiv_dataset.py b/nvidia/txt2kg/assets/examples/download_biorxiv_dataset.py index a7cf2da..8a4605b 100644 --- a/nvidia/txt2kg/assets/examples/download_biorxiv_dataset.py +++ b/nvidia/txt2kg/assets/examples/download_biorxiv_dataset.py @@ -1,4 +1,20 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# """ Download and process the MTEB raw_biorxiv dataset for txt2kg demo. Filter for genetics/genomics categories and create individual txt files. diff --git a/nvidia/txt2kg/assets/examples/download_cc_biorxiv_dataset.py b/nvidia/txt2kg/assets/examples/download_cc_biorxiv_dataset.py index bfa76b4..645b046 100644 --- a/nvidia/txt2kg/assets/examples/download_cc_biorxiv_dataset.py +++ b/nvidia/txt2kg/assets/examples/download_cc_biorxiv_dataset.py @@ -1,4 +1,20 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# """ Download and process the marianna13/biorxiv dataset for txt2kg demo. Filter for Creative Commons licensed papers and create individual txt files. diff --git a/nvidia/txt2kg/assets/frontend/app/.static/3d-force-graph-mock.js b/nvidia/txt2kg/assets/frontend/app/.static/3d-force-graph-mock.js index 218be2b..5990b7d 100644 --- a/nvidia/txt2kg/assets/frontend/app/.static/3d-force-graph-mock.js +++ b/nvidia/txt2kg/assets/frontend/app/.static/3d-force-graph-mock.js @@ -1 +1,17 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// console.log('This is mock data to avoid SSR issues') diff --git a/nvidia/txt2kg/assets/frontend/app/api/backend/route.ts b/nvidia/txt2kg/assets/frontend/app/api/backend/route.ts index 178002a..0103ff7 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/backend/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/backend/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import remoteBackend from '@/lib/remote-backend'; import type { Triple } from '@/types/graph'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/config/route.ts b/nvidia/txt2kg/assets/frontend/app/api/config/route.ts index d94e619..0f80a92 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/config/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/config/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextResponse } from "next/server"; export async function GET() { diff --git a/nvidia/txt2kg/assets/frontend/app/api/embeddings/route.ts b/nvidia/txt2kg/assets/frontend/app/api/embeddings/route.ts index caf7bb3..e6038e5 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/embeddings/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/embeddings/route.ts @@ -1,9 +1,25 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import { EmbeddingsService } from '@/lib/embeddings'; -import { PineconeService } from '@/lib/pinecone'; +import { QdrantService } from '@/lib/qdrant'; /** - * Generate embeddings for text chunks and store them in Pinecone + * Generate embeddings for text chunks and store them in Qdrant */ export async function POST(request: NextRequest) { try { @@ -38,15 +54,15 @@ export async function POST(request: NextRequest) { console.log('Generating embeddings for chunks...'); const embeddings = await embeddingsService.encode(chunks); console.log(`Generated ${embeddings.length} embeddings`); - - // Initialize PineconeService - const pineconeService = PineconeService.getInstance(); - - // Check if Pinecone server is running - const isPineconeRunning = await pineconeService.isPineconeRunning(); + + // Initialize QdrantService + const pineconeService = QdrantService.getInstance(); + + // Check if Qdrant server is running + const isPineconeRunning = await pineconeService.isQdrantRunning(); if (!isPineconeRunning) { return NextResponse.json( - { error: 'Pinecone server is not available. Please make sure it is running.' }, + { error: 'Qdrant server is not available. Please make sure it is running.' }, { status: 503 } ); } diff --git a/nvidia/txt2kg/assets/frontend/app/api/enhanced-query/route.ts b/nvidia/txt2kg/assets/frontend/app/api/enhanced-query/route.ts index 7533849..7841ad8 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/enhanced-query/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/enhanced-query/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import { RemoteBackendService } from '@/lib/remote-backend'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/extract-triples/route.ts b/nvidia/txt2kg/assets/frontend/app/api/extract-triples/route.ts index da1382b..0e82e80 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/extract-triples/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/extract-triples/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import { processDocument, TextProcessor } from '@/lib/text-processor'; import { llmService } from '@/lib/llm-service'; @@ -29,7 +45,8 @@ export async function POST(req: NextRequest) { ollamaModel, ollamaBaseUrl, vllmModel, - vllmBaseUrl + vllmBaseUrl, + nvidiaModel } = body; if (!text || typeof text !== 'string') { @@ -136,7 +153,8 @@ export async function POST(req: NextRequest) { ollamaModel: ollamaModel, ollamaBaseUrl: ollamaBaseUrl, vllmModel: vllmModel, - vllmBaseUrl: vllmBaseUrl + vllmBaseUrl: vllmBaseUrl, + nvidiaModel: nvidiaModel }); } diff --git a/nvidia/txt2kg/assets/frontend/app/api/fix-query-logs/route.ts b/nvidia/txt2kg/assets/frontend/app/api/fix-query-logs/route.ts index 525cc67..a318846 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/fix-query-logs/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/fix-query-logs/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import queryLoggerService, { QueryLogEntry } from '@/lib/query-logger'; import fs from 'fs'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/graph-data/route.ts b/nvidia/txt2kg/assets/frontend/app/api/graph-data/route.ts index 26c9304..c9a5200 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/graph-data/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/graph-data/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { type NextRequest, NextResponse } from "next/server" // Utility function to generate UUID with fallback diff --git a/nvidia/txt2kg/assets/frontend/app/api/graph-db/clear/route.ts b/nvidia/txt2kg/assets/frontend/app/api/graph-db/clear/route.ts index 3434760..6a144ba 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/graph-db/clear/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/graph-db/clear/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import { getGraphDbService } from '@/lib/graph-db-util'; import { getGraphDbType } from '../../settings/route'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/graph-db/disconnect/route.ts b/nvidia/txt2kg/assets/frontend/app/api/graph-db/disconnect/route.ts index 5eac33b..098b114 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/graph-db/disconnect/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/graph-db/disconnect/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import { getGraphDbService } from '@/lib/graph-db-util'; import { getGraphDbType } from '../../settings/route'; 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 690b919..91bb57f 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/graph-db/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/graph-db/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import { getGraphDbService } from '@/lib/graph-db-util'; import { getGraphDbType } from '../settings/route'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/graph-db/triples/route.ts b/nvidia/txt2kg/assets/frontend/app/api/graph-db/triples/route.ts index f777a4d..3142133 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/graph-db/triples/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/graph-db/triples/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import { getGraphDbService } from '@/lib/graph-db-util'; import { getGraphDbType } from '../../settings/route'; @@ -160,6 +176,16 @@ export async function POST(req: NextRequest) { // Store triples in the graph database await graphDbService.importTriples(validTriples); + // Mark document as processed if documentName is provided (only for ArangoDB) + if (graphDbType === 'arangodb' && documentName) { + try { + await (graphDbService as any).markDocumentAsProcessed(documentName, validTriples.length); + } catch (error) { + console.error('Error marking document as processed:', error); + // Don't fail the request if marking fails + } + } + // Return success response return NextResponse.json({ success: true, diff --git a/nvidia/txt2kg/assets/frontend/app/api/graph-query-llm/route.ts b/nvidia/txt2kg/assets/frontend/app/api/graph-query-llm/route.ts new file mode 100644 index 0000000..b0250e8 --- /dev/null +++ b/nvidia/txt2kg/assets/frontend/app/api/graph-query-llm/route.ts @@ -0,0 +1,66 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +import { NextRequest, NextResponse } from 'next/server'; +import backendService from '@/lib/backend-service'; +import { getGraphDbType } from '../settings/route'; + +/** + * API endpoint for LLM-enhanced graph query + * This retrieves triples using graph search and generates an answer using LLM + * Makes traditional graph search comparable to RAG for fair benchmarking + * POST /api/graph-query-llm + */ +export async function POST(request: NextRequest) { + try { + const { query, topK = 5, useTraditional = true, llmModel, llmProvider } = await request.json(); + + if (!query) { + return NextResponse.json({ error: 'Query is required' }, { status: 400 }); + } + + // Initialize backend if needed with the selected graph DB type + if (!backendService.isInitialized) { + const graphDbType = getGraphDbType(); + console.log(`Initializing backend with graph DB type: ${graphDbType}`); + await backendService.initialize(graphDbType); + } + + console.log(`Graph query with LLM: "${query}", topK=${topK}, traditional=${useTraditional}, model=${llmModel || 'default'}, provider=${llmProvider || 'default'}`); + + // Query the backend with LLM enhancement + const result = await backendService.queryWithLLM(query, topK, useTraditional, llmModel, llmProvider); + + // DEBUG: Log first triple in API route to verify depth/pathLength + if (result.triples && result.triples.length > 0) { + console.log('API route - first triple:', JSON.stringify(result.triples[0], null, 2)); + } + + // Return results + return NextResponse.json({ + query, + answer: result.answer, + triples: result.triples, + count: result.count, + message: `Retrieved ${result.count} triples and generated answer using ${useTraditional ? 'traditional' : 'vector'} graph search + LLM` + }); + } catch (error) { + console.error('Error in graph query with LLM:', error); + const errorMessage = error instanceof Error ? error.message : 'Unknown error'; + return NextResponse.json({ error: errorMessage }, { status: 500 }); + } +} + diff --git a/nvidia/txt2kg/assets/frontend/app/api/metrics/route.ts b/nvidia/txt2kg/assets/frontend/app/api/metrics/route.ts index 8f024c2..66dbe1f 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/metrics/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/metrics/route.ts @@ -1,8 +1,24 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import remoteBackendInstance from '@/lib/remote-backend'; -import { Neo4jService } from '@/lib/neo4j'; -import neo4jService from '@/lib/neo4j'; -import { PineconeService } from '@/lib/pinecone'; +import { getGraphDbService } from '@/lib/graph-db-util'; +import { getGraphDbType } from '../settings/route'; +import { QdrantService } from '@/lib/qdrant'; import RAGService from '@/lib/rag'; import queryLoggerService, { QueryLogSummary } from '@/lib/query-logger'; @@ -11,16 +27,31 @@ import queryLoggerService, { QueryLogSummary } from '@/lib/query-logger'; */ export async function GET(request: NextRequest) { try { - // Initialize services - const neo4j = Neo4jService.getInstance(); - const pineconeService = PineconeService.getInstance(); + // Initialize services with the correct graph database type + const graphDbType = getGraphDbType(); + const graphDbService = getGraphDbService(graphDbType); + const pineconeService = QdrantService.getInstance(); - if (!neo4j.isInitialized()) { - neo4j.initialize(); + // Initialize graph database if needed + if (!graphDbService.isInitialized()) { + if (graphDbType === 'arangodb') { + await graphDbService.initialize( + process.env.ARANGODB_URL, + process.env.ARANGODB_DB, + process.env.ARANGODB_USER, + process.env.ARANGODB_PASSWORD + ); + } else if (graphDbType === 'neo4j') { + graphDbService.initialize( + process.env.NEO4J_URI, + process.env.NEO4J_USER || process.env.NEO4J_USERNAME, + process.env.NEO4J_PASSWORD + ); + } } - // Get graph stats from Neo4j - const graphData = await neo4j.getGraphData(); + // Get graph stats from the active graph database + const graphData = await graphDbService.getGraphData(); // Get unique entities (nodes) const uniqueEntities = new Set(); @@ -51,11 +82,12 @@ export async function GET(request: NextRequest) { // Get real query logs instead of mock data let queryLogs: QueryLogSummary[] = []; - let precision = 0; + let precision = 0; let recall = 0; let f1Score = 0; let avgQueryTime = vectorStats.avgQueryTime || 0; let avgRelevance = 0; + let queryTimesByMode: Record = {}; // Get query logs from file-based logger instead of Neo4j try { @@ -72,25 +104,42 @@ export async function GET(request: NextRequest) { // Calculate metrics from the query logs if (queryLogs.length > 0) { // Calculate metrics from logs with actual data - const logsWithMetrics = queryLogs.filter(log => - log.metrics.avgPrecision > 0 || - log.metrics.avgRecall > 0 || + const logsWithMetrics = queryLogs.filter(log => + log.metrics.avgPrecision > 0 || + log.metrics.avgRecall > 0 || log.metrics.avgExecutionTimeMs > 0 ); - + const logsWithRelevance = queryLogs.filter(log => log.metrics.avgRelevanceScore > 0); - + if (logsWithMetrics.length > 0) { precision = logsWithMetrics.reduce((sum, log) => sum + (log.metrics.avgPrecision || 0), 0) / logsWithMetrics.length; recall = logsWithMetrics.reduce((sum, log) => sum + (log.metrics.avgRecall || 0), 0) / logsWithMetrics.length; avgQueryTime = logsWithMetrics.reduce((sum, log) => sum + (log.metrics.avgExecutionTimeMs || 0), 0) / logsWithMetrics.length; f1Score = precision > 0 && recall > 0 ? 2 * (precision * recall) / (precision + recall) : 0; } - + if (logsWithRelevance.length > 0) { avgRelevance = logsWithRelevance.reduce((sum, log) => sum + (log.metrics.avgRelevanceScore || 0), 0) / logsWithRelevance.length; } } + + // Calculate per-mode query times + const logsByMode = queryLogs.reduce((acc, log) => { + const mode = log.queryMode || 'traditional'; + if (!acc[mode]) acc[mode] = []; + acc[mode].push(log); + return acc; + }, {} as Record); + + Object.entries(logsByMode).forEach(([mode, logs]) => { + const logsWithTime = logs.filter(log => log.metrics.avgExecutionTimeMs > 0); + if (logsWithTime.length > 0) { + queryTimesByMode[mode] = logsWithTime.reduce((sum, log) => + sum + log.metrics.avgExecutionTimeMs, 0 + ) / logsWithTime.length; + } + }); } catch (error) { console.warn('Error getting query logs from file:', error); // Keep values at 0 instead of using defaults @@ -117,6 +166,7 @@ export async function GET(request: NextRequest) { recall, f1Score, topQueries, + queryTimesByMode: queryTimesByMode || {}, // Add metadata about query logs queryLogStats: { totalQueryLogs: queryLogs.length, diff --git a/nvidia/txt2kg/assets/frontend/app/api/neo4j/disconnect/route.ts b/nvidia/txt2kg/assets/frontend/app/api/neo4j/disconnect/route.ts index 64efe5f..b43bd4c 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/neo4j/disconnect/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/neo4j/disconnect/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; /** diff --git a/nvidia/txt2kg/assets/frontend/app/api/neo4j/route.ts b/nvidia/txt2kg/assets/frontend/app/api/neo4j/route.ts index cbd66da..972e888 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/neo4j/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/neo4j/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import { Neo4jService } from '@/lib/neo4j'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/neo4j/triples/route.ts b/nvidia/txt2kg/assets/frontend/app/api/neo4j/triples/route.ts index 3082a31..471433c 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/neo4j/triples/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/neo4j/triples/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; /** diff --git a/nvidia/txt2kg/assets/frontend/app/api/ollama/batch/route.ts b/nvidia/txt2kg/assets/frontend/app/api/ollama/batch/route.ts index da59cd0..047ae5e 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/ollama/batch/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/ollama/batch/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import { llmService, LLMMessage } from '@/lib/llm-service'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/ollama/route.ts b/nvidia/txt2kg/assets/frontend/app/api/ollama/route.ts index 499e81e..819d3c3 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/ollama/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/ollama/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import { llmService } from '@/lib/llm-service'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/ollama/test/route.ts b/nvidia/txt2kg/assets/frontend/app/api/ollama/test/route.ts index f0545d9..a5c24e0 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/ollama/test/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/ollama/test/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; /** diff --git a/nvidia/txt2kg/assets/frontend/app/api/pinecone-diag/clear/route.ts b/nvidia/txt2kg/assets/frontend/app/api/pinecone-diag/clear/route.ts index f73d7cf..d2491b7 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/pinecone-diag/clear/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/pinecone-diag/clear/route.ts @@ -1,5 +1,21 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; -import { PineconeService } from '@/lib/pinecone'; +import { QdrantService } from '@/lib/qdrant'; /** * Clear all data from the Pinecone vector database @@ -7,7 +23,7 @@ import { PineconeService } from '@/lib/pinecone'; */ export async function POST() { // Get the Pinecone service instance - const pineconeService = PineconeService.getInstance(); + const pineconeService = QdrantService.getInstance(); // Clear all vectors from the database const deleteSuccess = await pineconeService.deleteAllEntities(); diff --git a/nvidia/txt2kg/assets/frontend/app/api/pinecone-diag/create-index/route.ts b/nvidia/txt2kg/assets/frontend/app/api/pinecone-diag/create-index/route.ts index 7ce0f5c..749dacc 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/pinecone-diag/create-index/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/pinecone-diag/create-index/route.ts @@ -1,5 +1,21 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextResponse } from 'next/server'; -import { PineconeService } from '@/lib/pinecone'; +import { QdrantService } from '@/lib/qdrant'; /** * Create Pinecone index API endpoint @@ -8,7 +24,7 @@ import { PineconeService } from '@/lib/pinecone'; export async function POST() { try { // Get the Pinecone service instance - const pineconeService = PineconeService.getInstance(); + const pineconeService = QdrantService.getInstance(); // Force re-initialization to create the index (pineconeService as any).initialized = false; diff --git a/nvidia/txt2kg/assets/frontend/app/api/pinecone-diag/stats/route.ts b/nvidia/txt2kg/assets/frontend/app/api/pinecone-diag/stats/route.ts index a1aa129..e9159e0 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/pinecone-diag/stats/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/pinecone-diag/stats/route.ts @@ -1,5 +1,21 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; -import { PineconeService } from '@/lib/pinecone'; +import { QdrantService } from '@/lib/qdrant'; /** * Get Pinecone vector database stats @@ -7,7 +23,7 @@ import { PineconeService } from '@/lib/pinecone'; export async function GET() { try { // Initialize Pinecone service - const pineconeService = PineconeService.getInstance(); + const pineconeService = QdrantService.getInstance(); // We can now directly call getStats() which handles initialization and error recovery const stats = await pineconeService.getStats(); diff --git a/nvidia/txt2kg/assets/frontend/app/api/process-document/route.ts b/nvidia/txt2kg/assets/frontend/app/api/process-document/route.ts index 9182ff5..f18ba9c 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/process-document/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/process-document/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import { RemoteBackendService } from '@/lib/remote-backend'; import { EmbeddingsService } from '@/lib/embeddings'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/generate/[taskId]/route.ts b/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/generate/[taskId]/route.ts index 38c6536..1924744 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/generate/[taskId]/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/generate/[taskId]/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server' const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080' diff --git a/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/generate/route.ts b/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/generate/route.ts index 5405d2b..37caf86 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/generate/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/generate/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server' const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080' diff --git a/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/health/route.ts b/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/health/route.ts index 4110185..ce98920 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/health/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/health/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server' const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080' diff --git a/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/stats/route.ts b/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/stats/route.ts index 163a5b7..1ab0710 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/stats/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/stats/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server' const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080' diff --git a/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/visualize/route.ts b/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/visualize/route.ts index 9c916ee..31c8bb5 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/visualize/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/pygraphistry/visualize/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server' const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080' diff --git a/nvidia/txt2kg/assets/frontend/app/api/query-log/add/route.ts b/nvidia/txt2kg/assets/frontend/app/api/query-log/add/route.ts index b1283bd..af24b5b 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/query-log/add/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/query-log/add/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import neo4jService from '@/lib/neo4j'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/query-log/route.ts b/nvidia/txt2kg/assets/frontend/app/api/query-log/route.ts index c9ed02d..6019426 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/query-log/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/query-log/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import queryLoggerService from '@/lib/query-logger'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/query-log/test/route.ts b/nvidia/txt2kg/assets/frontend/app/api/query-log/test/route.ts index b22b31c..7cec9a3 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/query-log/test/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/query-log/test/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import neo4jService from '@/lib/neo4j'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/query/route.ts b/nvidia/txt2kg/assets/frontend/app/api/query/route.ts index ede7853..9619364 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/query/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/query/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import backendService from '@/lib/backend-service'; import type { Triple } from '@/types/graph'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/rag-query/route.ts b/nvidia/txt2kg/assets/frontend/app/api/rag-query/route.ts index 00fec6b..474544f 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/rag-query/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/rag-query/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import RAGService from '@/lib/rag'; @@ -20,17 +36,20 @@ export async function POST(req: NextRequest) { const ragService = RAGService; await ragService.initialize(); - console.log(`Processing RAG query: "${query}" with topK=${topK}`); + console.log(`Processing Pure RAG query: "${query}" with topK=${topK}`); // Retrieve documents and generate answer - const answer = await ragService.retrievalQA(query, topK); + const result = await ragService.retrievalQA(query, topK); // Check if this is a fallback response - const isGeneralKnowledgeFallback = answer.startsWith('[Note: No specific information was found'); + const isGeneralKnowledgeFallback = result.answer.startsWith('[Note: No specific information was found'); + + console.log(`βœ… Pure RAG query completed. Retrieved ${result.documentCount} document chunks`); // Return the results return NextResponse.json({ - answer, + answer: result.answer, + documentCount: result.documentCount, usedFallback: isGeneralKnowledgeFallback, success: true }); diff --git a/nvidia/txt2kg/assets/frontend/app/api/remote-webgpu-stream/[sessionId]/route.ts b/nvidia/txt2kg/assets/frontend/app/api/remote-webgpu-stream/[sessionId]/route.ts index cd57fe0..119f029 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/remote-webgpu-stream/[sessionId]/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/remote-webgpu-stream/[sessionId]/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server' // Proxy route specifically for WebRTC streaming frames diff --git a/nvidia/txt2kg/assets/frontend/app/api/remote-webgpu/[...path]/route.ts b/nvidia/txt2kg/assets/frontend/app/api/remote-webgpu/[...path]/route.ts index 109b0fc..78d2c2f 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/remote-webgpu/[...path]/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/remote-webgpu/[...path]/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server' // Proxy route for remote WebGPU clustering service diff --git a/nvidia/txt2kg/assets/frontend/app/api/sentence-embeddings/route.ts b/nvidia/txt2kg/assets/frontend/app/api/sentence-embeddings/route.ts index c23c0bb..7fc1905 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/sentence-embeddings/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/sentence-embeddings/route.ts @@ -1,6 +1,22 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import { processSentenceEmbeddings, SentenceEmbedding } from '@/lib/text-processor'; -import { PineconeService } from '@/lib/pinecone'; +import { QdrantService } from '@/lib/qdrant'; /** * API endpoint for splitting text into sentences and generating embeddings @@ -49,7 +65,7 @@ export async function POST(req: NextRequest) { }); // Store in Pinecone - const pineconeService = PineconeService.getInstance(); + const pineconeService = QdrantService.getInstance(); await pineconeService.storeEmbeddingsWithMetadata( embeddingsMap, textContentMap, diff --git a/nvidia/txt2kg/assets/frontend/app/api/settings/route.ts b/nvidia/txt2kg/assets/frontend/app/api/settings/route.ts index e091f38..5875395 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/settings/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/settings/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import { GraphDBType } from '@/lib/graph-db-service'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/stop-embeddings/route.ts b/nvidia/txt2kg/assets/frontend/app/api/stop-embeddings/route.ts index f8b026b..55cb1af 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/stop-embeddings/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/stop-embeddings/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server' // Global flag to track if embeddings generation should be stopped diff --git a/nvidia/txt2kg/assets/frontend/app/api/stop-processing/route.ts b/nvidia/txt2kg/assets/frontend/app/api/stop-processing/route.ts index c5b3128..807df2b 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/stop-processing/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/stop-processing/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server' // Global flag to track if processing should be stopped diff --git a/nvidia/txt2kg/assets/frontend/app/api/store-documents/route.ts b/nvidia/txt2kg/assets/frontend/app/api/store-documents/route.ts index af4a8c3..0e3e2b2 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/store-documents/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/store-documents/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import RAGService from '@/lib/rag'; diff --git a/nvidia/txt2kg/assets/frontend/app/api/test-proxy/route.ts b/nvidia/txt2kg/assets/frontend/app/api/test-proxy/route.ts index 5e4c77c..77bad52 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/test-proxy/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/test-proxy/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server' // Simple test endpoint to verify proxy connectivity diff --git a/nvidia/txt2kg/assets/frontend/app/api/unified-gpu/capabilities/route.ts b/nvidia/txt2kg/assets/frontend/app/api/unified-gpu/capabilities/route.ts index ff01d58..dc10b4a 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/unified-gpu/capabilities/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/unified-gpu/capabilities/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server' const UNIFIED_GPU_SERVICE_URL = process.env.UNIFIED_GPU_SERVICE_URL || 'http://localhost:8080' diff --git a/nvidia/txt2kg/assets/frontend/app/api/unified-gpu/visualize/route.ts b/nvidia/txt2kg/assets/frontend/app/api/unified-gpu/visualize/route.ts index fb4fbd1..2193362 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/unified-gpu/visualize/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/unified-gpu/visualize/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server' const UNIFIED_GPU_SERVICE_URL = process.env.UNIFIED_GPU_SERVICE_URL || 'http://localhost:8080' diff --git a/nvidia/txt2kg/assets/frontend/app/api/vllm/route.ts b/nvidia/txt2kg/assets/frontend/app/api/vllm/route.ts index 4301a53..0a72b3e 100644 --- a/nvidia/txt2kg/assets/frontend/app/api/vllm/route.ts +++ b/nvidia/txt2kg/assets/frontend/app/api/vllm/route.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { NextRequest, NextResponse } from 'next/server'; import { LLMService } from '@/lib/llm-service'; diff --git a/nvidia/txt2kg/assets/frontend/app/components/documents-list.tsx b/nvidia/txt2kg/assets/frontend/app/components/documents-list.tsx index e89b83e..f535b25 100644 --- a/nvidia/txt2kg/assets/frontend/app/components/documents-list.tsx +++ b/nvidia/txt2kg/assets/frontend/app/components/documents-list.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client"; import { useState, useEffect } from "react"; diff --git a/nvidia/txt2kg/assets/frontend/app/document-data/page.tsx b/nvidia/txt2kg/assets/frontend/app/document-data/page.tsx index b17fcff..f5073cf 100644 --- a/nvidia/txt2kg/assets/frontend/app/document-data/page.tsx +++ b/nvidia/txt2kg/assets/frontend/app/document-data/page.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { DocumentsTable } from "@/components/documents-table"; import { DocumentProcessor } from "@/components/document-processor"; diff --git a/nvidia/txt2kg/assets/frontend/app/graph/page.tsx b/nvidia/txt2kg/assets/frontend/app/graph/page.tsx index 1458303..d3eb3a4 100644 --- a/nvidia/txt2kg/assets/frontend/app/graph/page.tsx +++ b/nvidia/txt2kg/assets/frontend/app/graph/page.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useEffect, useState } from "react" diff --git a/nvidia/txt2kg/assets/frontend/app/graph3d/page.tsx b/nvidia/txt2kg/assets/frontend/app/graph3d/page.tsx index 2e6dfc2..96b5196 100644 --- a/nvidia/txt2kg/assets/frontend/app/graph3d/page.tsx +++ b/nvidia/txt2kg/assets/frontend/app/graph3d/page.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" /** diff --git a/nvidia/txt2kg/assets/frontend/app/layout.tsx b/nvidia/txt2kg/assets/frontend/app/layout.tsx index 1de1542..e28b19d 100644 --- a/nvidia/txt2kg/assets/frontend/app/layout.tsx +++ b/nvidia/txt2kg/assets/frontend/app/layout.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import type React from "react" import type { Metadata } from "next" import { Inter } from "next/font/google" @@ -43,9 +59,6 @@ export default function RootLayout({
txt2kg - - Powered by NVIDIA AI -
diff --git a/nvidia/txt2kg/assets/frontend/app/page.tsx b/nvidia/txt2kg/assets/frontend/app/page.tsx index 741415e..2289d69 100644 --- a/nvidia/txt2kg/assets/frontend/app/page.tsx +++ b/nvidia/txt2kg/assets/frontend/app/page.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useState, useEffect } from "react" diff --git a/nvidia/txt2kg/assets/frontend/app/rag/metrics/page.tsx b/nvidia/txt2kg/assets/frontend/app/rag/metrics/page.tsx index 304ad72..43986e8 100644 --- a/nvidia/txt2kg/assets/frontend/app/rag/metrics/page.tsx +++ b/nvidia/txt2kg/assets/frontend/app/rag/metrics/page.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client"; import { useState, useEffect } from "react"; @@ -17,6 +33,7 @@ interface MetricsData { recall: number; f1Score: number; topQueries: { query: string; count: number }[]; + queryTimesByMode?: Record; queryLogStats?: { totalQueryLogs: number; totalExecutions: number; diff --git a/nvidia/txt2kg/assets/frontend/app/rag/page.tsx b/nvidia/txt2kg/assets/frontend/app/rag/page.tsx index 3de4886..f5d7186 100644 --- a/nvidia/txt2kg/assets/frontend/app/rag/page.tsx +++ b/nvidia/txt2kg/assets/frontend/app/rag/page.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client"; import { useState, useEffect } from "react"; @@ -12,6 +28,7 @@ import { ArrowLeft, BarChart2, Search as SearchIcon } from "lucide-react"; export default function RagPage() { const router = useRouter(); const [results, setResults] = useState(null); + const [llmAnswer, setLlmAnswer] = useState(null); const [isLoading, setIsLoading] = useState(false); const [errorMessage, setErrorMessage] = useState(null); const [vectorEnabled, setVectorEnabled] = useState(false); @@ -20,6 +37,7 @@ export default function RagPage() { avgRelevance: number; precision: number; recall: number; + queryTimesByMode?: Record; } | null>(null); const [currentParams, setCurrentParams] = useState({ kNeighbors: 4096, @@ -64,7 +82,8 @@ export default function RagPage() { avgQueryTime: data.avgQueryTime, avgRelevance: data.avgRelevance, precision: data.precision, - recall: data.recall + recall: data.recall, + queryTimesByMode: data.queryTimesByMode }); } } catch (error) { @@ -84,12 +103,20 @@ export default function RagPage() { let resultCount = 0; let relevanceScore = 0; + // Debug logging + console.log('πŸ” Query params:', { + usePureRag: params.usePureRag, + useVectorSearch: params.useVectorSearch, + vectorEnabled, + queryMode: params.queryMode + }); + try { // If using pure RAG (Pinecone + LangChain) without graph search if (params.usePureRag) { queryMode = 'pure-rag'; try { - console.log('Using pure RAG with just Pinecone and LangChain for query:', query); + console.log('Using pure RAG with Qdrant and NVIDIA LLM for query:', query); const ragResponse = await fetch('/api/rag-query', { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -101,17 +128,22 @@ export default function RagPage() { if (ragResponse.ok) { const data = await ragResponse.json(); + console.log('πŸ“₯ RAG Response data:', { + hasAnswer: !!data.answer, + answerLength: data.answer?.length, + documentCount: data.documentCount + }); // Handle the answer - we might need to display differently than triples if (data.answer) { - // Special UI handling for text answer rather than triples - setResults([{ - subject: 'Answer', - predicate: '', - object: data.answer, - usedFallback: data.usedFallback - }]); - - resultCount = 1; + console.log('βœ… Setting answer in results:', data.answer.substring(0, 100) + '...'); + + // Set the LLM answer for display (same as traditional mode) + setLlmAnswer(data.answer); + + // Set empty results array since Pure RAG doesn't return triples + setResults([]); + + resultCount = data.documentCount || 0; relevanceScore = data.relevanceScore || 0; // Log the query with performance metrics @@ -121,7 +153,7 @@ export default function RagPage() { resultCount }); - console.log('Pure RAG query completed successfully'); + console.log(`βœ… Pure RAG query completed. Retrieved ${resultCount} document chunks`); setIsLoading(false); return; } @@ -136,8 +168,8 @@ export default function RagPage() { } } - // If we have vector embeddings, use enhanced query with metadata - if (vectorEnabled && params.useVectorSearch) { + // If we have vector embeddings AND explicitly selected vector search, use enhanced query with metadata + if (vectorEnabled && params.useVectorSearch && !params.usePureRag) { queryMode = 'vector-search'; try { console.log('Using enhanced RAG with LangChain for query:', query); @@ -184,35 +216,71 @@ export default function RagPage() { } } - // Call the traditional backend API as fallback or if explicitly selected + // Call the LLM-enhanced graph query API + console.log('βœ… Using Graph Search + LLM approach'); queryMode = 'traditional'; - const response = await fetch(`/api/query`, { + + // Get selected LLM model from localStorage + let llmModel = undefined; + let llmProvider = undefined; + try { + const savedModel = localStorage.getItem("selectedModelForRAG"); + if (savedModel) { + const modelData = JSON.parse(savedModel); + llmModel = modelData.model; + llmProvider = modelData.provider; + console.log(`Using LLM: ${llmModel} (${llmProvider})`); + } + } catch (e) { + console.warn("Could not load selected LLM model, using default"); + } + + const response = await fetch(`/api/graph-query-llm`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ query, - kNeighbors: params.kNeighbors, - fanout: params.fanout, - numHops: params.numHops, - topK: params.topK, - queryMode: queryMode, // Explicitly pass the query mode - useTraditional: true // Force use of the direct pattern matching approach + topK: params.topK || 5, + useTraditional: true, + llmModel, + llmProvider }), }); if (!response.ok) { const errorData = await response.json(); - throw new Error(errorData.error || 'Failed to query the RAG backend'); + throw new Error(errorData.error || 'Failed to query with LLM'); } const data = await response.json(); + + // Log sample of retrieved triples for debugging + console.log('πŸ“Š Retrieved Triples (sample):', data.triples.slice(0, 3)); + console.log('πŸ€– LLM-Generated Answer (preview):', data.answer?.substring(0, 200) + '...'); + console.log('πŸ“ˆ Triple Count:', data.count); + + // DEBUG: Check if depth/pathLength are present in received data + if (data.triples && data.triples.length > 0) { + console.log('πŸ” First triple structure:', JSON.stringify(data.triples[0], null, 2)); + console.log('πŸ” Has depth?', 'depth' in data.triples[0]); + console.log('πŸ” Has pathLength?', 'pathLength' in data.triples[0]); + } - // Update the results - setResults(data.relevantTriples || []); + // Update the results with the triples (for display) + setResults(data.triples || []); resultCount = data.count || 0; - relevanceScore = data.relevanceScore || 0; + relevanceScore = 0; // No relevance score for traditional search + + // Store the LLM answer for display + if (data.answer) { + console.log('βœ… Setting llmAnswer state (length:', data.answer.length, 'chars)'); + setLlmAnswer(data.answer); + } else { + console.log('⚠️ No answer in response'); + setLlmAnswer(null); + } // Log the query with performance metrics logQuery(query, queryMode, { @@ -279,6 +347,7 @@ export default function RagPage() { const clearResults = () => { setResults(null); + setLlmAnswer(null); setErrorMessage(null); }; @@ -318,22 +387,34 @@ export default function RagPage() {
-
- Avg. Query Time: - {metrics.avgQueryTime > 0 ? `${metrics.avgQueryTime.toFixed(2)}ms` : "No data"} -
-
- Relevance Score: - {metrics.avgRelevance > 0 ? `${(metrics.avgRelevance * 100).toFixed(1)}%` : "No data"} -
-
- Precision: - {metrics.precision > 0 ? `${(metrics.precision * 100).toFixed(1)}%` : "No data"} -
-
- Recall: - {metrics.recall > 0 ? `${(metrics.recall * 100).toFixed(1)}%` : "No data"} -
+ {/* Query times by mode */} + {metrics.queryTimesByMode && Object.keys(metrics.queryTimesByMode).length > 0 ? ( + <> + {metrics.queryTimesByMode['pure-rag'] !== undefined && ( +
+ Pure RAG: + {(metrics.queryTimesByMode['pure-rag'] / 1000).toFixed(2)}s +
+ )} + {metrics.queryTimesByMode['traditional'] !== undefined && ( +
+ Graph Search: + {(metrics.queryTimesByMode['traditional'] / 1000).toFixed(2)}s +
+ )} + {metrics.queryTimesByMode['vector-search'] !== undefined && ( +
+ GraphRAG: + {(metrics.queryTimesByMode['vector-search'] / 1000).toFixed(2)}s +
+ )} + + ) : ( +
+ Avg. Query Time: + {metrics.avgQueryTime > 0 ? `${metrics.avgQueryTime.toFixed(2)}ms` : "No data"} +
+ )}
)} @@ -349,14 +430,81 @@ export default function RagPage() { vectorEnabled={vectorEnabled} /> + {/* LLM Answer Section */} + {llmAnswer && ( +
+
+
+ +
+

Answer

+ {currentParams.queryMode && ( + + {currentParams.queryMode === 'pure-rag' ? 'Pure RAG' : + currentParams.queryMode === 'vector-search' ? 'GraphRAG' : + 'Graph Search'} + + )} +
+
+ {(() => { + // Parse tags + const thinkMatch = llmAnswer.match(/([\s\S]*?)<\/think>/); + const thinkContent = thinkMatch ? thinkMatch[1].trim() : null; + const mainAnswer = thinkContent + ? llmAnswer.replace(/[\s\S]*?<\/think>/, '').trim() + : llmAnswer; + + return ( + <> + {thinkContent && ( +
+ + + + + Reasoning Process + +
+ {thinkContent} +
+
+ )} +
+
$1') + .replace(/\*(.*?)\*/g, '$1') + }} + /> +
+ + ); + })()} +
+
+ )} + {/* Results Section */} - {results && results.length > 0 && ( + {results && results.length > 0 && !currentParams.usePureRag && (
-

Results ({results.length})

+

+ {llmAnswer ? `Retrieved Knowledge (${results.length})` : `Results (${results.length})`} +

+ {results.some((r: any) => r.pathLength && r.pathLength > 1) && ( + + + + + Multi-hop enabled + + )}
{results.map((triple, index) => ( @@ -389,8 +537,33 @@ export default function RagPage() {
)} {triple.confidence && !currentParams.usePureRag && ( -
- Confidence: {(triple.confidence * 100).toFixed(1)}% +
+
+
+ + Confidence: {(triple.confidence * 100).toFixed(1)}% + +
+ {triple.depth !== undefined && ( +
+ + + + + Hop: {triple.depth + 1} + +
+ )} + {triple.pathLength !== undefined && triple.pathLength > 1 && ( +
+ + + + + Multi-hop path (length: {triple.pathLength}) + +
+ )}
)}
@@ -399,7 +572,7 @@ export default function RagPage() {
)} - {results && results.length === 0 && !isLoading && ( + {results && results.length === 0 && !isLoading && !currentParams.usePureRag && (
diff --git a/nvidia/txt2kg/assets/frontend/app/test-large-graph/page.tsx b/nvidia/txt2kg/assets/frontend/app/test-large-graph/page.tsx index bbebef3..20ff789 100644 --- a/nvidia/txt2kg/assets/frontend/app/test-large-graph/page.tsx +++ b/nvidia/txt2kg/assets/frontend/app/test-large-graph/page.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import React, { useState, useEffect } from "react" diff --git a/nvidia/txt2kg/assets/frontend/app/test-million-nodes/page.tsx b/nvidia/txt2kg/assets/frontend/app/test-million-nodes/page.tsx index aec3ba3..2ae800b 100644 --- a/nvidia/txt2kg/assets/frontend/app/test-million-nodes/page.tsx +++ b/nvidia/txt2kg/assets/frontend/app/test-million-nodes/page.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import React, { useState, useEffect, useCallback, useMemo } from "react" diff --git a/nvidia/txt2kg/assets/frontend/app/test-webgpu-clustering/page.tsx b/nvidia/txt2kg/assets/frontend/app/test-webgpu-clustering/page.tsx index 3863f9e..8b4be39 100644 --- a/nvidia/txt2kg/assets/frontend/app/test-webgpu-clustering/page.tsx +++ b/nvidia/txt2kg/assets/frontend/app/test-webgpu-clustering/page.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" // @ts-nocheck diff --git a/nvidia/txt2kg/assets/frontend/components/advanced-options.tsx b/nvidia/txt2kg/assets/frontend/components/advanced-options.tsx index 5922a0a..167179f 100644 --- a/nvidia/txt2kg/assets/frontend/components/advanced-options.tsx +++ b/nvidia/txt2kg/assets/frontend/components/advanced-options.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import React, { useState } from "react"; import { ChevronDown, ChevronRight } from "lucide-react"; import { cn } from "@/lib/utils"; diff --git a/nvidia/txt2kg/assets/frontend/components/api-key-prompt.tsx b/nvidia/txt2kg/assets/frontend/components/api-key-prompt.tsx index 486aa3c..008fc61 100644 --- a/nvidia/txt2kg/assets/frontend/components/api-key-prompt.tsx +++ b/nvidia/txt2kg/assets/frontend/components/api-key-prompt.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import type React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/client-init.tsx b/nvidia/txt2kg/assets/frontend/components/client-init.tsx index 5e7fe85..625cf3d 100644 --- a/nvidia/txt2kg/assets/frontend/components/client-init.tsx +++ b/nvidia/txt2kg/assets/frontend/components/client-init.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useEffect } from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/database-connection.tsx b/nvidia/txt2kg/assets/frontend/components/database-connection.tsx index e1ddc80..4ddaa35 100644 --- a/nvidia/txt2kg/assets/frontend/components/database-connection.tsx +++ b/nvidia/txt2kg/assets/frontend/components/database-connection.tsx @@ -1,7 +1,23 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useState, useEffect } from "react" -import { Network, Database, Zap, AlertCircle, RefreshCw, ChevronDown, ChevronUp, InfoIcon, Trash2 } from "lucide-react" +import { Network, Database, Zap, AlertCircle, RefreshCw, ChevronDown, ChevronUp, InfoIcon, Trash2, LogOut } from "lucide-react" import { Badge } from '@/components/ui/badge' import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' import { Button } from "@/components/ui/button" @@ -157,15 +173,20 @@ export function DatabaseConnection({ className }: DatabaseConnectionProps) { try { const response = await fetch('/api/pinecone-diag/stats'); const data = await response.json(); - + if (response.ok) { setVectorStats({ nodes: typeof data.totalVectorCount === 'number' ? data.totalVectorCount : 0, relationships: 0, // Vector DB doesn't store relationships source: data.source || 'unknown', - httpHealthy: data.httpHealthy - }); - + httpHealthy: data.httpHealthy, + // Store additional Qdrant stats + ...(data.status && { status: data.status }), + ...(data.vectorSize && { vectorSize: data.vectorSize }), + ...(data.distance && { distance: data.distance }), + ...(data.url && { url: data.url }), + } as any); + // If we have a healthy HTTP connection, we're connected if (data.httpHealthy) { setVectorConnectionStatus("connected"); @@ -364,39 +385,65 @@ export function DatabaseConnection({ className }: DatabaseConnectionProps) { )}
- + + + + + + +

{graphConnectionStatus === "checking" ? "Checking..." : "Refresh connection"}

+
+
+
{graphConnectionStatus === "connected" ? ( <> - + + + + + + +

Disconnect

+
+
+
- - - + + + + + + + + +

Clear database

+
+
+
Clear Database @@ -487,21 +534,33 @@ export function DatabaseConnection({ className }: DatabaseConnectionProps) { <>
- Pinecone + Qdrant - direct-http + {(vectorStats as any).url || 'http://qdrant:6333'}
- - {vectorStats.nodes > 0 && ( -
-
- - {vectorStats.nodes.toLocaleString()} vectors -
+ +
+
+ + {vectorStats.nodes.toLocaleString()} vectors indexed
- )} + + {(vectorStats as any).status && ( +
+ + Status: {(vectorStats as any).status} +
+ )} + + {(vectorStats as any).vectorSize && ( +
+ + {(vectorStats as any).vectorSize}d ({(vectorStats as any).distance}) +
+ )} +
)} @@ -520,59 +579,85 @@ export function DatabaseConnection({ className }: DatabaseConnectionProps) { )}
- - + + + + + + +

{vectorConnectionStatus === "checking" ? "Checking..." : "Refresh connection"}

+
+
+
+ {vectorConnectionStatus === "connected" ? ( <> - - + + + + + + +

Disconnect

+
+
+
+ - - - + + + + + + + + +

Clear database

+
+
+
- Clear Pinecone Database + Clear Qdrant Database - Are you sure you want to clear all data from the Pinecone database? This action cannot be undone. + Are you sure you want to clear all data from the Qdrant vector database? This action cannot be undone. Warning - This will permanently delete all vectors from the Pinecone database. + This will permanently delete all vectors from the Qdrant database. -
- { - setGpuPreferred(checked) - if (checked && activeTab === 'threejs') { - setActiveTab('pygraphistry') - } - }} - /> - + + + WebGPU Accelerated +
- - -
- - - - Client-Side (Three.js) - WebGPU - - - - Server-Side (PyGraphistry) - GPU - - -
- - -
- -
-
- - -
- {processedGraphData ? ( - - ) : ( -
-
-
- No graph data available for PyGraphistry visualization -
-
- Please load graph data to enable GPU-accelerated visualization -
-
-
- )} -
-
-
+ +
+ +
diff --git a/nvidia/txt2kg/assets/frontend/components/fallback-graph.tsx b/nvidia/txt2kg/assets/frontend/components/fallback-graph.tsx index 7c96df3..e5414c8 100644 --- a/nvidia/txt2kg/assets/frontend/components/fallback-graph.tsx +++ b/nvidia/txt2kg/assets/frontend/components/fallback-graph.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import type React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/force-graph-wrapper.tsx b/nvidia/txt2kg/assets/frontend/components/force-graph-wrapper.tsx index 6b94b65..c74bae3 100644 --- a/nvidia/txt2kg/assets/frontend/components/force-graph-wrapper.tsx +++ b/nvidia/txt2kg/assets/frontend/components/force-graph-wrapper.tsx @@ -1,10 +1,25 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import React, { useEffect, useRef, useState, useCallback } from "react" import type { Triple } from "@/utils/text-processing" import { Maximize2, Minimize2, Pause, Play, RefreshCw, ZoomIn, X, LayoutGrid } from "lucide-react" import { WebGPUClusteringEngine } from "@/utils/webgpu-clustering" -import { EnhancedWebGPUClusteringEngine } from "@/utils/remote-webgpu-clustering" import * as d3 from 'd3' import * as THREE from 'three' @@ -389,7 +404,7 @@ export function ForceGraphWrapper({ const [isInitialized, setIsInitialized] = useState(false); // Add WebGPU clustering engine ref - const clusteringEngineRef = useRef(null); // Can be WebGPUClusteringEngine or EnhancedWebGPUClusteringEngine + const clusteringEngineRef = useRef(null); // Track if WebGPU clustering is available const [isClusteringAvailable, setIsClusteringAvailable] = useState(false); // Track if clustering is enabled @@ -1498,7 +1513,7 @@ export function ForceGraphWrapper({ } }, [graphRef.current, jsonData]); - // Enhanced WebGPU clustering initialization for 3D views with remote fallback + // WebGPU clustering initialization for 3D views useEffect(() => { async function initClustering() { try { @@ -1506,36 +1521,22 @@ export function ForceGraphWrapper({ if (layoutType === '3d' && !clusteringEngineRef.current) { console.log("πŸ”§ Initializing clustering engine for 3D view..."); - // Use enhanced clustering engine for 3D views with remote fallback - const enhancedEngine = new EnhancedWebGPUClusteringEngine([32, 18, 24], 'http://localhost:8083'); + // Use WebGPU clustering engine for 3D views + const engine = new WebGPUClusteringEngine([32, 18, 24]); console.log("⏳ Waiting for engine initialization..."); - // Wait longer for proper initialization (remote service check takes time) - await new Promise(resolve => setTimeout(resolve, 2000)); // Increased timeout even more + await new Promise(resolve => setTimeout(resolve, 1000)); - console.log("πŸ” Checking enhanced engine availability..."); - console.log("Engine available:", enhancedEngine.isAvailable()); - console.log("Engine using remote:", enhancedEngine.isUsingRemote()); - console.log("Engine capabilities:", enhancedEngine.getCapabilities()); + console.log("πŸ” Checking engine availability..."); + console.log("Engine available:", engine.isAvailable()); // Store the engine reference regardless of availability for debugging - clusteringEngineRef.current = enhancedEngine; + clusteringEngineRef.current = engine; - if (enhancedEngine.isAvailable()) { + if (engine.isAvailable()) { setIsClusteringAvailable(true); - - if (enhancedEngine.isUsingRemote()) { - console.log("βœ… Using remote WebGPU clustering service for 3D view"); - setUsingCpuFallback(false); // Remote GPU is available - - // Set up event listeners for remote clustering updates - enhancedEngine.on('clusteringComplete', (result: any) => { - console.log(`πŸš€ Remote clustering completed in ${result.processingTime}s`); - }); - } else { - console.log("βœ… Local WebGPU clustering engine initialized for 3D view"); - setUsingCpuFallback(false); // Local WebGPU is also not CPU fallback - } + console.log("βœ… Local WebGPU clustering engine initialized for 3D view"); + setUsingCpuFallback(false); // Auto-enable clustering for large 3D graphs if (graphData && graphData.nodes && graphData.nodes.length > 200) { @@ -2357,7 +2358,7 @@ export function ForceGraphWrapper({ try { console.log("πŸ”„ Applying GPU clustering to", graphData.nodes.length, "nodes"); - // Use the correct updateNodePositions method from EnhancedWebGPUClusteringEngine + // Use the updateNodePositions method from WebGPUClusteringEngine const success = await clusteringEngineRef.current.updateNodePositions( graphData.nodes, graphData.links || [] diff --git a/nvidia/txt2kg/assets/frontend/components/graph-actions.tsx b/nvidia/txt2kg/assets/frontend/components/graph-actions.tsx index 71bc34a..c3fb862 100644 --- a/nvidia/txt2kg/assets/frontend/components/graph-actions.tsx +++ b/nvidia/txt2kg/assets/frontend/components/graph-actions.tsx @@ -1,16 +1,27 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" -import { Network, Zap, HelpCircle } from "lucide-react" +import { Network, Zap } from "lucide-react" import { useDocuments } from "@/contexts/document-context" import { Loader2 } from "lucide-react" -import { useState } from "react" -import { Switch } from "@/components/ui/switch" -import { Label } from "@/components/ui/label" -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip" export function GraphActions() { const { documents, processDocuments, isProcessing, openGraphVisualization } = useDocuments() - const [useLangChain, setUseLangChain] = useState(false) const hasNewDocuments = documents.some((doc) => doc.status === "New") const hasProcessedDocuments = documents.some( @@ -30,7 +41,7 @@ export function GraphActions() { } await processDocuments(newDocumentIds, { - useLangChain, + useLangChain: false, useGraphTransformer: false, promptConfigs: undefined }); @@ -41,34 +52,6 @@ export function GraphActions() { return (
-
-
- { - setUseLangChain(value); - // Dispatch custom event to update other components - window.dispatchEvent(new CustomEvent('langChainToggled', { - detail: { useLangChain: value } - })); - }} - /> - - - - - - - -

- Enabling LangChain uses AI-powered knowledge extraction for more accurate triple generation. -

-
-
-
-
-
+ + {isOpen && ( + <> + {/* Backdrop */} +
setIsOpen(false)} + /> + + {/* Dropdown */} +
+
+

Select LLM for Answer Generation

+
+
+ {models.map((model) => ( + + ))} +
+
+ + )} +
+ ) +} + diff --git a/nvidia/txt2kg/assets/frontend/components/local-gpu-viewer.tsx b/nvidia/txt2kg/assets/frontend/components/local-gpu-viewer.tsx index 0158e84..0ecea45 100644 --- a/nvidia/txt2kg/assets/frontend/components/local-gpu-viewer.tsx +++ b/nvidia/txt2kg/assets/frontend/components/local-gpu-viewer.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import React, { useState, useEffect, useRef } from 'react' diff --git a/nvidia/txt2kg/assets/frontend/components/model-selector.tsx b/nvidia/txt2kg/assets/frontend/components/model-selector.tsx index 51499ed..0812c18 100644 --- a/nvidia/txt2kg/assets/frontend/components/model-selector.tsx +++ b/nvidia/txt2kg/assets/frontend/components/model-selector.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useState, useEffect, useRef } from "react" @@ -9,19 +25,19 @@ import { OllamaIcon } from "@/components/ui/ollama-icon" const baseModels = [ { id: "nvidia-nemotron", - name: "NVIDIA NeMo Llama 3.1 70B Nemotron", + name: "NVIDIA Llama 3.3 Nemotron Super 49B", icon: , - description: "NVIDIA hosted Nemotron optimized Llama 3.1 70B model", - model: "nvdev/nvidia/llama-3.1-nemotron-70b-instruct", + description: "NVIDIA hosted Nemotron Super 49B v1.5 model", + model: "nvidia/llama-3.3-nemotron-super-49b-v1.5", apiKeyName: "NVIDIA_API_KEY", baseURL: "https://integrate.api.nvidia.com/v1", }, { id: "nvidia-nemotron-nano", - name: "llama-3.1-nemotron-nano-8b-v1", + name: "NVIDIA Nemotron Nano 9B v2", icon: , - description: "NVIDIA hosted Nemotron Nano 8B model", - model: "nvdev/nvidia/llama-3.1-nemotron-nano-8b-instruct", + description: "NVIDIA hosted Nemotron Nano 9B v2 - Faster and more efficient", + model: "nvidia/nvidia-nemotron-nano-9b-v2", apiKeyName: "NVIDIA_API_KEY", baseURL: "https://integrate.api.nvidia.com/v1", }, diff --git a/nvidia/txt2kg/assets/frontend/components/nemotron-chat.tsx b/nvidia/txt2kg/assets/frontend/components/nemotron-chat.tsx index 81647fb..2a5e08b 100644 --- a/nvidia/txt2kg/assets/frontend/components/nemotron-chat.tsx +++ b/nvidia/txt2kg/assets/frontend/components/nemotron-chat.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useState, useEffect } from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/nemotron-model-hook.tsx b/nvidia/txt2kg/assets/frontend/components/nemotron-model-hook.tsx index d310f3d..d9dfa88 100644 --- a/nvidia/txt2kg/assets/frontend/components/nemotron-model-hook.tsx +++ b/nvidia/txt2kg/assets/frontend/components/nemotron-model-hook.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useState, useEffect } from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/neo4j-connection.tsx b/nvidia/txt2kg/assets/frontend/components/neo4j-connection.tsx index a93e0dc..46439c5 100644 --- a/nvidia/txt2kg/assets/frontend/components/neo4j-connection.tsx +++ b/nvidia/txt2kg/assets/frontend/components/neo4j-connection.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useState, useEffect } from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/nvidia-icon.tsx b/nvidia/txt2kg/assets/frontend/components/nvidia-icon.tsx index 1fda3b1..5efc56b 100644 --- a/nvidia/txt2kg/assets/frontend/components/nvidia-icon.tsx +++ b/nvidia/txt2kg/assets/frontend/components/nvidia-icon.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// export function NvidiaIcon({ className }: { className?: string }) { return ( diff --git a/nvidia/txt2kg/assets/frontend/components/nvidia-logo.tsx b/nvidia/txt2kg/assets/frontend/components/nvidia-logo.tsx index 34466aa..b5b469e 100644 --- a/nvidia/txt2kg/assets/frontend/components/nvidia-logo.tsx +++ b/nvidia/txt2kg/assets/frontend/components/nvidia-logo.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// export function NvidiaLogo({ className }: { className?: string }) { return ( diff --git a/nvidia/txt2kg/assets/frontend/components/ollama-connection.tsx b/nvidia/txt2kg/assets/frontend/components/ollama-connection.tsx index d314a60..a27b083 100644 --- a/nvidia/txt2kg/assets/frontend/components/ollama-connection.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ollama-connection.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useState, useEffect } from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/pinecone-connection.tsx b/nvidia/txt2kg/assets/frontend/components/pinecone-connection.tsx index 4d74753..b64ea4d 100644 --- a/nvidia/txt2kg/assets/frontend/components/pinecone-connection.tsx +++ b/nvidia/txt2kg/assets/frontend/components/pinecone-connection.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useState, useEffect } from "react" @@ -87,7 +103,7 @@ export function PineconeConnection({ className }: PineconeConnectionProps) { -

Local Pinecone stores vector embeddings in memory for semantic search

+

Qdrant stores vector embeddings for semantic search

@@ -109,34 +125,34 @@ export function PineconeConnection({ className }: PineconeConnectionProps) {

Error: {error}

{error.includes('404') && (

- The Pinecone server is running but the index doesn't exist yet. -
Or using Docker Compose: - docker-compose restart pinecone + docker compose restart qdrant

)}
@@ -144,13 +160,25 @@ export function PineconeConnection({ className }: PineconeConnectionProps) {
- Vectors: - {stats.nodes} + Qdrant + {(stats as any).url || 'http://qdrant:6333'}
- Source: - {stats.source} local + Vectors: + {stats.nodes} indexed
+ {(stats as any).status && ( +
+ Status: + {(stats as any).status} +
+ )} + {(stats as any).vectorSize && ( +
+ Dimensions: + {(stats as any).vectorSize}d ({(stats as any).distance}) +
+ )}
diff --git a/nvidia/txt2kg/assets/frontend/components/prompt-configuration.tsx b/nvidia/txt2kg/assets/frontend/components/prompt-configuration.tsx index 73f94a0..5cbb9fa 100644 --- a/nvidia/txt2kg/assets/frontend/components/prompt-configuration.tsx +++ b/nvidia/txt2kg/assets/frontend/components/prompt-configuration.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { useState, useEffect } from "react"; import { Textarea } from "@/components/ui/textarea"; import { Button } from "@/components/ui/button"; @@ -219,10 +235,6 @@ export function PromptConfiguration({ )} -
- This system prompt is used for the default triple extraction mode (without LangChain). -
-
updateParam('topK', parseInt(e.target.value))} diff --git a/nvidia/txt2kg/assets/frontend/components/remote-gpu-viewer.tsx b/nvidia/txt2kg/assets/frontend/components/remote-gpu-viewer.tsx index 085a715..9acc11e 100644 --- a/nvidia/txt2kg/assets/frontend/components/remote-gpu-viewer.tsx +++ b/nvidia/txt2kg/assets/frontend/components/remote-gpu-viewer.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import React, { useState, useEffect, useRef, useCallback } from 'react' diff --git a/nvidia/txt2kg/assets/frontend/components/s3-connection.tsx b/nvidia/txt2kg/assets/frontend/components/s3-connection.tsx index 26b132c..fe94724 100644 --- a/nvidia/txt2kg/assets/frontend/components/s3-connection.tsx +++ b/nvidia/txt2kg/assets/frontend/components/s3-connection.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useState, useEffect } from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/s3-upload-container.tsx b/nvidia/txt2kg/assets/frontend/components/s3-upload-container.tsx index 7380e3f..9f32b12 100644 --- a/nvidia/txt2kg/assets/frontend/components/s3-upload-container.tsx +++ b/nvidia/txt2kg/assets/frontend/components/s3-upload-container.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useState, useEffect } from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/s3-upload.tsx b/nvidia/txt2kg/assets/frontend/components/s3-upload.tsx index d77336f..ceee110 100644 --- a/nvidia/txt2kg/assets/frontend/components/s3-upload.tsx +++ b/nvidia/txt2kg/assets/frontend/components/s3-upload.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useState } from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/settings-modal.tsx b/nvidia/txt2kg/assets/frontend/components/settings-modal.tsx index 8b4c20b..c05cbf8 100644 --- a/nvidia/txt2kg/assets/frontend/components/settings-modal.tsx +++ b/nvidia/txt2kg/assets/frontend/components/settings-modal.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import React, { useState, useEffect } from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/tabs/ConfigureTab.tsx b/nvidia/txt2kg/assets/frontend/components/tabs/ConfigureTab.tsx index 8a461f9..7b5ad0c 100644 --- a/nvidia/txt2kg/assets/frontend/components/tabs/ConfigureTab.tsx +++ b/nvidia/txt2kg/assets/frontend/components/tabs/ConfigureTab.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import React from "react" import { Database, FileText, Cpu, Sparkles, Zap } from "lucide-react" import { ModelSelector } from "@/components/model-selector" @@ -176,9 +192,6 @@ export function ConfigureTab() {

Process Documents

-

- Extract structured knowledge triples from documents for knowledge graph construction -

diff --git a/nvidia/txt2kg/assets/frontend/components/tabs/EditTab.tsx b/nvidia/txt2kg/assets/frontend/components/tabs/EditTab.tsx index 39e69e8..77e0389 100644 --- a/nvidia/txt2kg/assets/frontend/components/tabs/EditTab.tsx +++ b/nvidia/txt2kg/assets/frontend/components/tabs/EditTab.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { TripleViewer } from "@/components/triple-viewer" import { Network } from "lucide-react" diff --git a/nvidia/txt2kg/assets/frontend/components/tabs/UploadTab.tsx b/nvidia/txt2kg/assets/frontend/components/tabs/UploadTab.tsx index 4fd18d1..2b061d2 100644 --- a/nvidia/txt2kg/assets/frontend/components/tabs/UploadTab.tsx +++ b/nvidia/txt2kg/assets/frontend/components/tabs/UploadTab.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { AlertCircle, Upload, Database, Table } from "lucide-react" import { UploadDocuments } from "@/components/upload-documents" import { S3UploadContainer } from "@/components/s3-upload-container" diff --git a/nvidia/txt2kg/assets/frontend/components/tabs/VisualizeTab.tsx b/nvidia/txt2kg/assets/frontend/components/tabs/VisualizeTab.tsx index 318560d..60f4ae0 100644 --- a/nvidia/txt2kg/assets/frontend/components/tabs/VisualizeTab.tsx +++ b/nvidia/txt2kg/assets/frontend/components/tabs/VisualizeTab.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { KnowledgeGraphViewer } from "@/components/knowledge-graph-viewer" import { Eye } from "lucide-react" diff --git a/nvidia/txt2kg/assets/frontend/components/theme-provider.tsx b/nvidia/txt2kg/assets/frontend/components/theme-provider.tsx index 198ab63..d0b221c 100644 --- a/nvidia/txt2kg/assets/frontend/components/theme-provider.tsx +++ b/nvidia/txt2kg/assets/frontend/components/theme-provider.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import type React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/theme-toggle.tsx b/nvidia/txt2kg/assets/frontend/components/theme-toggle.tsx index 08251b2..4305821 100644 --- a/nvidia/txt2kg/assets/frontend/components/theme-toggle.tsx +++ b/nvidia/txt2kg/assets/frontend/components/theme-toggle.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { Moon, Sun } from "lucide-react" diff --git a/nvidia/txt2kg/assets/frontend/components/triple-editor.tsx b/nvidia/txt2kg/assets/frontend/components/triple-editor.tsx index 2f0a5f4..8c6064d 100644 --- a/nvidia/txt2kg/assets/frontend/components/triple-editor.tsx +++ b/nvidia/txt2kg/assets/frontend/components/triple-editor.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import type React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/triple-viewer.tsx b/nvidia/txt2kg/assets/frontend/components/triple-viewer.tsx index cdde972..6497e0c 100644 --- a/nvidia/txt2kg/assets/frontend/components/triple-viewer.tsx +++ b/nvidia/txt2kg/assets/frontend/components/triple-viewer.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useState, useEffect, useRef } from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/alert-dialog.tsx b/nvidia/txt2kg/assets/frontend/components/ui/alert-dialog.tsx index 25e7b47..c80ff7b 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/alert-dialog.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/alert-dialog.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/alert.tsx b/nvidia/txt2kg/assets/frontend/components/ui/alert.tsx index 41fa7e0..e31ef4a 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/alert.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/alert.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import * as React from "react" import { cva, type VariantProps } from "class-variance-authority" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/avatar.tsx b/nvidia/txt2kg/assets/frontend/components/ui/avatar.tsx index 51e507b..361981b 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/avatar.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/avatar.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/badge.tsx b/nvidia/txt2kg/assets/frontend/components/ui/badge.tsx index f000e3e..7098007 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/badge.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/badge.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import * as React from "react" import { cva, type VariantProps } from "class-variance-authority" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/button.tsx b/nvidia/txt2kg/assets/frontend/components/ui/button.tsx index 36496a2..60b6bf5 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/button.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/button.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import * as React from "react" import { Slot } from "@radix-ui/react-slot" import { cva, type VariantProps } from "class-variance-authority" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/card.tsx b/nvidia/txt2kg/assets/frontend/components/ui/card.tsx index f62edea..3b30a32 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/card.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/card.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import * as React from "react" import { cn } from "@/lib/utils" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/checkbox.tsx b/nvidia/txt2kg/assets/frontend/components/ui/checkbox.tsx index df61a13..9dae30e 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/checkbox.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/checkbox.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/collapsible.tsx b/nvidia/txt2kg/assets/frontend/components/ui/collapsible.tsx index 9fa4894..ae651e1 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/collapsible.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/collapsible.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/dialog.tsx b/nvidia/txt2kg/assets/frontend/components/ui/dialog.tsx index c0a7b98..b269e47 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/dialog.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/dialog.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/dropdown-menu.tsx b/nvidia/txt2kg/assets/frontend/components/ui/dropdown-menu.tsx index 0fc4c0e..3d68ba6 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/dropdown-menu.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/dropdown-menu.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/input.tsx b/nvidia/txt2kg/assets/frontend/components/ui/input.tsx index 9fbdfbb..f119d1b 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/input.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/input.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import * as React from "react" import { cn } from "@/lib/utils" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/label.tsx b/nvidia/txt2kg/assets/frontend/components/ui/label.tsx index 3317f2e..46c3662 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/label.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/label.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/ollama-icon.tsx b/nvidia/txt2kg/assets/frontend/components/ui/ollama-icon.tsx index d2815be..9244adc 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/ollama-icon.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/ollama-icon.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import React from 'react' import Image from 'next/image' diff --git a/nvidia/txt2kg/assets/frontend/components/ui/pagination.tsx b/nvidia/txt2kg/assets/frontend/components/ui/pagination.tsx index ea40d19..90fc76d 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/pagination.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/pagination.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import * as React from "react" import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/popover.tsx b/nvidia/txt2kg/assets/frontend/components/ui/popover.tsx index a0ec48b..d64a062 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/popover.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/popover.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/progress.tsx b/nvidia/txt2kg/assets/frontend/components/ui/progress.tsx index 5c87ea4..ac465fb 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/progress.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/progress.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/radio-group.tsx b/nvidia/txt2kg/assets/frontend/components/ui/radio-group.tsx index e9bde17..a7002ed 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/radio-group.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/radio-group.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/scroll-area.tsx b/nvidia/txt2kg/assets/frontend/components/ui/scroll-area.tsx index 0b4a48d..9d90578 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/scroll-area.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/scroll-area.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/select.tsx b/nvidia/txt2kg/assets/frontend/components/ui/select.tsx index cbe5a36..ca4380f 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/select.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/select.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/separator.tsx b/nvidia/txt2kg/assets/frontend/components/ui/separator.tsx index 12d81c4..02919bf 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/separator.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/separator.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/sheet.tsx b/nvidia/txt2kg/assets/frontend/components/ui/sheet.tsx index a37f17b..eb25f96 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/sheet.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/sheet.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/sidebar.tsx b/nvidia/txt2kg/assets/frontend/components/ui/sidebar.tsx index eeb2d7a..c7a6784 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/sidebar.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/sidebar.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/skeleton.tsx b/nvidia/txt2kg/assets/frontend/components/ui/skeleton.tsx index 01b8b6d..d3bc78b 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/skeleton.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/skeleton.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { cn } from "@/lib/utils" function Skeleton({ diff --git a/nvidia/txt2kg/assets/frontend/components/ui/slider.tsx b/nvidia/txt2kg/assets/frontend/components/ui/slider.tsx index c31c2b3..a0d0fb5 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/slider.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/slider.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/spinner.tsx b/nvidia/txt2kg/assets/frontend/components/ui/spinner.tsx index f161715..70d0f8c 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/spinner.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/spinner.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import React from "react" import { Loader2, LucideProps } from "lucide-react" import { cn } from "@/lib/utils" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/switch.tsx b/nvidia/txt2kg/assets/frontend/components/ui/switch.tsx index bc69cf2..b90cdbd 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/switch.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/switch.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/table.tsx b/nvidia/txt2kg/assets/frontend/components/ui/table.tsx index 7f3502f..21da335 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/table.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/table.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import * as React from "react" import { cn } from "@/lib/utils" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/tabs.tsx b/nvidia/txt2kg/assets/frontend/components/ui/tabs.tsx index 4a87cf8..15d089d 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/tabs.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/tabs.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/textarea.tsx b/nvidia/txt2kg/assets/frontend/components/ui/textarea.tsx index 0ce9097..9355b31 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/textarea.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/textarea.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import * as React from "react" import { cn } from "@/lib/utils" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/toast.tsx b/nvidia/txt2kg/assets/frontend/components/ui/toast.tsx index 92b0fc8..8ee3628 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/toast.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/toast.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/toaster.tsx b/nvidia/txt2kg/assets/frontend/components/ui/toaster.tsx index 171beb4..7b36ffb 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/toaster.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/toaster.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import { useToast } from "@/hooks/use-toast" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/toggle-group.tsx b/nvidia/txt2kg/assets/frontend/components/ui/toggle-group.tsx index 1c876bb..7a384c2 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/toggle-group.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/toggle-group.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/toggle.tsx b/nvidia/txt2kg/assets/frontend/components/ui/toggle.tsx index c19bea3..7e1b4ba 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/toggle.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/toggle.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/tooltip.tsx b/nvidia/txt2kg/assets/frontend/components/ui/tooltip.tsx index 30fc44d..408a9a3 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/tooltip.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/tooltip.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import * as React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/ui/use-mobile.tsx b/nvidia/txt2kg/assets/frontend/components/ui/use-mobile.tsx index 2b0fe1d..fb88ea8 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/use-mobile.tsx +++ b/nvidia/txt2kg/assets/frontend/components/ui/use-mobile.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import * as React from "react" const MOBILE_BREAKPOINT = 768 diff --git a/nvidia/txt2kg/assets/frontend/components/ui/use-toast.ts b/nvidia/txt2kg/assets/frontend/components/ui/use-toast.ts index 02e111d..2d6649d 100644 --- a/nvidia/txt2kg/assets/frontend/components/ui/use-toast.ts +++ b/nvidia/txt2kg/assets/frontend/components/ui/use-toast.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" // Inspired by react-hot-toast library diff --git a/nvidia/txt2kg/assets/frontend/components/unified-gpu-viewer.tsx b/nvidia/txt2kg/assets/frontend/components/unified-gpu-viewer.tsx index 5a73922..8048c78 100644 --- a/nvidia/txt2kg/assets/frontend/components/unified-gpu-viewer.tsx +++ b/nvidia/txt2kg/assets/frontend/components/unified-gpu-viewer.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import React, { useState, useEffect, useRef } from 'react' diff --git a/nvidia/txt2kg/assets/frontend/components/upload-documents.tsx b/nvidia/txt2kg/assets/frontend/components/upload-documents.tsx index f3c9b4e..a069bc3 100644 --- a/nvidia/txt2kg/assets/frontend/components/upload-documents.tsx +++ b/nvidia/txt2kg/assets/frontend/components/upload-documents.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import type React from "react" diff --git a/nvidia/txt2kg/assets/frontend/components/webgpu-3d-viewer.tsx b/nvidia/txt2kg/assets/frontend/components/webgpu-3d-viewer.tsx index 122cba8..fd462ef 100644 --- a/nvidia/txt2kg/assets/frontend/components/webgpu-3d-viewer.tsx +++ b/nvidia/txt2kg/assets/frontend/components/webgpu-3d-viewer.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import React, { useEffect, useRef, useState, useCallback } from 'react' @@ -7,10 +23,9 @@ import { Badge } from '@/components/ui/badge' import { Switch } from '@/components/ui/switch' import { Alert, AlertDescription } from '@/components/ui/alert' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' -import { Loader2, Cpu, Server, Monitor, Wifi, RotateCcw } from 'lucide-react' +import { Loader2, Cpu, Monitor, RotateCcw } from 'lucide-react' import { useToast } from '@/hooks/use-toast' -import { EnhancedWebGPUClusteringEngine, RemoteWebGPUClusteringClient } from '@/utils/remote-webgpu-clustering' -import { WebRTCGraphViewer } from './webrtc-graph-viewer' +import { WebGPUClusteringEngine } from '@/utils/webgpu-clustering' import { ForceGraphWrapper } from './force-graph-wrapper' interface PerformanceMetrics { @@ -33,7 +48,7 @@ interface WebGPU3DViewerProps { } interface RenderingMode { - id: 'local' | 'hybrid' | 'webrtc' + id: 'local' | 'hybrid' name: string description: string available: boolean @@ -50,9 +65,7 @@ export function WebGPU3DViewer({ const [activeMode, setActiveMode] = useState('local') const [isInitializing, setIsInitializing] = useState(true) const [renderingModes, setRenderingModes] = useState([]) - const [clusteringEngine, setClusteringEngine] = useState(null) - const [remoteClient, setRemoteClient] = useState(null) - const [capabilities, setCapabilities] = useState(null) + const [clusteringEngine, setClusteringEngine] = useState(null) const { toast } = useToast() @@ -62,48 +75,27 @@ export function WebGPU3DViewer({ try { setIsInitializing(true) - // Initialize enhanced clustering engine - const engine = new EnhancedWebGPUClusteringEngine([32, 18, 24], remoteServiceUrl) + // Initialize local WebGPU clustering engine + const engine = new WebGPUClusteringEngine([32, 18, 24]) await new Promise(resolve => setTimeout(resolve, 200)) // Give time to initialize - // Initialize remote client for WebRTC capabilities - const client = new RemoteWebGPUClusteringClient(remoteServiceUrl, false) // Disable proxy mode for WebSocket - const remoteAvailable = await client.checkAvailability() - const remoteCaps = client.getCapabilities() - setClusteringEngine(engine) - if (remoteAvailable) { - console.log('Remote client available, setting client state') - setRemoteClient(client) - setCapabilities(remoteCaps) - } else { - console.log('Remote client not available') - setRemoteClient(null) - setCapabilities(null) - } - // Determine available rendering modes const modes: RenderingMode[] = [ { id: 'local', name: 'Local WebGPU', description: 'Client-side WebGPU clustering and Three.js rendering', - available: Boolean(engine.isAvailable() && !engine.isUsingRemote()), - recommended: Boolean(engine.isAvailable() && !engine.isUsingRemote()) + available: Boolean(engine.isAvailable()), + recommended: true }, { id: 'hybrid', - name: 'Hybrid GPU/CPU', - description: 'Server GPU clustering, client CPU rendering', - available: Boolean(remoteAvailable && remoteCaps?.modes?.hybrid?.available), - recommended: Boolean(!engine.isAvailable() || engine.isUsingRemote()) - }, - { - id: 'webrtc', - name: 'WebRTC Streaming', - description: 'Full server GPU rendering streamed to browser', - available: Boolean(remoteAvailable && remoteCaps?.modes?.webrtc_stream?.available) + name: 'CPU Fallback', + description: 'CPU-based rendering fallback', + available: true, + recommended: !engine.isAvailable() } ] @@ -417,63 +409,30 @@ export function WebGPU3DViewer({ - {/* WebRTC Streaming Mode */} - - - {/* Service Status */} - {capabilities && ( + {clusteringEngine && ( Service Status -
+

Local WebGPU

- - {clusteringEngine?.isAvailable() && !clusteringEngine?.isUsingRemote() ? 'Available' : 'Not Available'} + + {clusteringEngine?.isAvailable() ? 'Available' : 'Not Available'}
-

Remote Service

- - {remoteClient ? 'Connected' : 'Disconnected'} - -
- -
-

Server GPU

- - {capabilities?.gpuAcceleration?.rapidsAvailable ? 'RAPIDS' : 'CPU Only'} - -
- -
-

WebRTC

- - {capabilities?.modes?.webrtc_stream?.available ? 'Available' : 'Not Available'} +

Clustering

+ + {clusteringEngine?.isAvailable() ? 'GPU Accelerated' : 'CPU Fallback'}
- - {capabilities && ( -
-

- Cluster dimensions: {capabilities.clusterDimensions?.join(' Γ— ')} - ({capabilities.maxClusterCount?.toLocaleString()} total clusters) -

-
- )} )} diff --git a/nvidia/txt2kg/assets/frontend/components/webrtc-graph-viewer.tsx b/nvidia/txt2kg/assets/frontend/components/webrtc-graph-viewer.tsx index bd8bf8c..16b6940 100644 --- a/nvidia/txt2kg/assets/frontend/components/webrtc-graph-viewer.tsx +++ b/nvidia/txt2kg/assets/frontend/components/webrtc-graph-viewer.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import React, { useEffect, useRef, useState, useCallback } from 'react' diff --git a/nvidia/txt2kg/assets/frontend/contexts/document-context.tsx b/nvidia/txt2kg/assets/frontend/contexts/document-context.tsx index ed68ef4..bbe728d 100644 --- a/nvidia/txt2kg/assets/frontend/contexts/document-context.tsx +++ b/nvidia/txt2kg/assets/frontend/contexts/document-context.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" import type React from "react" @@ -379,7 +395,8 @@ export function DocumentProvider({ children }: { children: React.ReactNode }) { console.log(`πŸ¦™ Using Ollama model: ${requestBody.ollamaModel}`); } else if (model.id === "nvidia-nemotron" || model.id === "nvidia-nemotron-nano") { requestBody.llmProvider = "nvidia"; - console.log(`πŸ–₯️ Using NVIDIA model: ${model.id}`); + requestBody.nvidiaModel = model.model; // Pass the actual model name + console.log(`πŸ–₯️ Using NVIDIA model: ${model.model}`); } } catch (e) { // Ignore parsing errors, will use default @@ -498,8 +515,51 @@ export function DocumentProvider({ children }: { children: React.ReactNode }) { setIsProcessing(true); try { + // Check which documents are already processed in ArangoDB + console.log('πŸ” Checking which documents are already processed in ArangoDB...'); + let alreadyProcessedDocs: Set = new Set(); + + try { + const response = await fetch('/api/graph-db/check-document', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + documentNames: docsToProcess.map(d => d.name) + }) + }); + + if (response.ok) { + const result = await response.json(); + if (result.processedDocuments) { + Object.entries(result.processedDocuments).forEach(([docName, isProcessed]) => { + if (isProcessed) { + alreadyProcessedDocs.add(docName); + } + }); + console.log(`βœ… Found ${alreadyProcessedDocs.size} documents already processed in ArangoDB:`, Array.from(alreadyProcessedDocs)); + } + } + } catch (checkError) { + console.warn('⚠️ Could not check for already processed documents, continuing anyway:', checkError); + } + // Process each document sequentially for (const doc of docsToProcess) { + // Skip if document is already processed in ArangoDB + if (alreadyProcessedDocs.has(doc.name)) { + console.log(`⏭️ Skipping document "${doc.name}" - already processed in ArangoDB`); + updateDocumentStatus(doc.id, "Processed", { + triples: doc.triples || [], + graph: doc.graph, + error: undefined + }); + toast({ + title: "Document Skipped", + description: `"${doc.name}" is already stored in ArangoDB`, + duration: 3000, + }); + continue; + } // Update status to Processing before we begin updateDocumentStatus(doc.id, "Processing"); diff --git a/nvidia/txt2kg/assets/frontend/hooks/use-keyboard-shortcuts.ts b/nvidia/txt2kg/assets/frontend/hooks/use-keyboard-shortcuts.ts index be36792..4ab5695 100644 --- a/nvidia/txt2kg/assets/frontend/hooks/use-keyboard-shortcuts.ts +++ b/nvidia/txt2kg/assets/frontend/hooks/use-keyboard-shortcuts.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { useEffect } from 'react' interface KeyboardShortcut { diff --git a/nvidia/txt2kg/assets/frontend/hooks/use-mobile.tsx b/nvidia/txt2kg/assets/frontend/hooks/use-mobile.tsx index 2b0fe1d..fb88ea8 100644 --- a/nvidia/txt2kg/assets/frontend/hooks/use-mobile.tsx +++ b/nvidia/txt2kg/assets/frontend/hooks/use-mobile.tsx @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import * as React from "react" const MOBILE_BREAKPOINT = 768 diff --git a/nvidia/txt2kg/assets/frontend/hooks/use-shift-select.ts b/nvidia/txt2kg/assets/frontend/hooks/use-shift-select.ts index fd5b964..bb1c980 100644 --- a/nvidia/txt2kg/assets/frontend/hooks/use-shift-select.ts +++ b/nvidia/txt2kg/assets/frontend/hooks/use-shift-select.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { useState, useCallback, useRef } from 'react' interface UseShiftSelectOptions { diff --git a/nvidia/txt2kg/assets/frontend/hooks/use-toast.ts b/nvidia/txt2kg/assets/frontend/hooks/use-toast.ts index 02e111d..2d6649d 100644 --- a/nvidia/txt2kg/assets/frontend/hooks/use-toast.ts +++ b/nvidia/txt2kg/assets/frontend/hooks/use-toast.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// "use client" // Inspired by react-hot-toast library diff --git a/nvidia/txt2kg/assets/frontend/lib/arangodb-loader.ts b/nvidia/txt2kg/assets/frontend/lib/arangodb-loader.ts index 837719b..34ee378 100644 --- a/nvidia/txt2kg/assets/frontend/lib/arangodb-loader.ts +++ b/nvidia/txt2kg/assets/frontend/lib/arangodb-loader.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { ArangoDBService } from './arangodb'; /** diff --git a/nvidia/txt2kg/assets/frontend/lib/arangodb.ts b/nvidia/txt2kg/assets/frontend/lib/arangodb.ts index dafd760..b038b21 100644 --- a/nvidia/txt2kg/assets/frontend/lib/arangodb.ts +++ b/nvidia/txt2kg/assets/frontend/lib/arangodb.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { Database, aql } from 'arangojs'; /** @@ -9,6 +25,7 @@ export class ArangoDBService { private static instance: ArangoDBService; private collectionName: string = 'entities'; private edgeCollectionName: string = 'relationships'; + private documentsCollectionName: string = 'processed_documents'; private constructor() {} @@ -75,6 +92,16 @@ export class ArangoDBService { }); } + // Create documents collection if it doesn't exist + if (!collectionNames.includes(this.documentsCollectionName)) { + await this.db.createCollection(this.documentsCollectionName); + await this.db.collection(this.documentsCollectionName).ensureIndex({ + type: 'persistent', + fields: ['documentName'], + unique: true + }); + } + console.log('ArangoDB initialized successfully'); } catch (error) { console.error('Failed to initialize ArangoDB:', error); @@ -250,6 +277,88 @@ export class ArangoDBService { return await collection.save({ name }); } + /** + * Check if a document has already been processed and stored in ArangoDB + * @param documentName - Name of the document to check + * @returns Promise resolving to true if document exists, false otherwise + */ + public async isDocumentProcessed(documentName: string): Promise { + if (!this.db) { + throw new Error('ArangoDB connection not initialized. Call initialize() first.'); + } + + try { + const existing = await this.executeQuery( + `FOR d IN ${this.documentsCollectionName} FILTER d.documentName == @documentName RETURN d`, + { documentName } + ); + return existing.length > 0; + } catch (error) { + console.error('Error checking if document is processed:', error); + return false; + } + } + + /** + * Mark a document as processed in ArangoDB + * @param documentName - Name of the document + * @param tripleCount - Number of triples stored for this document + * @returns Promise resolving when the document is marked as processed + */ + public async markDocumentAsProcessed(documentName: string, tripleCount: number): Promise { + if (!this.db) { + throw new Error('ArangoDB connection not initialized. Call initialize() first.'); + } + + try { + const collection = this.db.collection(this.documentsCollectionName); + await collection.save({ + documentName, + tripleCount, + processedAt: new Date().toISOString() + }); + console.log(`Marked document "${documentName}" as processed with ${tripleCount} triples`); + } catch (error) { + // If error is due to unique constraint (document already exists), update it instead + if (error && typeof error === 'object' && 'errorNum' in error && error.errorNum === 1210) { + console.log(`Document "${documentName}" already exists, updating...`); + await this.executeQuery( + `FOR d IN ${this.documentsCollectionName} + FILTER d.documentName == @documentName + UPDATE d WITH { tripleCount: @tripleCount, processedAt: @processedAt } IN ${this.documentsCollectionName}`, + { + documentName, + tripleCount, + processedAt: new Date().toISOString() + } + ); + } else { + console.error('Error marking document as processed:', error); + throw error; + } + } + } + + /** + * Get all processed documents from ArangoDB + * @returns Promise resolving to array of processed document names + */ + public async getProcessedDocuments(): Promise { + if (!this.db) { + throw new Error('ArangoDB connection not initialized. Call initialize() first.'); + } + + try { + const documents = await this.executeQuery( + `FOR d IN ${this.documentsCollectionName} RETURN d.documentName` + ); + return documents; + } catch (error) { + console.error('Error getting processed documents:', error); + return []; + } + } + /** * Get graph data in a format compatible with the existing application * @returns Promise resolving to nodes and relationships @@ -397,6 +506,178 @@ export class ArangoDBService { } } + /** + * Perform graph traversal to find relevant triples using ArangoDB's native graph capabilities + * @param keywords - Array of keywords to search for + * @param maxDepth - Maximum traversal depth (default: 2) + * @param maxResults - Maximum number of results to return (default: 100) + * @returns Promise resolving to array of triples with relevance scores + */ + public async graphTraversal( + keywords: string[], + maxDepth: number = 2, + maxResults: number = 100 + ): Promise> { + console.log(`[ArangoDB] graphTraversal called with keywords: ${keywords.join(', ')}`); + + if (!this.db) { + throw new Error('ArangoDB connection not initialized. Call initialize() first.'); + } + + try { + // Build case-insensitive keyword matching conditions + const keywordConditions = keywords + .filter(kw => kw.length > 2) // Filter short words + .map(kw => kw.toLowerCase()); + + if (keywordConditions.length === 0) { + return []; + } + + // AQL query that: + // 1. Finds seed nodes matching keywords + // 2. Performs graph traversal from those nodes + // 3. Scores results based on keyword matches and depth + const query = ` + // Find all entities matching keywords (case-insensitive) + LET seedNodes = ( + FOR entity IN ${this.collectionName} + LET lowerName = LOWER(entity.name) + LET matches = ( + FOR keyword IN @keywords + FILTER CONTAINS(lowerName, keyword) + RETURN 1 + ) + FILTER LENGTH(matches) > 0 + RETURN { + node: entity, + matchCount: LENGTH(matches) + } + ) + + // Perform graph traversal from seed nodes + // Multi-hop: Extract ALL edges in each path, not just the final edge + LET traversalResults = ( + FOR seed IN seedNodes + FOR v, e, p IN 0..@maxDepth ANY seed.node._id ${this.edgeCollectionName} + OPTIONS {uniqueVertices: 'global', bfs: true} + FILTER e != null + + // Extract all edges from the path for multi-hop context + LET pathEdges = ( + FOR edgeIdx IN 0..(LENGTH(p.edges) - 1) + LET pathEdge = p.edges[edgeIdx] + LET subjectEntity = DOCUMENT(pathEdge._from) + LET objectEntity = DOCUMENT(pathEdge._to) + LET subjectLower = LOWER(subjectEntity.name) + LET objectLower = LOWER(objectEntity.name) + LET predicateLower = LOWER(pathEdge.type) + + // Calculate score for this edge + LET subjectMatches = ( + FOR kw IN @keywords + FILTER CONTAINS(subjectLower, kw) + LET isExact = (subjectLower == kw) + RETURN isExact ? 1000 : (LENGTH(kw) * LENGTH(kw)) + ) + LET objectMatches = ( + FOR kw IN @keywords + FILTER CONTAINS(objectLower, kw) + LET isExact = (objectLower == kw) + RETURN isExact ? 1000 : (LENGTH(kw) * LENGTH(kw)) + ) + LET predicateMatches = ( + FOR kw IN @keywords + FILTER CONTAINS(predicateLower, kw) + LET isExact = (predicateLower == kw) + RETURN isExact ? 50 : (LENGTH(kw) * LENGTH(kw)) + ) + + LET totalScore = SUM(subjectMatches) + SUM(objectMatches) + SUM(predicateMatches) + + // Depth penalty (edges earlier in path get slight boost) + LET depthPenalty = 1.0 / (1.0 + (edgeIdx * 0.1)) + + LET confidence = MIN([totalScore * depthPenalty / 1000.0, 1.0]) + + FILTER confidence > 0 + + RETURN { + subject: subjectEntity.name, + predicate: pathEdge.type, + object: objectEntity.name, + confidence: confidence, + depth: edgeIdx, + _edgeId: pathEdge._id, + pathLength: LENGTH(p.edges) + } + ) + + // Return all edges from this path + FOR pathTriple IN pathEdges + RETURN pathTriple + ) + + // Remove duplicates by edge ID and sort by confidence + LET uniqueResults = ( + FOR result IN traversalResults + COLLECT edgeId = result._edgeId INTO groups + LET best = FIRST( + FOR g IN groups + SORT g.result.confidence DESC + RETURN g.result + ) + RETURN best + ) + + // Sort by confidence and limit results + FOR result IN uniqueResults + SORT result.confidence DESC, result.depth ASC + LIMIT @maxResults + RETURN { + subject: result.subject, + predicate: result.predicate, + object: result.object, + confidence: result.confidence, + depth: result.depth, + pathLength: result.pathLength + } + `; + + console.log(`[ArangoDB] Executing query with ${keywordConditions.length} keywords`); + + const results = await this.executeQuery(query, { + keywords: keywordConditions, + maxDepth, + maxResults + }); + + console.log(`[ArangoDB] Multi-hop graph traversal found ${results.length} triples for keywords: ${keywords.join(', ')}`); + + // Log top 10 results with confidence scores + if (results.length > 0) { + console.log('[ArangoDB] Top 10 triples by confidence (multi-hop):'); + results.slice(0, 10).forEach((triple: any, idx: number) => { + const pathInfo = triple.pathLength ? ` path=${triple.pathLength}` : ''; + console.log(` ${idx + 1}. [conf=${triple.confidence?.toFixed(3)}] ${triple.subject} -> ${triple.predicate} -> ${triple.object} (depth=${triple.depth}${pathInfo})`); + }); + } else { + console.log('[ArangoDB] No triples found!'); + } + + return results; + } catch (error) { + console.error('Error performing graph traversal in ArangoDB:', error); + throw error; + } + } + /** * Get basic info about the ArangoDB connection */ @@ -404,7 +685,7 @@ export class ArangoDBService { if (!this.db) { return { status: 'not connected' }; } - + return { status: 'connected', url: this.db.url, diff --git a/nvidia/txt2kg/assets/frontend/lib/backend-service.ts b/nvidia/txt2kg/assets/frontend/lib/backend-service.ts index 0364720..b2b34d1 100644 --- a/nvidia/txt2kg/assets/frontend/lib/backend-service.ts +++ b/nvidia/txt2kg/assets/frontend/lib/backend-service.ts @@ -1,15 +1,38 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import axios from 'axios'; import { GraphDBService, GraphDBType } from './graph-db-service'; -import { PineconeService } from './pinecone'; +import { QdrantService } from './qdrant'; import { getGraphDbService } from './graph-db-util'; import type { Triple } from '@/types/graph'; /** - * Backend service that combines graph database for storage and Pinecone for embeddings + * Backend service that combines graph database for storage and Qdrant for embeddings + * + * Two distinct modes: + * 1. Knowledge Graph Mode: Stores triples in graph DB + entity names in 'entity-embeddings' collection + * 2. Pure RAG Mode: Stores document chunks in 'document-embeddings' collection (via RAGService) + * + * Use processTriples() for knowledge graph ingestion + * Use storeDocumentChunks() for Pure RAG document ingestion */ export class BackendService { private graphDBService: GraphDBService; - private pineconeService: PineconeService; + private pineconeService: QdrantService; private sentenceTransformerUrl: string = 'http://sentence-transformers:80'; private modelName: string = 'all-MiniLM-L6-v2'; private static instance: BackendService; @@ -18,7 +41,7 @@ export class BackendService { private constructor() { this.graphDBService = GraphDBService.getInstance(); - this.pineconeService = PineconeService.getInstance(); + this.pineconeService = QdrantService.getInstance(); // Use environment variables if available if (process.env.SENTENCE_TRANSFORMER_URL) { @@ -221,28 +244,52 @@ export class BackendService { */ public async queryTraditional(queryText: string): Promise { console.log(`Performing traditional graph query: "${queryText}"`); - + + // Extract keywords from query + const keywords = this.extractKeywords(queryText); + console.log(`Extracted keywords: ${keywords.join(', ')}`); + + // Filter out stop words + const filteredKeywords = keywords.filter(kw => !this.isStopWord(kw)); + + // If using ArangoDB, use its native graph traversal capabilities + if (this.activeGraphDbType === 'arangodb') { + console.log(`Using ArangoDB native graph traversal for keywords: ${filteredKeywords.join(', ')}`); + + try { + const results = await this.graphDBService.graphTraversal(filteredKeywords, 2, 100); + console.log(`ArangoDB graph traversal found ${results.length} relevant triples`); + + // Log top 10 results with confidence scores for debugging + console.log('Top 10 triples by confidence:'); + results.slice(0, 10).forEach((triple, idx) => { + console.log(` ${idx + 1}. [${triple.confidence.toFixed(3)}] ${triple.subject} -> ${triple.predicate} -> ${triple.object} (depth: ${triple.depth})`); + }); + + return results; + } catch (error) { + console.error('Error using ArangoDB graph traversal, falling back to traditional method:', error); + // Fall through to traditional method if ArangoDB traversal fails + } + } + + // Fallback to traditional keyword matching for Neo4j or if ArangoDB traversal fails + console.log(`Using fallback keyword-based search`); + // Get graph data from graph database const graphData = await this.graphDBService.getGraphData(); console.log(`Retrieved graph from ${this.activeGraphDbType} with ${graphData.nodes.length} nodes and ${graphData.relationships.length} relationships`); - + // Create a map of node IDs to names const nodeIdToName = new Map(); for (const node of graphData.nodes) { nodeIdToName.set(node.id, node.name); } - - // Extract keywords from query - const keywords = this.extractKeywords(queryText); - console.log(`Extracted keywords: ${keywords.join(', ')}`); - + // Find matching nodes based on keywords const matchingNodeIds = new Set(); for (const node of graphData.nodes) { - for (const keyword of keywords) { - // Skip common words - if (this.isStopWord(keyword)) continue; - + for (const keyword of filteredKeywords) { // Simple text matching - convert to lowercase for case-insensitive matching if (node.name.toLowerCase().includes(keyword.toLowerCase())) { matchingNodeIds.add(node.id); @@ -250,37 +297,36 @@ export class BackendService { } } } - + console.log(`Found ${matchingNodeIds.size} nodes matching keywords directly`); - + // Find relationships where either subject or object matches const relevantTriples: Triple[] = []; - + for (const rel of graphData.relationships) { // Check if either end of the relationship matches our search const isSourceMatching = matchingNodeIds.has(rel.source); const isTargetMatching = matchingNodeIds.has(rel.target); - + if (isSourceMatching || isTargetMatching) { const sourceName = nodeIdToName.get(rel.source); const targetName = nodeIdToName.get(rel.target); - + if (sourceName && targetName) { // Check if the relationship type matches keywords let matchesRelationship = false; - for (const keyword of keywords) { - if (this.isStopWord(keyword)) continue; + for (const keyword of filteredKeywords) { if (rel.type.toLowerCase().includes(keyword.toLowerCase())) { matchesRelationship = true; break; } } - + // Higher relevance to relationships that match the query directly - const relevance = (isSourceMatching ? 1 : 0) + - (isTargetMatching ? 1 : 0) + + const relevance = (isSourceMatching ? 1 : 0) + + (isTargetMatching ? 1 : 0) + (matchesRelationship ? 2 : 0); - + if (relevance > 0) { relevantTriples.push({ subject: sourceName, @@ -292,12 +338,12 @@ export class BackendService { } } } - + // Sort by confidence (highest first) - relevantTriples.sort((a, b) => + relevantTriples.sort((a, b) => (b.confidence || 0) - (a.confidence || 0) ); - + // Return all relevant triples, sorted by relevance console.log(`Found ${relevantTriples.length} relevant triples with traditional search`); return relevantTriples; @@ -426,6 +472,188 @@ export class BackendService { return relevantTriples.slice(0, topK * 5); } + /** + * Query with LLM enhancement: retrieve triples and use LLM to generate answer + * This makes traditional graph search comparable to RAG by adding LLM generation + * @param queryText - The user's question + * @param topK - Number of top triples to use as context (default 5) + * @param useTraditional - Whether to use traditional (keyword-based) or vector search + * @param llmModel - Optional LLM model to use (defaults to environment variable) + * @param llmProvider - Optional LLM provider (ollama, nvidia, etc.) + * @returns Generated answer from LLM based on retrieved triples + */ + public async queryWithLLM( + queryText: string, + topK: number = 5, + useTraditional: boolean = true, + llmModel?: string, + llmProvider?: string + ): Promise<{ answer: string; triples: Triple[]; count: number }> { + console.log(`Querying with LLM enhancement: "${queryText}", topK=${topK}, traditional=${useTraditional}`); + + // Step 1: Retrieve relevant triples using graph search + const allTriples = await this.query(queryText, 4096, 400, 2, useTraditional); + + // Step 2: Take top K triples for context + const topTriples = allTriples.slice(0, topK); + console.log(`Using top ${topTriples.length} triples as context for LLM`); + + // DEBUG: Log first triple to verify depth/pathLength are present + if (topTriples.length > 0) { + console.log('First triple structure:', JSON.stringify(topTriples[0], null, 2)); + } + + if (topTriples.length === 0) { + return { + answer: "I couldn't find any relevant information in the knowledge graph to answer this question.", + triples: [], + count: 0 + }; + } + + // Step 3: Format triples as natural language context + const context = topTriples + .map(triple => { + // Convert triple to natural language + const predicate = triple.predicate + .replace(/_/g, ' ') + .replace(/-/g, ' ') + .toLowerCase(); + return `${triple.subject} ${predicate} ${triple.object}`; + }) + .join('. '); + + // Step 4: Use LLM to generate answer from context + try { + // Simplified prompt to work better with NVIDIA Nemotron's natural reasoning format + const prompt = `Answer the question based on the following context from the knowledge graph. + +Context: +${context} + +Question: ${queryText} + +Answer:`; + + // Determine LLM endpoint and model based on provider + const finalProvider = llmProvider || 'ollama'; + const finalModel = llmModel || process.env.OLLAMA_MODEL || 'llama3.1:8b'; + + console.log(`Using LLM: provider=${finalProvider}, model=${finalModel}`); + + let response; + + if (finalProvider === 'nvidia') { + // Use NVIDIA API + const nvidiaApiKey = process.env.NVIDIA_API_KEY; + if (!nvidiaApiKey) { + throw new Error('NVIDIA_API_KEY is required for NVIDIA provider. Please set the NVIDIA_API_KEY environment variable.'); + } + + const nvidiaUrl = 'https://integrate.api.nvidia.com/v1'; + + // Note: NVIDIA API doesn't support streaming in axios, so we'll use non-streaming + // and format the thinking content into tags manually + response = await axios.post(`${nvidiaUrl}/chat/completions`, { + model: finalModel, + messages: [ + { + role: 'system', + content: '/think' // Special NVIDIA API command to activate thinking mode + }, + { + role: 'user', + content: prompt + } + ], + temperature: 0.2, + max_tokens: 4096, + top_p: 0.95, + frequency_penalty: 0, + presence_penalty: 0, + stream: false, // We need non-streaming to get thinking tokens + // NVIDIA-specific thinking token parameters + min_thinking_tokens: 1024, + max_thinking_tokens: 2048 + }, { + headers: { + 'Authorization': `Bearer ${nvidiaApiKey}`, + 'Content-Type': 'application/json' + }, + timeout: 120000 // 120 second timeout + }); + } else { + // Use Ollama (default) + const ollamaUrl = process.env.OLLAMA_BASE_URL || 'http://localhost:11434/v1'; + + response = await axios.post(`${ollamaUrl}/chat/completions`, { + model: finalModel, + messages: [ + { + role: 'system', + content: 'You are a knowledgeable research assistant specializing in biomedical and scientific literature. Provide accurate, well-structured answers based on the provided context. Maintain a professional yet accessible tone, and clearly indicate when information is limited or uncertain.' + }, + { + role: 'user', + content: prompt + } + ], + temperature: 0.2, // Lower for more factual, consistent responses + max_tokens: 800 // Increased for more comprehensive answers + }); + } + + // Extract answer and reasoning (if using NVIDIA with thinking tokens) + const messageData = response.data.choices[0].message; + let answer = messageData.content || ''; + + // Check if NVIDIA API returned reasoning_content (thinking tokens) + if (finalProvider === 'nvidia' && messageData.reasoning_content) { + // Format with tags for UI parsing + answer = `\n${messageData.reasoning_content}\n\n\n${answer}`; + console.log('Formatted response with thinking content'); + } + + // DEBUG: Log triples before returning to verify they still have depth/pathLength + console.log('Returning triples (first one):', JSON.stringify(topTriples[0], null, 2)); + + return { + answer, + triples: topTriples, + count: topTriples.length + }; + } catch (error) { + console.error('Error calling LLM for answer generation:', error); + // Fallback: return triples without LLM enhancement + return { + answer: `Found ${topTriples.length} relevant triples:\n\n${context}`, + triples: topTriples, + count: topTriples.length + }; + } + } + + /** + * Store document chunks for Pure RAG (separate from entity embeddings) + * This stores full text chunks rather than just entity names + * @param documents Array of document text chunks + * @param metadata Optional metadata for each document + */ + public async storeDocumentChunks( + documents: string[], + metadata?: Record[] + ): Promise { + console.log(`Storing ${documents.length} document chunks for Pure RAG`); + + // Generate embeddings for document chunks + const embeddings = await this.generateEmbeddings(documents); + + // Store in Qdrant document-embeddings collection + await this.pineconeService.storeDocumentChunks(documents, embeddings, metadata); + + console.log(`βœ… Stored ${documents.length} document chunks in document-embeddings collection`); + } + /** * Close connections to backend services */ diff --git a/nvidia/txt2kg/assets/frontend/lib/client-init.ts b/nvidia/txt2kg/assets/frontend/lib/client-init.ts index fd8b981..1ef1d35 100644 --- a/nvidia/txt2kg/assets/frontend/lib/client-init.ts +++ b/nvidia/txt2kg/assets/frontend/lib/client-init.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// /** * Client-side initialization utilities * This file contains functions for initializing the application on the client side diff --git a/nvidia/txt2kg/assets/frontend/lib/embeddings.ts b/nvidia/txt2kg/assets/frontend/lib/embeddings.ts index 97f21f2..5bd2cb6 100644 --- a/nvidia/txt2kg/assets/frontend/lib/embeddings.ts +++ b/nvidia/txt2kg/assets/frontend/lib/embeddings.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { getShouldStopEmbeddings, resetStopEmbeddings } from "@/app/api/stop-embeddings/route"; /** @@ -8,7 +24,7 @@ export class EmbeddingsService { private apiUrl: string; private modelId: string; private static instance: EmbeddingsService; - private dimension: number = 768; // Dimension for gte-modernbert-base + private dimension: number = 384; // Dimension for all-MiniLM-L6-v2 (default model) private useNvidiaApi: boolean = false; private nvidiaApiKey: string = ''; private nvidiaModel: string = 'nvidia/llama-3.2-nv-embedqa-1b-v2'; @@ -16,7 +32,7 @@ export class EmbeddingsService { private constructor() { this.apiUrl = process.env.EMBEDDINGS_API_URL || 'http://localhost:8000'; - this.modelId = process.env.EMBEDDINGS_MODEL_ID || 'Alibaba-NLP/gte-modernbert-base'; + this.modelId = process.env.EMBEDDINGS_MODEL_ID || 'all-MiniLM-L6-v2'; // Always get NVIDIA API key from environment variables this.nvidiaApiKey = process.env.NVIDIA_API_KEY || ''; diff --git a/nvidia/txt2kg/assets/frontend/lib/graph-db-service.ts b/nvidia/txt2kg/assets/frontend/lib/graph-db-service.ts index 3f7550a..8a0f839 100644 --- a/nvidia/txt2kg/assets/frontend/lib/graph-db-service.ts +++ b/nvidia/txt2kg/assets/frontend/lib/graph-db-service.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { Neo4jService } from './neo4j'; import { ArangoDBService } from './arangodb'; import type { Triple } from '@/types/graph'; @@ -166,6 +182,30 @@ export class GraphDBService { } } + /** + * Perform graph traversal using native database capabilities + * Only available for ArangoDB + */ + public async graphTraversal( + keywords: string[], + maxDepth: number = 2, + maxResults: number = 100 + ): Promise> { + if (this.activeDBType === 'arangodb') { + return await this.arangoDBService.graphTraversal(keywords, maxDepth, maxResults); + } else { + // Neo4j doesn't have this method yet, return empty array + console.warn('graphTraversal is only available for ArangoDB'); + return []; + } + } + /** * Clear all data from the active graph database */ diff --git a/nvidia/txt2kg/assets/frontend/lib/graph-db-util.ts b/nvidia/txt2kg/assets/frontend/lib/graph-db-util.ts index cd9b229..84752d1 100644 --- a/nvidia/txt2kg/assets/frontend/lib/graph-db-util.ts +++ b/nvidia/txt2kg/assets/frontend/lib/graph-db-util.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { GraphDBService, GraphDBType } from './graph-db-service'; import { Neo4jService } from './neo4j'; import { ArangoDBService } from './arangodb'; diff --git a/nvidia/txt2kg/assets/frontend/lib/langchain-service.ts b/nvidia/txt2kg/assets/frontend/lib/langchain-service.ts index e24aa85..f5c9f09 100644 --- a/nvidia/txt2kg/assets/frontend/lib/langchain-service.ts +++ b/nvidia/txt2kg/assets/frontend/lib/langchain-service.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { ChatOpenAI } from "@langchain/openai"; import { SystemMessage } from "@langchain/core/messages"; @@ -29,7 +45,7 @@ export class LangChainService { temperature?: number; maxTokens?: number; }): Promise { - const modelId = "nvdev/nvidia/llama-3.1-nemotron-70b-instruct"; + const modelId = "nvidia/llama-3.3-nemotron-super-49b-v1.5"; const cacheKey = `nemotron-${options?.temperature || 0.7}-${options?.maxTokens || 8192}`; console.log(`Requesting Nemotron model (cacheKey: ${cacheKey})`); @@ -73,15 +89,17 @@ export class LangChainService { // Create a new ChatOpenAI instance const model = new ChatOpenAI({ modelName: modelId, - temperature: options?.temperature || 0.7, + temperature: options?.temperature || 0.6, maxTokens: options?.maxTokens || 8192, openAIApiKey: apiKey, configuration: { baseURL: "https://integrate.api.nvidia.com/v1", - timeout: 60000, // 60 second timeout + timeout: 120000, // 120 second timeout for larger model }, modelKwargs: { - "response_format": { "type": "text" } + top_p: 0.95, + frequency_penalty: 0, + presence_penalty: 0 } }); diff --git a/nvidia/txt2kg/assets/frontend/lib/llm-service.ts b/nvidia/txt2kg/assets/frontend/lib/llm-service.ts index c2126b9..5b0f39a 100644 --- a/nvidia/txt2kg/assets/frontend/lib/llm-service.ts +++ b/nvidia/txt2kg/assets/frontend/lib/llm-service.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import OpenAI from 'openai'; import { Agent } from 'http'; import { Agent as HttpsAgent } from 'https'; diff --git a/nvidia/txt2kg/assets/frontend/lib/neo4j.ts b/nvidia/txt2kg/assets/frontend/lib/neo4j.ts index 02dcb8d..13a8ceb 100644 --- a/nvidia/txt2kg/assets/frontend/lib/neo4j.ts +++ b/nvidia/txt2kg/assets/frontend/lib/neo4j.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import neo4j, { Driver, Session, Record as Neo4jRecord, Config } from 'neo4j-driver'; /** diff --git a/nvidia/txt2kg/assets/frontend/lib/pinecone.ts b/nvidia/txt2kg/assets/frontend/lib/pinecone.ts index b7b4777..23b3a2d 100644 --- a/nvidia/txt2kg/assets/frontend/lib/pinecone.ts +++ b/nvidia/txt2kg/assets/frontend/lib/pinecone.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// /** * Pinecone service for vector embeddings * Uses direct API calls for Pinecone local server diff --git a/nvidia/txt2kg/assets/frontend/lib/qdrant.ts b/nvidia/txt2kg/assets/frontend/lib/qdrant.ts new file mode 100644 index 0000000..48fe140 --- /dev/null +++ b/nvidia/txt2kg/assets/frontend/lib/qdrant.ts @@ -0,0 +1,704 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/** + * Qdrant service for vector embeddings + * Drop-in replacement for PineconeService + */ +import { Document } from "@langchain/core/documents"; +import { randomUUID } from "crypto"; + +// Helper function to generate deterministic UUID from string +function stringToUUID(str: string): string { + // Create a simple hash-based UUID v4 + const hash = str.split('').reduce((acc, char) => { + return ((acc << 5) - acc) + char.charCodeAt(0) | 0; + }, 0); + + // Generate a deterministic UUID from the hash + const hex = Math.abs(hash).toString(16).padStart(32, '0').substring(0, 32); + return `${hex.substring(0, 8)}-${hex.substring(8, 12)}-4${hex.substring(13, 16)}-${hex.substring(16, 20)}-${hex.substring(20, 32)}`; +} + +// Define types for Qdrant requests and responses +interface QdrantPoint { + id: string | number; + vector: number[]; + payload?: Record; +} + +interface QdrantQueryResponse { + result: Array<{ + id: string | number; + score: number; + payload?: Record; + }>; +} + +// Define interface for document search results +export interface DocumentSearchResult { + id: string; + score: number; + metadata?: Record; +} + +export class QdrantService { + private dimension: number = 384; // Dimension for MiniLM-L6-v2 + private static instance: QdrantService; + private initialized: boolean = false; + private collectionName: string = 'entity-embeddings'; + private hostUrl: string; + private isInitializing = false; + + private constructor() { + // Get environment variables with defaults + const qdrantUrl = process.env.QDRANT_URL || 'http://localhost:6333'; + this.hostUrl = qdrantUrl; + + console.log(`Initializing Qdrant service with host: ${this.hostUrl}`); + } + + /** + * Get singleton instance + */ + public static getInstance(): QdrantService { + if (!QdrantService.instance) { + QdrantService.instance = new QdrantService(); + } + return QdrantService.instance; + } + + /** + * Check if the service is initialized + */ + public isInitialized(): boolean { + return this.initialized; + } + + /** + * Make a request to the Qdrant API + */ + private async makeRequest(endpoint: string, method: string = 'GET', body?: any): Promise { + try { + const url = endpoint.startsWith('http') ? endpoint : `${this.hostUrl}${endpoint}`; + + console.log(`Making Qdrant request to: ${url}`); + + const options: RequestInit = { + method, + headers: { + 'Content-Type': 'application/json', + } + }; + + if (body) { + options.body = JSON.stringify(body); + } + + const response = await fetch(url, options); + + if (!response.ok) { + const errorText = await response.text(); + console.log(`Qdrant API error (${response.status}) for ${url}: ${errorText}`); + return null; + } + + // For HEAD requests or empty responses + if (method === 'HEAD' || response.headers.get('content-length') === '0') { + return { status: response.status }; + } + + return await response.json(); + } catch (error) { + console.log(`Error in Qdrant API request to ${endpoint} - request failed`); + return null; + } + } + + /** + * Check if the Qdrant server is up and running + */ + private isQdrantRunningCheck = false; + + public async isQdrantRunning(): Promise { + // Prevent concurrent checks that could cause loops + if (this.isQdrantRunningCheck) { + console.log('Already checking if Qdrant is running, returning true to break cycle'); + return true; + } + + this.isQdrantRunningCheck = true; + + try { + // Check Qdrant health endpoint + const response = await fetch(`${this.hostUrl}/healthz`, { + method: 'GET' + }); + + if (response.ok) { + console.log(`Qdrant server is up and healthy`); + this.isQdrantRunningCheck = false; + return true; + } + + console.log('Qdrant health check failed - server might not be running'); + this.isQdrantRunningCheck = false; + return false; + } catch (error) { + console.log('Error checking Qdrant server health - server appears to be down'); + this.isQdrantRunningCheck = false; + return false; + } + } + + /** + * Initialize Qdrant and create collection if needed + */ + public async initialize(forceCreateCollection: boolean = false): Promise { + if ((this.initialized && !forceCreateCollection) || this.isInitializing) { + return; + } + + this.isInitializing = true; + + try { + console.log('Qdrant service initializing...'); + + // Check if Qdrant server is running + const isRunning = await this.isQdrantRunning(); + if (!isRunning) { + console.log('Qdrant server does not appear to be running. Please ensure it is started in Docker.'); + this.isInitializing = false; + return; + } + + // Check if collection exists + const collectionInfo = await this.makeRequest(`/collections/${this.collectionName}`, 'GET'); + + if (!collectionInfo || collectionInfo.status === 'error') { + // Create collection + console.log(`Creating Qdrant collection: ${this.collectionName}`); + const createResult = await this.makeRequest(`/collections/${this.collectionName}`, 'PUT', { + vectors: { + size: this.dimension, + distance: 'Cosine' + } + }); + + if (createResult && createResult.result === true) { + console.log(`Created Qdrant collection with ${this.dimension} dimensions`); + this.initialized = true; + } else { + console.log('Failed to create Qdrant collection - continuing without initialization'); + } + } else { + // Collection exists + const vectorCount = collectionInfo.result?.points_count || 0; + console.log(`Connected to Qdrant collection with ${vectorCount} vectors`); + this.initialized = true; + } + + this.isInitializing = false; + console.log('Qdrant service initialization completed'); + } catch (error) { + console.log('Error during Qdrant service initialization - continuing without connection'); + this.isInitializing = false; + } + } + + /** + * Store embeddings for entities + */ + public async storeEmbeddings( + entityEmbeddings: Map, + textContentMap?: Map + ): Promise { + if (!this.initialized) { + await this.initialize(); + } + + if (!this.initialized) { + console.log('Qdrant not available - skipping embedding storage'); + return; + } + + try { + const points: QdrantPoint[] = []; + + // Convert to Qdrant point format + for (const [entityName, embedding] of entityEmbeddings.entries()) { + const point: QdrantPoint = { + id: stringToUUID(entityName), // Convert string ID to UUID + vector: embedding, + payload: { + originalId: entityName, // Store original ID in payload for retrieval + text: textContentMap?.get(entityName) || entityName, + type: 'entity' + } + }; + points.push(point); + } + + // Use batching for efficient upserts + const batchSize = 100; + for (let i = 0; i < points.length; i += batchSize) { + const batch = points.slice(i, i + batchSize); + + const success = await this.upsertVectors(batch); + if (success) { + console.log(`Upserted batch ${Math.floor(i/batchSize) + 1} of ${Math.ceil(points.length/batchSize)}`); + } else { + console.log(`Failed to upsert batch ${Math.floor(i/batchSize) + 1} - continuing`); + } + } + + console.log(`Completed embedding storage attempt for ${points.length} embeddings`); + } catch (error) { + console.log('Error storing embeddings - continuing without storage'); + } + } + + /** + * Upsert vectors to Qdrant + * @param points Array of points to upsert + * @param collectionName Optional collection name (defaults to entity-embeddings) + */ + public async upsertVectors(points: QdrantPoint[], collectionName?: string): Promise { + const targetCollection = collectionName || this.collectionName; + + if (!this.initialized) { + await this.initialize(); + } + + if (!this.initialized) { + console.log('Qdrant not available - skipping vector upsert'); + return false; + } + + try { + console.log(`Upserting ${points.length} vectors to Qdrant collection: ${targetCollection}`); + + const response = await this.makeRequest(`/collections/${targetCollection}/points`, 'PUT', { + points: points + }); + + if (!response || response.status === 'error') { + console.log(`Qdrant upsert failed`); + return false; + } + + console.log(`Successfully upserted ${points.length} vectors`); + return true; + } catch (error) { + console.log('Error upserting vectors to Qdrant - continuing without storage'); + return false; + } + } + + /** + * Store embeddings with metadata + */ + public async storeEmbeddingsWithMetadata( + embeddings: Map, + textContent: Map, + metadata: Map + ): Promise { + if (!this.initialized) { + await this.initialize(); + } + + if (!this.initialized) { + console.log('Qdrant not available - skipping embedding storage with metadata'); + return; + } + + try { + const points: QdrantPoint[] = []; + + // Convert to Qdrant point format + for (const [key, embedding] of embeddings.entries()) { + const point: QdrantPoint = { + id: stringToUUID(key), // Convert string ID to UUID + vector: embedding, + payload: { + originalId: key, // Store original ID in payload for retrieval + text: textContent.get(key) || '', + ...metadata.get(key) || {} + } + }; + points.push(point); + } + + // Use batching for efficient upserts + const batchSize = 100; + for (let i = 0; i < points.length; i += batchSize) { + const batch = points.slice(i, i + batchSize); + + const success = await this.upsertVectors(batch); + if (success) { + console.log(`Upserted batch ${Math.floor(i/batchSize) + 1} of ${Math.ceil(points.length/batchSize)}`); + } else { + console.log(`Failed to upsert batch ${Math.floor(i/batchSize) + 1} - continuing`); + } + } + + console.log(`Completed embedding storage attempt for ${points.length} embeddings with metadata`); + } catch (error) { + console.log('Error storing embeddings with metadata - continuing without storage'); + } + } + + /** + * Find similar entities to a query embedding + */ + public async findSimilarEntitiesWithMetadata( + embedding: number[], + limit: number = 10 + ): Promise<{ entities: string[], metadata: Map }> { + if (!this.initialized) { + await this.initialize(); + } + + if (!this.initialized) { + console.log('Qdrant not available - returning empty results'); + return { entities: [], metadata: new Map() }; + } + + try { + const queryResponse = await this.queryVectors(embedding, limit, true); + + if (!queryResponse) { + return { entities: [], metadata: new Map() }; + } + + // Extract entities and metadata, using originalId from payload + const entities = queryResponse.result.map(match => + match.payload?.originalId || String(match.id) + ); + const metadataMap = new Map(); + + queryResponse.result.forEach(match => { + const originalId = match.payload?.originalId || String(match.id); + metadataMap.set(originalId, { + ...match.payload, + score: match.score + }); + }); + + return { entities, metadata: metadataMap }; + } catch (error) { + console.log('Error finding similar entities - returning empty results'); + return { entities: [], metadata: new Map() }; + } + } + + /** + * Query vectors in Qdrant + */ + private async queryVectors( + vector: number[], + limit: number = 10, + withPayload: boolean = false + ): Promise { + if (!this.initialized) { + await this.initialize(); + } + + if (!this.initialized) { + console.log('Qdrant not available - cannot query vectors'); + return null; + } + + try { + const response = await this.makeRequest(`/collections/${this.collectionName}/points/query`, 'POST', { + query: vector, + limit: limit, + with_payload: withPayload + }); + + if (!response || response.status === 'error') { + console.log(`Qdrant query failed`); + return null; + } + + return response; + } catch (error) { + console.log('Error querying vectors from Qdrant - returning null'); + return null; + } + } + + /** + * Find similar entities to a query embedding + */ + public async findSimilarEntities(queryEmbedding: number[], topK: number = 10): Promise { + if (!this.initialized) { + await this.initialize(); + } + + if (!this.initialized) { + console.log('Qdrant not available - returning empty entity list'); + return []; + } + + try { + const queryResponse = await this.queryVectors(queryEmbedding, topK, true); + if (!queryResponse) { + return []; + } + return queryResponse.result.map(match => + match.payload?.originalId || String(match.id) + ); + } catch (error) { + console.log('Error finding similar entities - returning empty list'); + return []; + } + } + + /** + * Get all entities in the collection (up to limit) + */ + public async getAllEntities(limit: number = 1000): Promise { + if (!this.initialized) { + await this.initialize(); + } + + try { + // Qdrant doesn't have a direct "get all" like Pinecone + // We'll use scroll API to get points + const response = await this.makeRequest(`/collections/${this.collectionName}/points/scroll`, 'POST', { + limit: limit, + with_payload: false, + with_vector: false + }); + + if (!response || !response.result || !response.result.points) { + return []; + } + + return response.result.points.map((point: any) => String(point.id)); + } catch (error) { + console.error('Error getting all entities:', error); + return []; + } + } + + /** + * Delete entities from the collection + */ + public async deleteEntities(entityIds: string[]): Promise { + if (!this.initialized) { + await this.initialize(); + } + + if (!this.initialized) { + console.log('Qdrant not available - cannot delete entities'); + return false; + } + + try { + console.log(`Deleting ${entityIds.length} entities from Qdrant`); + + const response = await this.makeRequest(`/collections/${this.collectionName}/points/delete`, 'POST', { + points: entityIds + }); + + if (!response || response.status === 'error') { + console.log(`Qdrant delete failed`); + return false; + } + + console.log(`Successfully deleted ${entityIds.length} entities`); + return true; + } catch (error) { + console.log('Error deleting entities from Qdrant - operation failed'); + return false; + } + } + + /** + * Get collection statistics from Qdrant + */ + public async getStats(): Promise { + try { + console.log('Getting stats from Qdrant...'); + const response = await this.makeRequest(`/collections/${this.collectionName}`, 'GET'); + + if (response && response.result) { + const stats = response.result; + console.log('Successfully retrieved stats from Qdrant'); + return { + totalVectorCount: stats.points_count || 0, + indexedVectorCount: stats.indexed_vectors_count || 0, + status: stats.status || 'unknown', + optimizerStatus: stats.optimizer_status || 'unknown', + vectorSize: stats.config?.params?.vectors?.size || this.dimension, + distance: stats.config?.params?.vectors?.distance || 'Cosine', + source: 'qdrant', + httpHealthy: true, + url: this.hostUrl + }; + } else { + console.log(`Qdrant stats request failed`); + return { + totalVectorCount: 0, + source: 'error', + httpHealthy: false, + error: 'Failed to get stats' + }; + } + } catch (error) { + console.log('Qdrant connection failed - server may not be running'); + return { + totalVectorCount: 0, + source: 'error', + httpHealthy: false, + error: error instanceof Error ? error.message : String(error) + }; + } + } + + /** + * Delete all entities in the collection + */ + public async deleteAllEntities(): Promise { + if (!this.initialized) { + await this.initialize(); + } + + if (!this.initialized) { + console.log('Qdrant not available - cannot delete all entities'); + return false; + } + + try { + console.log('Deleting all entities from Qdrant'); + + // Delete the entire collection and recreate it + const deleteResult = await this.makeRequest(`/collections/${this.collectionName}`, 'DELETE'); + + if (!deleteResult || deleteResult.status === 'error') { + console.log(`Qdrant delete collection failed`); + return false; + } + + // Recreate the collection + await this.initialize(true); + + console.log('Successfully deleted all entities from Qdrant'); + return true; + } catch (error) { + console.log('Error deleting all entities from Qdrant - operation failed'); + return false; + } + } + + /** + * Find similar documents to a query embedding + * @param queryEmbedding Query embedding vector + * @param topK Number of results to return + * @returns Promise resolving to array of document search results + */ + public async findSimilarDocuments(queryEmbedding: number[], topK: number = 10): Promise { + if (!this.initialized) { + await this.initialize(); + } + + if (!this.initialized) { + console.log('Qdrant not available - returning empty document results'); + return []; + } + + try { + const queryResponse = await this.queryVectors(queryEmbedding, topK, true); + if (!queryResponse) { + return []; + } + return queryResponse.result.map(match => ({ + id: match.payload?.originalId || String(match.id), + score: match.score, + metadata: match.payload + })); + } catch (error) { + console.log('Error finding similar documents - returning empty results'); + return []; + } + } + + /** + * Store document chunks for Pure RAG + * @param documents Array of document text chunks + * @param embeddings Array of embeddings corresponding to the documents + * @param metadata Optional metadata for each document + */ + public async storeDocumentChunks( + documents: string[], + embeddings: number[][], + metadata?: Record[] + ): Promise { + const documentCollection = 'document-embeddings'; + + try { + console.log(`Storing ${documents.length} document chunks in collection: ${documentCollection}`); + + // Ensure the document collection exists + const collectionInfo = await this.makeRequest(`/collections/${documentCollection}`, 'GET'); + if (!collectionInfo || collectionInfo.status === 'error') { + console.log(`Creating Qdrant collection: ${documentCollection}`); + await this.makeRequest(`/collections/${documentCollection}`, 'PUT', { + vectors: { + size: this.dimension, + distance: 'Cosine' + } + }); + } + + const points: QdrantPoint[] = []; + + // Convert to Qdrant point format + for (let i = 0; i < documents.length; i++) { + const docId = metadata?.[i]?.id || `doc_${randomUUID()}`; + const point: QdrantPoint = { + id: stringToUUID(docId), + vector: embeddings[i], + payload: { + originalId: docId, + text: documents[i], + type: 'document', + ...(metadata?.[i] || {}) + } + }; + points.push(point); + } + + // Use batching for efficient upserts + const batchSize = 100; + for (let i = 0; i < points.length; i += batchSize) { + const batch = points.slice(i, i + batchSize); + const success = await this.upsertVectors(batch, documentCollection); + if (success) { + console.log(`Upserted document batch ${Math.floor(i/batchSize) + 1} of ${Math.ceil(points.length/batchSize)}`); + } else { + console.log(`Failed to upsert document batch ${Math.floor(i/batchSize) + 1} - continuing`); + } + } + + console.log(`βœ… Completed storing ${points.length} document chunks`); + } catch (error) { + console.log('Error storing document chunks - continuing without storage'); + } + } +} diff --git a/nvidia/txt2kg/assets/frontend/lib/query-logger.ts b/nvidia/txt2kg/assets/frontend/lib/query-logger.ts index bc308d9..2558fbc 100644 --- a/nvidia/txt2kg/assets/frontend/lib/query-logger.ts +++ b/nvidia/txt2kg/assets/frontend/lib/query-logger.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import fs from 'fs'; import path from 'path'; import { promises as fsPromises } from 'fs'; @@ -17,6 +33,7 @@ export interface QueryLogEntry { export interface QueryLogSummary { query: string; + queryMode: 'traditional' | 'vector-search' | 'pure-rag'; count: number; firstQueried: string; lastQueried: string; @@ -148,9 +165,10 @@ export class QueryLoggerService { return []; } - // Group logs by query + // Group logs by query AND queryMode const querySummaries = new Map(); logs.forEach(entry => { - const existing = querySummaries.get(entry.query) || { + // Use composite key: query + mode + const key = `${entry.query}|||${entry.queryMode}`; + const existing = querySummaries.get(key) || { query: entry.query, + queryMode: entry.queryMode, count: 0, timestamps: [], executionTimes: [], @@ -180,12 +201,13 @@ export class QueryLoggerService { if (entry.metrics.recall !== undefined) existing.recalls.push(entry.metrics.recall); existing.resultCounts.push(entry.metrics.resultCount); - querySummaries.set(entry.query, existing); + querySummaries.set(key, existing); }); // Convert to array and format const result: QueryLogSummary[] = Array.from(querySummaries.values()).map(summary => ({ query: summary.query, + queryMode: summary.queryMode, count: summary.count, firstQueried: summary.timestamps[0], lastQueried: summary.timestamps[summary.timestamps.length - 1], diff --git a/nvidia/txt2kg/assets/frontend/lib/rag.ts b/nvidia/txt2kg/assets/frontend/lib/rag.ts index 2165fc0..bb59a6c 100644 --- a/nvidia/txt2kg/assets/frontend/lib/rag.ts +++ b/nvidia/txt2kg/assets/frontend/lib/rag.ts @@ -1,7 +1,28 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// /** - * Retrieval Augmented Generation (RAG) implementation using Pinecone and LangChain - * This module provides a RetrievalQA chain using Pinecone as the vector store - * Note: xAI integration has been removed - needs alternative LLM provider implementation + * Retrieval Augmented Generation (RAG) implementation using Qdrant and LangChain + * This module provides a RetrievalQA chain using Qdrant as the vector store + * Uses NVIDIA API for LLM inference + * + * Architecture: + * - Uses 'document-embeddings' collection for Pure RAG (stores full text chunks) + * - Separate from 'entity-embeddings' collection used for knowledge graph entities + * - Documents are retrieved via semantic similarity and fed to LLM for answer generation */ import { ChatOpenAI } from "@langchain/openai"; @@ -9,27 +30,42 @@ import { Document } from "@langchain/core/documents"; import { RunnableSequence } from "@langchain/core/runnables"; import { StringOutputParser } from "@langchain/core/output_parsers"; import { PromptTemplate } from "@langchain/core/prompts"; -import { PineconeService, DocumentSearchResult } from './pinecone'; +import { QdrantVectorStore } from "@langchain/community/vectorstores/qdrant"; +import { Embeddings } from "@langchain/core/embeddings"; import { EmbeddingsService } from './embeddings'; -// Interface for records to store in Pinecone -interface PineconeRecord { - id: string; - values: number[]; - metadata?: Record; +// Custom embeddings adapter to use our EmbeddingsService with LangChain +class CustomEmbeddings extends Embeddings { + private embeddingsService: EmbeddingsService; + + constructor() { + super({}); + this.embeddingsService = EmbeddingsService.getInstance(); + } + + async embedDocuments(documents: string[]): Promise { + await this.embeddingsService.initialize(); + return await this.embeddingsService.encode(documents); + } + + async embedQuery(query: string): Promise { + await this.embeddingsService.initialize(); + const embeddings = await this.embeddingsService.encode([query]); + return embeddings[0]; + } } export class RAGService { private static instance: RAGService; - private pineconeService: PineconeService; - private embeddingsService: EmbeddingsService; + private vectorStore: QdrantVectorStore | null = null; + private embeddingsService: CustomEmbeddings; private llm: ChatOpenAI | null = null; private initialized: boolean = false; private isInitializing: boolean = false; + private collectionName: string = 'document-embeddings'; private constructor() { - this.pineconeService = PineconeService.getInstance(); - this.embeddingsService = EmbeddingsService.getInstance(); + this.embeddingsService = new CustomEmbeddings(); } /** @@ -51,28 +87,56 @@ export class RAGService { } this.isInitializing = true; - + try { console.log('Initializing RAG service...'); - // Initialize dependencies - await this.pineconeService.initialize(); - await this.embeddingsService.initialize(); - - // Initialize LLM - Try NVIDIA first, then fall back to error + // Check for NVIDIA API key const nvidiaApiKey = process.env.NVIDIA_API_KEY; if (!nvidiaApiKey) { - throw new Error('RAG service requires NVIDIA_API_KEY to be set in environment variables. xAI integration has been removed.'); + const error = new Error('NVIDIA_API_KEY is required for RAG service. Please set the NVIDIA_API_KEY environment variable.'); + console.error('❌ RAG Initialization Error:', error.message); + throw error; } - - // Note: This is a placeholder - NVIDIA LLM integration would need to be implemented - // For now, we'll throw an error to indicate RAG service is not available - throw new Error('RAG service is temporarily unavailable after xAI removal. Please implement alternative LLM provider.'); + + // Initialize NVIDIA LLM using ChatOpenAI with NVIDIA's base URL + this.llm = new ChatOpenAI({ + modelName: "nvidia/llama-3.3-nemotron-super-49b-v1.5", + temperature: 0.2, + maxTokens: 1024, + openAIApiKey: nvidiaApiKey, + configuration: { + baseURL: "https://integrate.api.nvidia.com/v1", + timeout: 120000, // 120 second timeout + }, + modelKwargs: { + top_p: 0.95, + frequency_penalty: 0, + presence_penalty: 0 + } + }); + + console.log('βœ… NVIDIA LLM initialized successfully'); + + // Initialize Qdrant vector store + const qdrantUrl = process.env.QDRANT_URL || 'http://localhost:6333'; + + this.vectorStore = await QdrantVectorStore.fromExistingCollection( + this.embeddingsService, + { + url: qdrantUrl, + collectionName: this.collectionName, + contentPayloadKey: 'text', // Map payload.text to pageContent + } + ); + + console.log('βœ… Qdrant vector store connected successfully'); this.initialized = true; - console.log('RAG service initialized successfully'); + console.log('βœ… RAG service initialized successfully'); } catch (error) { - console.error('Error initializing RAG service:', error); + console.error('❌ Error initializing RAG service:', error); + this.isInitializing = false; throw error; } finally { this.isInitializing = false; @@ -80,7 +144,7 @@ export class RAGService { } /** - * Store documents in Pinecone for retrieval + * Store documents in Qdrant for retrieval * @param documents Array of text documents to store * @param metadata Optional metadata for the documents */ @@ -97,34 +161,33 @@ export class RAGService { return; } - console.log(`Storing ${documents.length} documents in Pinecone`); + if (!this.vectorStore) { + throw new Error('Vector store not initialized'); + } - // Generate embeddings for documents - const embeddings = await this.embeddingsService.encode(documents); + console.log(`Storing ${documents.length} documents in Qdrant`); - // Prepare records for Pinecone - const records: PineconeRecord[] = embeddings.map((embedding, i) => ({ - id: `doc_${Date.now()}_${i}`, - values: embedding, + // Create Document objects with metadata + const docs = documents.map((text, i) => new Document({ + pageContent: text, metadata: { - text: documents[i], timestamp: new Date().toISOString(), ...(metadata && metadata[i] ? metadata[i] : {}) } })); - // Store in Pinecone - await this.pineconeService.upsertVectors(records); - console.log(`Successfully stored ${records.length} document embeddings`); + // Store in Qdrant using LangChain + await this.vectorStore.addDocuments(docs); + console.log(`βœ… Successfully stored ${docs.length} document embeddings`); } /** - * Perform question answering with document retrieval + * Perform question answering with document retrieval using proper RAG implementation * @param query User query * @param topK Number of most similar documents to retrieve - * @returns Answer generated from relevant context + * @returns Object containing the answer and document count */ - public async retrievalQA(query: string, topK: number = 5): Promise { + public async retrievalQA(query: string, topK: number = 5): Promise<{ answer: string; documentCount: number }> { if (!this.initialized) { await this.initialize(); } @@ -133,15 +196,18 @@ export class RAGService { throw new Error('LLM not initialized'); } - // Generate embedding for query - const queryEmbedding = (await this.embeddingsService.encode([query]))[0]; + if (!this.vectorStore) { + throw new Error('Vector store not initialized'); + } + + console.log(`πŸ” Performing RAG query with topK=${topK}`); + + // Use LangChain's similarity search to retrieve relevant documents + const similarDocs = await this.vectorStore.similaritySearch(query, topK); - // Retrieve similar documents from Pinecone - const similarDocs = await this.pineconeService.findSimilarDocuments(queryEmbedding, topK); - if (!similarDocs || similarDocs.length === 0) { - console.log('No relevant documents found, falling back to LLM'); - + console.log('⚠️ No relevant documents found, falling back to LLM general knowledge'); + // Define prompt template for standalone LLM response const fallbackPromptTemplate = PromptTemplate.fromTemplate(` You are a helpful assistant answering questions based on your general knowledge. @@ -164,18 +230,73 @@ Answer: // Execute fallback chain const answer = await fallbackChain.invoke({}); - return `[Note: No specific information was found in the knowledge base. This answer is based on general knowledge.]\n\n${answer}`; + return { + answer: `[Note: No specific information was found in the knowledge base. This answer is based on general knowledge.]\n\n${answer}`, + documentCount: 0 + }; + } + + console.log(`βœ… Found ${similarDocs.length} relevant document chunks`); + + // Log first document structure for debugging + if (similarDocs.length > 0) { + console.log('πŸ“„ First document chunk structure:', { + hasPageContent: !!similarDocs[0].pageContent, + pageContentLength: similarDocs[0].pageContent?.length || 0, + hasMetadata: !!similarDocs[0].metadata, + metadataKeys: similarDocs[0].metadata ? Object.keys(similarDocs[0].metadata) : [] + }); } // Extract text from retrieved documents + // Support both pageContent (LangChain standard) and metadata.text (legacy format) const context = similarDocs - .map((doc: DocumentSearchResult) => doc.metadata?.text || '') - .filter((text: string) => text.length > 0) + .map((doc) => { + // Try pageContent first (LangChain standard) + if (doc.pageContent && doc.pageContent.trim().length > 0) { + return doc.pageContent; + } + // Fall back to metadata.text (legacy Qdrant storage format) + if (doc.metadata?.text && doc.metadata.text.trim().length > 0) { + return doc.metadata.text; + } + return ''; + }) + .filter((text) => text.length > 0) .join('\n\n'); - // Define prompt template for QA + console.log(`πŸ“ Extracted context length: ${context.length} characters`); + + if (!context || context.trim().length === 0) { + console.log('⚠️ Retrieved documents have no content, falling back to LLM'); + const fallbackPromptTemplate = PromptTemplate.fromTemplate(` +You are a helpful assistant answering questions based on your general knowledge. + +Question: {query} + +Answer: +`); + + const fallbackChain = RunnableSequence.from([ + { + query: () => query, + }, + fallbackPromptTemplate, + this.llm, + new StringOutputParser(), + ]); + + const answer = await fallbackChain.invoke({}); + return { + answer: `[Note: No specific information was found in the knowledge base. This answer is based on general knowledge.]\n\n${answer}`, + documentCount: similarDocs.length + }; + } + + // Define prompt template for RAG const promptTemplate = PromptTemplate.fromTemplate(` -Answer the question based only on the following context: +Answer the question based only on the following context from the knowledge base. +If you cannot find the answer in the context, say "I cannot find this information in the knowledge base." Context: {context} @@ -185,7 +306,7 @@ Question: {query} Answer: `); - // Create retrieval chain + // Create retrieval chain using RunnableSequence const retrievalChain = RunnableSequence.from([ { context: () => context, @@ -196,9 +317,22 @@ Answer: new StringOutputParser(), ]); + console.log('πŸ€– Generating answer with NVIDIA LLM...'); + // Execute chain - const answer = await retrievalChain.invoke({}); - return answer; + try { + const answer = await retrievalChain.invoke({}); + console.log('βœ… RAG query completed successfully'); + console.log(`πŸ“ Answer length: ${answer.length} characters`); + console.log(`πŸ“„ Retrieved ${similarDocs.length} document chunks`); + return { + answer, + documentCount: similarDocs.length + }; + } catch (error) { + console.error('❌ Error generating answer with NVIDIA LLM:', error); + throw error; + } } /** @@ -215,15 +349,16 @@ Answer: await this.initialize(); } - // Generate embedding for query - const queryEmbedding = (await this.embeddingsService.encode([query]))[0]; + if (!this.vectorStore) { + throw new Error('Vector store not initialized'); + } - // Retrieve similar documents from Pinecone - const similarDocs = await this.pineconeService.findSimilarDocuments(queryEmbedding, topK); - - return similarDocs.map((doc: DocumentSearchResult) => ({ - text: doc.metadata?.text || '', - score: doc.score, + // Use LangChain's similarity search with scores + const results = await this.vectorStore.similaritySearchWithScore(query, topK); + + return results.map(([doc, score]) => ({ + text: doc.pageContent, + score: score, metadata: doc.metadata })); } diff --git a/nvidia/txt2kg/assets/frontend/lib/remote-backend.ts b/nvidia/txt2kg/assets/frontend/lib/remote-backend.ts index 9b1d13e..bf9618e 100644 --- a/nvidia/txt2kg/assets/frontend/lib/remote-backend.ts +++ b/nvidia/txt2kg/assets/frontend/lib/remote-backend.ts @@ -1,18 +1,34 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { GraphDBService, GraphDBType } from './graph-db-service'; -import { PineconeService } from './pinecone'; +import { QdrantService } from './qdrant'; import { EmbeddingsService } from './embeddings'; import { TextProcessor } from './text-processor'; import type { Triple } from '@/types/graph'; /** * Remote backend implementation that uses a graph database for storage, - * Pinecone for vector embeddings, and SentenceTransformer for generating embeddings. + * Qdrant for vector embeddings, and SentenceTransformer for generating embeddings. * Follows the implementation in PyTorch Geometric's txt2kg.py * Enhanced with LangChain text processing for better extraction */ export class RemoteBackendService { private graphDBService: GraphDBService; - private pineconeService: PineconeService; + private pineconeService: QdrantService; private embeddingsService: EmbeddingsService; private textProcessor: TextProcessor; private initialized: boolean = false; @@ -20,7 +36,7 @@ export class RemoteBackendService { private constructor() { this.graphDBService = GraphDBService.getInstance(); - this.pineconeService = PineconeService.getInstance(); + this.pineconeService = QdrantService.getInstance(); this.embeddingsService = EmbeddingsService.getInstance(); this.textProcessor = TextProcessor.getInstance(); } diff --git a/nvidia/txt2kg/assets/frontend/lib/text-processor.ts b/nvidia/txt2kg/assets/frontend/lib/text-processor.ts index cb8fbe1..6278c2e 100644 --- a/nvidia/txt2kg/assets/frontend/lib/text-processor.ts +++ b/nvidia/txt2kg/assets/frontend/lib/text-processor.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"; import { StructuredOutputParser } from "langchain/output_parsers"; import { PromptTemplate } from "@langchain/core/prompts"; @@ -76,6 +92,7 @@ export class TextProcessor { private ollamaBaseUrl: string = 'http://localhost:11434/v1'; private vllmModel: string = 'meta-llama/Llama-3.2-3B-Instruct'; private vllmBaseUrl: string = 'http://localhost:8001/v1'; + private nvidiaModel: string = 'nvidia/llama-3.3-nemotron-super-49b-v1.5'; // Default NVIDIA model private constructor() { this.sentenceTransformerUrl = process.env.SENTENCE_TRANSFORMER_URL || "http://localhost:8000"; @@ -138,11 +155,9 @@ export class TextProcessor { case 'nvidia': try { - // Use the default Nemotron model for NVIDIA - this.llm = await langChainService.getNemotronModel({ - temperature: 0.1, - maxTokens: 8192 - }); + // For NVIDIA, we'll use direct OpenAI client instead of LangChain + // This is handled in processText method + this.llm = null; // Set to null, will be handled differently } catch (error) { console.error('Failed to initialize NVIDIA model:', error); throw new Error(`Failed to initialize NVIDIA model: ${error instanceof Error ? error.message : String(error)}`); @@ -210,11 +225,16 @@ export class TextProcessor { await this.initialize(); } - // Ensure we have an LLM to extract triples + // For NVIDIA, use direct OpenAI client + if (this.selectedLLMProvider === 'nvidia') { + return await this.processTextWithNvidiaAPI(text); + } + + // Ensure we have an LLM to extract triples for non-NVIDIA providers if (!this.llm) { const providerMessage = this.selectedLLMProvider === 'ollama' ? "Ollama server connection failed. Please ensure Ollama is running and accessible." - : "NVIDIA API key is required. Please set NVIDIA_API_KEY in your environment variables."; + : "LLM configuration error"; throw new Error(`LLM configuration error: ${providerMessage}`); } @@ -222,14 +242,100 @@ export class TextProcessor { const chunks = await this.chunkText(text); console.log(`Split text into ${chunks.length} chunks`); - // Step 2: Process each chunk to extract triples + // Step 2: Process chunks in parallel with controlled concurrency + // DGX Spark has unified memory, so we can prefetch batches into GPU before processing + const concurrency = this.selectedLLMProvider === 'ollama' ? 4 : 2; // Higher concurrency for local Ollama + const allTriples: Array = []; + + console.log(`Processing with concurrency: ${concurrency} (provider: ${this.selectedLLMProvider})`); + + // Helper function to process a single chunk + const processChunk = async (chunk: string, index: number) => { + // Check if processing should be stopped + if (getShouldStopProcessing()) { + console.log(`Processing stopped by user at chunk ${index + 1}/${chunks.length}`); + resetStopProcessing(); + throw new Error('Processing stopped by user'); + } + + console.log(`Processing chunk ${index + 1}/${chunks.length} (${chunk.length} chars)`); + + // Format the prompt with the chunk and parser instructions + const formatInstructions = this.tripleParser!.getFormatInstructions(); + const prompt = await this.extractionTemplate!.format({ + text: chunk, + format_instructions: formatInstructions + }); + + // Extract triples using the LLM + const response = await this.llm!.invoke(prompt); + const responseText = response.content as string; + const parsedTriples = await this.tripleParser!.parse(responseText); + + return parsedTriples; + }; + + // Process chunks in batches with controlled concurrency + for (let i = 0; i < chunks.length; i += concurrency) { + const batch = chunks.slice(i, i + concurrency); + const batchIndices = Array.from({ length: batch.length }, (_, idx) => i + idx); + + console.log(`Processing batch ${Math.floor(i / concurrency) + 1}/${Math.ceil(chunks.length / concurrency)} (${batch.length} chunks in parallel)`); + + try { + // Process batch in parallel - GPU can prefetch next chunks while processing current ones + const results = await Promise.all( + batch.map((chunk, idx) => processChunk(chunk, batchIndices[idx])) + ); + + // Flatten and add to all triples + results.forEach((triples: Array) => { + allTriples.push(...triples); + }); + } catch (error) { + console.error(`Error processing batch:`, error); + // Continue with next batch instead of failing completely + if (error instanceof Error && error.message === 'Processing stopped by user') { + throw error; + } + } + } + + // Step 3: Post-process to remove duplicates and normalize + const processedTriples = this.postProcessTriples(allTriples); + console.log(`Extracted ${processedTriples.length} unique triples after post-processing`); + + return processedTriples; + } + + /** + * Process text using NVIDIA API directly with OpenAI client (bypasses LangChain) + * @param text Text to process + * @returns Array of triples with metadata + */ + private async processTextWithNvidiaAPI(text: string): Promise> { + const apiKey = process.env.NVIDIA_API_KEY; + if (!apiKey) { + throw new Error('NVIDIA_API_KEY is required but not set'); + } + + // Initialize parser if needed + if (!this.tripleParser) { + await this.initialize(); + } + + // Step 1: Chunk the text + const chunks = await this.chunkText(text); + console.log(`Split text into ${chunks.length} chunks`); + + // Step 2: Process each chunk const allTriples: Array = []; for (let i = 0; i < chunks.length; i++) { // Check if processing should be stopped if (getShouldStopProcessing()) { console.log(`Processing stopped by user at chunk ${i + 1}/${chunks.length}`); - resetStopProcessing(); // Reset the flag for next time + resetStopProcessing(); throw new Error('Processing stopped by user'); } @@ -237,25 +343,63 @@ export class TextProcessor { console.log(`Processing chunk ${i + 1}/${chunks.length} (${chunk.length} chars)`); try { - // Format the prompt with the chunk and parser instructions + // Create the prompt const formatInstructions = this.tripleParser!.getFormatInstructions(); - const prompt = await this.extractionTemplate!.format({ - text: chunk, - format_instructions: formatInstructions + const prompt = `You are a knowledge graph builder that extracts structured information from text. +Extract subject-predicate-object triples from the following text. + +Guidelines: +- Extract only factual triples present in the text +- Normalize entity names to their canonical form +- Assign appropriate confidence scores (0-1) +- Include entity types in metadata +- For each triple, include a brief context from the source text + +Text: ${chunk} + +${formatInstructions}`; + + // Call NVIDIA API directly using fetch + console.log(`πŸ–₯️ Calling NVIDIA API with model: ${this.nvidiaModel}`); + const response = await fetch('https://integrate.api.nvidia.com/v1/chat/completions', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${apiKey}` + }, + body: JSON.stringify({ + model: this.nvidiaModel, // Use the configured model + messages: [ + { + role: 'user', + content: prompt + } + ], + temperature: 0.1, + max_tokens: 8192, + top_p: 0.95 + }) }); - // Extract triples using the LLM - const response = await this.llm!.invoke(prompt); - const responseText = response.content as string; - const parsedTriples = await this.tripleParser!.parse(responseText); + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`NVIDIA API error (${response.status}): ${errorText}`); + } + + const data = await response.json(); + const responseText = data.choices[0].message.content; + // Parse the response + const parsedTriples = await this.tripleParser!.parse(responseText); allTriples.push(...parsedTriples); + } catch (error) { console.error(`Error processing chunk ${i + 1}:`, error); + throw error; // Re-throw to see the actual error } } - // Step 3: Post-process to remove duplicates and normalize + // Step 3: Post-process const processedTriples = this.postProcessTriples(allTriples); console.log(`Extracted ${processedTriples.length} unique triples after post-processing`); @@ -435,11 +579,15 @@ export class TextProcessor { ollamaBaseUrl?: string; vllmModel?: string; vllmBaseUrl?: string; + nvidiaModel?: string; }): void { this.selectedLLMProvider = provider; if (provider === 'ollama') { this.ollamaModel = options?.ollamaModel || this.ollamaModel; this.ollamaBaseUrl = options?.ollamaBaseUrl || this.ollamaBaseUrl; + } else if (provider === 'nvidia') { + this.nvidiaModel = options?.nvidiaModel || this.nvidiaModel; + console.log(`πŸ–₯️ TextProcessor: NVIDIA model set to: ${this.nvidiaModel}`); } else if (provider === 'vllm') { this.vllmModel = options?.vllmModel || this.vllmModel; this.vllmBaseUrl = options?.vllmBaseUrl || this.vllmBaseUrl; diff --git a/nvidia/txt2kg/assets/frontend/lib/utils.ts b/nvidia/txt2kg/assets/frontend/lib/utils.ts index f3d0231..2fb3e3c 100644 --- a/nvidia/txt2kg/assets/frontend/lib/utils.ts +++ b/nvidia/txt2kg/assets/frontend/lib/utils.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { clsx, type ClassValue } from "clsx" import { twMerge } from "tailwind-merge" diff --git a/nvidia/txt2kg/assets/frontend/next.config.mjs b/nvidia/txt2kg/assets/frontend/next.config.mjs index 6eff3b2..ca31ca2 100644 --- a/nvidia/txt2kg/assets/frontend/next.config.mjs +++ b/nvidia/txt2kg/assets/frontend/next.config.mjs @@ -14,6 +14,8 @@ const nextConfig = { experimental: { // webpackBuildWorker: true, }, + // Enable standalone output for optimized Docker builds + output: 'standalone', // Make environment variables accessible to server components env: { NVIDIA_API_KEY: process.env.NVIDIA_API_KEY, diff --git a/nvidia/txt2kg/assets/frontend/next.env.d.ts b/nvidia/txt2kg/assets/frontend/next.env.d.ts index de8f3d5..a6521c9 100644 --- a/nvidia/txt2kg/assets/frontend/next.env.d.ts +++ b/nvidia/txt2kg/assets/frontend/next.env.d.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// /// /// diff --git a/nvidia/txt2kg/assets/frontend/package.json b/nvidia/txt2kg/assets/frontend/package.json index afd5fdc..f64e9d8 100644 --- a/nvidia/txt2kg/assets/frontend/package.json +++ b/nvidia/txt2kg/assets/frontend/package.json @@ -1,5 +1,5 @@ { - "name": "my-v0-project", + "name": "txt2kg", "version": "0.1.0", "private": true, "scripts": { @@ -19,8 +19,8 @@ "@langchain/community": "^0.3.40", "@langchain/core": "^0.3.43", "@langchain/openai": "^0.5.2", + "@qdrant/js-client-rest": "^1.11.0", "@radix-ui/react-alert-dialog": "^1.1.4", - "@radix-ui/react-avatar": "^1.1.2", "@radix-ui/react-checkbox": "^1.1.3", "@radix-ui/react-collapsible": "^1.1.2", "@radix-ui/react-dialog": "^1.1.4", diff --git a/nvidia/txt2kg/assets/frontend/tailwind.config.ts b/nvidia/txt2kg/assets/frontend/tailwind.config.ts index c9355e9..e5bcc09 100644 --- a/nvidia/txt2kg/assets/frontend/tailwind.config.ts +++ b/nvidia/txt2kg/assets/frontend/tailwind.config.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import type { Config } from "tailwindcss" const config: Config = { diff --git a/nvidia/txt2kg/assets/frontend/types/graph.ts b/nvidia/txt2kg/assets/frontend/types/graph.ts index b6ab52e..8ad20d0 100644 --- a/nvidia/txt2kg/assets/frontend/types/graph.ts +++ b/nvidia/txt2kg/assets/frontend/types/graph.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// /** * Triple interface representing a knowledge graph edge */ diff --git a/nvidia/txt2kg/assets/frontend/types/next-navigation.d.ts b/nvidia/txt2kg/assets/frontend/types/next-navigation.d.ts index a67f87b..911267a 100644 --- a/nvidia/txt2kg/assets/frontend/types/next-navigation.d.ts +++ b/nvidia/txt2kg/assets/frontend/types/next-navigation.d.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// declare module 'next/navigation' { export function useRouter(): { push: (url: string) => void; diff --git a/nvidia/txt2kg/assets/frontend/utils/remote-webgpu-clustering.ts b/nvidia/txt2kg/assets/frontend/utils/remote-webgpu-clustering.ts index a1fcde1..c2c875c 100644 --- a/nvidia/txt2kg/assets/frontend/utils/remote-webgpu-clustering.ts +++ b/nvidia/txt2kg/assets/frontend/utils/remote-webgpu-clustering.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// // Remote WebGPU Clustering Client // Provides fallback clustering when local WebGPU is not available diff --git a/nvidia/txt2kg/assets/frontend/utils/s3-storage.ts b/nvidia/txt2kg/assets/frontend/utils/s3-storage.ts index 0f89a1e..29debb9 100644 --- a/nvidia/txt2kg/assets/frontend/utils/s3-storage.ts +++ b/nvidia/txt2kg/assets/frontend/utils/s3-storage.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// import { S3Client, PutObjectCommand, GetObjectCommand, ListObjectsV2Command, DeleteObjectCommand, _Object } from '@aws-sdk/client-s3'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; diff --git a/nvidia/txt2kg/assets/frontend/utils/text-processing.ts b/nvidia/txt2kg/assets/frontend/utils/text-processing.ts index 93f2fb3..f6d292a 100644 --- a/nvidia/txt2kg/assets/frontend/utils/text-processing.ts +++ b/nvidia/txt2kg/assets/frontend/utils/text-processing.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// /** * Text processing utilities for knowledge graph extraction * Matches PyTorch Geometric's txt2kg.py implementation diff --git a/nvidia/txt2kg/assets/frontend/utils/webgpu-clustering.ts b/nvidia/txt2kg/assets/frontend/utils/webgpu-clustering.ts index 8e43665..9a65027 100644 --- a/nvidia/txt2kg/assets/frontend/utils/webgpu-clustering.ts +++ b/nvidia/txt2kg/assets/frontend/utils/webgpu-clustering.ts @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// // WebGPU Clustering utilities for NVIDIA GPU acceleration // This implements clustered rendering for knowledge graphs diff --git a/nvidia/txt2kg/assets/scripts/benchmark_llm.py b/nvidia/txt2kg/assets/scripts/benchmark_llm.py index 70a7b57..4fd0815 100755 --- a/nvidia/txt2kg/assets/scripts/benchmark_llm.py +++ b/nvidia/txt2kg/assets/scripts/benchmark_llm.py @@ -1,4 +1,20 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# """ LLM Benchmark Script: vLLM vs Ollama Performance Comparison Compares performance metrics between vLLM and Ollama deployments diff --git a/nvidia/txt2kg/assets/scripts/gnn/arangodb_txt2kg.py b/nvidia/txt2kg/assets/scripts/gnn/arangodb_txt2kg.py index 727eeb0..73eced4 100755 --- a/nvidia/txt2kg/assets/scripts/gnn/arangodb_txt2kg.py +++ b/nvidia/txt2kg/assets/scripts/gnn/arangodb_txt2kg.py @@ -1,4 +1,20 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# import argparse import gc diff --git a/nvidia/txt2kg/assets/scripts/gnn/preprocess_data.py b/nvidia/txt2kg/assets/scripts/gnn/preprocess_data.py index 727eeb0..73eced4 100644 --- a/nvidia/txt2kg/assets/scripts/gnn/preprocess_data.py +++ b/nvidia/txt2kg/assets/scripts/gnn/preprocess_data.py @@ -1,4 +1,20 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# import argparse import gc diff --git a/nvidia/txt2kg/assets/scripts/gnn/train_test_gnn.py b/nvidia/txt2kg/assets/scripts/gnn/train_test_gnn.py index 21845cf..6b99331 100644 --- a/nvidia/txt2kg/assets/scripts/gnn/train_test_gnn.py +++ b/nvidia/txt2kg/assets/scripts/gnn/train_test_gnn.py @@ -1,4 +1,20 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# import argparse import os diff --git a/nvidia/txt2kg/assets/scripts/kg_extraction_benchmark.py b/nvidia/txt2kg/assets/scripts/kg_extraction_benchmark.py index 50ef484..b582f21 100755 --- a/nvidia/txt2kg/assets/scripts/kg_extraction_benchmark.py +++ b/nvidia/txt2kg/assets/scripts/kg_extraction_benchmark.py @@ -1,4 +1,20 @@ #!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# """ Knowledge Graph Extraction Benchmark: vLLM vs Ollama Realistic benchmark based on the txt2kg codebase use case diff --git a/nvidia/txt2kg/assets/scripts/setup-pinecone.js b/nvidia/txt2kg/assets/scripts/setup-pinecone.js index 37f4196..4b17b75 100644 --- a/nvidia/txt2kg/assets/scripts/setup-pinecone.js +++ b/nvidia/txt2kg/assets/scripts/setup-pinecone.js @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// /** * Simplified Pinecone setup script for Docker environments */ diff --git a/nvidia/txt2kg/assets/scripts/test-graph-transformer.js b/nvidia/txt2kg/assets/scripts/test-graph-transformer.js index d41dc3f..94442f0 100644 --- a/nvidia/txt2kg/assets/scripts/test-graph-transformer.js +++ b/nvidia/txt2kg/assets/scripts/test-graph-transformer.js @@ -1,3 +1,19 @@ +// +// SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// // Test script for LLMGraphTransformer - DEPRECATED // xAI integration has been removed // const { ChatXAI } = require('@langchain/xai'); diff --git a/nvidia/txt2kg/assets/start.sh b/nvidia/txt2kg/assets/start.sh index 6a8dd05..a386dcd 100755 --- a/nvidia/txt2kg/assets/start.sh +++ b/nvidia/txt2kg/assets/start.sh @@ -1,4 +1,20 @@ #!/bin/bash +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# # Setup script for txt2kg project @@ -78,6 +94,32 @@ else exit 1 fi +# Check Docker daemon permissions +echo "Checking Docker permissions..." +if ! docker info &> /dev/null; then + echo "" + echo "==========================================" + echo "ERROR: Docker Permission Denied" + echo "==========================================" + echo "" + echo "You don't have permission to connect to the Docker daemon." + echo "" + echo "To fix this, run one of the following:" + echo "" + echo "Option 1 (Recommended): Add your user to the docker group" + echo " sudo usermod -aG docker \$USER" + echo " newgrp docker" + echo "" + echo "Option 2: Run this script with sudo (not recommended)" + echo " sudo ./start.sh" + echo "" + echo "After adding yourself to the docker group, you may need to log out" + echo "and log back in for the changes to take effect." + echo "" + exit 1 +fi +echo "βœ“ Docker permissions OK" + # Build the docker-compose command if [ "$USE_COMPLETE" = true ]; then CMD="$DOCKER_COMPOSE_CMD -f $(pwd)/deploy/compose/docker-compose.complete.yml" @@ -121,6 +163,7 @@ echo " 2. Open http://localhost:3001 in your browser" echo " 3. Upload documents and start building your knowledge graph!" echo "" echo "Other options:" +echo " β€’ Stop services: ./stop.sh" echo " β€’ Run frontend in dev mode: ./start.sh --dev-frontend" echo " β€’ Use complete stack: ./start.sh --complete" echo " β€’ View logs: docker compose logs -f" diff --git a/nvidia/txt2kg/assets/stop.sh b/nvidia/txt2kg/assets/stop.sh new file mode 100755 index 0000000..d67aaf6 --- /dev/null +++ b/nvidia/txt2kg/assets/stop.sh @@ -0,0 +1,100 @@ +#!/bin/bash +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Stop script for txt2kg project + +# Parse command line arguments +USE_COMPLETE=false + +while [[ $# -gt 0 ]]; do + case $1 in + --complete) + USE_COMPLETE=true + shift + ;; + --help|-h) + echo "Usage: ./stop.sh [OPTIONS]" + echo "" + echo "Options:" + echo " --complete Stop complete stack (vLLM, Pinecone, Sentence Transformers)" + echo " --help, -h Show this help message" + echo "" + echo "Default: Stops minimal stack with Ollama, ArangoDB, and Next.js frontend" + echo "" + echo "Examples:" + echo " ./stop.sh # Stop minimal demo" + echo " ./stop.sh --complete # Stop complete stack" + exit 0 + ;; + *) + echo "Unknown option: $1" + echo "Run './stop.sh --help' for usage information" + exit 1 + ;; + esac +done + +# Check which Docker Compose version is available +DOCKER_COMPOSE_CMD="" +if docker compose version &> /dev/null; then + DOCKER_COMPOSE_CMD="docker compose" +elif command -v docker-compose &> /dev/null; then + DOCKER_COMPOSE_CMD="docker-compose" +else + echo "Error: Neither 'docker compose' nor 'docker-compose' is available" + echo "Please install Docker Compose: https://docs.docker.com/compose/install/" + exit 1 +fi + +# Check Docker daemon permissions +if ! docker info &> /dev/null; then + echo "" + echo "==========================================" + echo "ERROR: Docker Permission Denied" + echo "==========================================" + echo "" + echo "You don't have permission to connect to the Docker daemon." + echo "" + echo "To fix this, add your user to the docker group:" + echo " sudo usermod -aG docker \$USER" + echo " newgrp docker" + echo "" + exit 1 +fi + +# Build the docker-compose command +if [ "$USE_COMPLETE" = true ]; then + CMD="$DOCKER_COMPOSE_CMD -f $(pwd)/deploy/compose/docker-compose.complete.yml" + echo "Stopping complete stack..." +else + CMD="$DOCKER_COMPOSE_CMD -f $(pwd)/deploy/compose/docker-compose.yml" + echo "Stopping minimal configuration..." +fi + +# Execute the command +echo "Running: $CMD down" +cd $(dirname "$0") +eval "$CMD down" + +echo "" +echo "==========================================" +echo "txt2kg has been stopped" +echo "==========================================" +echo "" +echo "To start again, run: ./start.sh" +echo ""