mirror of
https://github.com/NVIDIA/dgx-spark-playbooks.git
synced 2026-04-25 11:23:52 +00:00
chore: Regenerate all playbooks
This commit is contained in:
parent
65d43d3ae6
commit
373591c46f
@ -54,8 +54,9 @@ The setup includes:
|
|||||||
- Document processing time scales with document size and complexity
|
- Document processing time scales with document size and complexity
|
||||||
|
|
||||||
- **Rollback**: Stop and remove Docker containers, delete downloaded models if needed
|
- **Rollback**: Stop and remove Docker containers, delete downloaded models if needed
|
||||||
- **Last Updated**: 11/19/2025
|
- **Last Updated**: 12/02/2025
|
||||||
- Updated GPU Visualization Service
|
- Knowledge graph search with multi-hop graph traversal
|
||||||
|
- Improved UI/UX
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,44 @@
|
|||||||
|
# Dependencies
|
||||||
node_modules
|
node_modules
|
||||||
|
.pnpm-store
|
||||||
|
**/node_modules
|
||||||
|
**/.pnpm-store
|
||||||
|
|
||||||
|
# Next.js build outputs
|
||||||
.next
|
.next
|
||||||
|
out
|
||||||
|
**/.next
|
||||||
|
**/out
|
||||||
|
|
||||||
|
# Git
|
||||||
.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
|
||||||
@ -1,48 +1,74 @@
|
|||||||
# Use the official Node.js image from the Docker Hub
|
# Optimized multi-stage Dockerfile for faster builds
|
||||||
FROM node:18-slim
|
# Stage 1: Dependencies
|
||||||
|
FROM node:18-slim AS deps
|
||||||
# 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
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install pnpm globally with --force and yes flags
|
# Install pnpm
|
||||||
RUN npm install -g pnpm --force --yes
|
RUN npm install -g pnpm --force --yes
|
||||||
|
|
||||||
# Copy package files ONLY (for better Docker layer caching)
|
# Copy dependency files
|
||||||
# Copy package.json (required) and pnpm-lock.yaml (optional)
|
COPY ./frontend/package.json ./frontend/pnpm-lock.yaml* ./
|
||||||
COPY ./frontend/package.json ./
|
|
||||||
COPY ./frontend/pnpm-lock.yaml* ./
|
|
||||||
|
|
||||||
# Copy the scripts directory (needed for setup-pinecone)
|
|
||||||
COPY ./scripts/ /scripts/
|
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
|
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)
|
# Install dependencies with cache mount for faster rebuilds
|
||||||
# Use --no-frozen-lockfile as fallback if lockfile is missing or out of sync
|
RUN --mount=type=cache,target=/root/.local/share/pnpm/store \
|
||||||
RUN pnpm config set auto-install-peers true && \
|
pnpm config set auto-install-peers true && \
|
||||||
if [ -f pnpm-lock.yaml ]; then \
|
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 \
|
else \
|
||||||
echo "No lock file found, installing without frozen lockfile..." && \
|
|
||||||
pnpm install --no-optional --no-frozen-lockfile; \
|
pnpm install --no-optional --no-frozen-lockfile; \
|
||||||
fi
|
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/ ./
|
COPY ./frontend/ ./
|
||||||
|
|
||||||
# Build the application
|
# Set build environment variables
|
||||||
RUN pnpm build
|
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
|
EXPOSE 3000
|
||||||
|
|
||||||
# Start the application
|
ENV PORT 3000
|
||||||
CMD ["pnpm", "start"]
|
ENV HOSTNAME "0.0.0.0"
|
||||||
|
|
||||||
|
CMD ["node", "server.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
|
// ArangoDB initialization script to create the txt2kg database
|
||||||
// This script is executed automatically when the ArangoDB container starts
|
// This script is executed automatically when the ArangoDB container starts
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/bin/bash
|
#!/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
|
set -e
|
||||||
|
|
||||||
# Wait for ArangoDB to be ready
|
# Wait for ArangoDB to be ready
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/bin/sh
|
#!/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
|
# Script to initialize Pinecone index at container startup
|
||||||
echo "Initializing Pinecone index..."
|
echo "Initializing Pinecone index..."
|
||||||
|
|||||||
68
nvidia/txt2kg/assets/deploy/app/qdrant-init.sh
Normal file
68
nvidia/txt2kg/assets/deploy/app/qdrant-init.sh
Normal file
@ -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"
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
build:
|
build:
|
||||||
@ -8,12 +9,18 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- ARANGODB_URL=http://arangodb:8529
|
- ARANGODB_URL=http://arangodb:8529
|
||||||
- ARANGODB_DB=txt2kg
|
- ARANGODB_DB=txt2kg
|
||||||
|
- QDRANT_URL=http://qdrant:6333
|
||||||
|
- VECTOR_DB_TYPE=qdrant
|
||||||
- LANGCHAIN_TRACING_V2=true
|
- 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
|
- GRPC_SSL_CIPHER_SUITES=HIGH+ECDSA:HIGH+aRSA
|
||||||
- NODE_TLS_REJECT_UNAUTHORIZED=0
|
- NODE_TLS_REJECT_UNAUTHORIZED=0
|
||||||
- OLLAMA_BASE_URL=http://ollama:11434/v1
|
- OLLAMA_BASE_URL=http://ollama:11434/v1
|
||||||
- OLLAMA_MODEL=llama3.1:8b
|
- OLLAMA_MODEL=llama3.1:8b
|
||||||
- REMOTE_WEBGPU_SERVICE_URL=http://txt2kg-remote-webgpu:8083
|
- REMOTE_WEBGPU_SERVICE_URL=http://txt2kg-remote-webgpu:8083
|
||||||
|
- NVIDIA_API_KEY=${NVIDIA_API_KEY:-}
|
||||||
# Node.js timeout configurations for large model processing
|
# Node.js timeout configurations for large model processing
|
||||||
- NODE_OPTIONS=--max-http-header-size=80000
|
- NODE_OPTIONS=--max-http-header-size=80000
|
||||||
- UV_THREADPOOL_SIZE=128
|
- UV_THREADPOOL_SIZE=128
|
||||||
@ -22,9 +29,12 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- default
|
- default
|
||||||
- txt2kg-network
|
- txt2kg-network
|
||||||
|
- pinecone-net
|
||||||
depends_on:
|
depends_on:
|
||||||
- arangodb
|
- arangodb
|
||||||
- ollama
|
- ollama
|
||||||
|
# Optional: sentence-transformers and entity-embeddings are only needed for vector search
|
||||||
|
# Traditional graph search works without these services
|
||||||
arangodb:
|
arangodb:
|
||||||
image: arangodb:latest
|
image: arangodb:latest
|
||||||
ports:
|
ports:
|
||||||
@ -58,16 +68,13 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ollama_data:/root/.ollama
|
- ollama_data:/root/.ollama
|
||||||
environment:
|
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_FLASH_ATTENTION=1 # Enable flash attention for better performance
|
||||||
- OLLAMA_KEEP_ALIVE=30m # Keep models loaded for 30 minutes
|
- OLLAMA_KEEP_ALIVE=30m # Keep models loaded for 30 minutes
|
||||||
- OLLAMA_CUDA=1 # Enable CUDA acceleration
|
- OLLAMA_NUM_PARALLEL=4 # Process 4 requests in parallel - DGX Spark has unified memory
|
||||||
- OLLAMA_LLM_LIBRARY=cuda # Use CUDA library for LLM operations
|
|
||||||
- OLLAMA_NUM_PARALLEL=1 # Process one request at a time for 70B models
|
|
||||||
- OLLAMA_MAX_LOADED_MODELS=1 # Load only one model at a time to avoid VRAM contention
|
- 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_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:
|
networks:
|
||||||
- default
|
- default
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@ -79,19 +86,90 @@ services:
|
|||||||
count: all
|
count: all
|
||||||
capabilities: [gpu]
|
capabilities: [gpu]
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:11434/api/tags"]
|
test: ["CMD", "ollama", "list"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 60s
|
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:
|
volumes:
|
||||||
arangodb_data:
|
arangodb_data:
|
||||||
arangodb_apps_data:
|
arangodb_apps_data:
|
||||||
ollama_data:
|
ollama_data:
|
||||||
|
qdrant_data:
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
txt2kg-network:
|
txt2kg-network:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
|
pinecone-net:
|
||||||
|
name: pinecone
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/usr/bin/env python3
|
#!/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 os
|
||||||
import torch
|
import torch
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/usr/bin/env python3
|
#!/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 requests
|
||||||
import json
|
import json
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/usr/bin/env python3
|
#!/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 os
|
||||||
import argparse
|
import argparse
|
||||||
|
|||||||
@ -23,6 +23,7 @@ RUN pip install --no-cache-dir -r requirements.txt
|
|||||||
|
|
||||||
# Copy the service code
|
# Copy the service code
|
||||||
COPY unified_gpu_service.py .
|
COPY unified_gpu_service.py .
|
||||||
|
COPY pygraphistry_service.py .
|
||||||
|
|
||||||
# Create a non-root user for security (using a different UID to avoid conflicts)
|
# 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
|
RUN useradd -m -u 1001 appuser && chown -R appuser:appuser /app
|
||||||
|
|||||||
@ -9,11 +9,12 @@ This directory contains optional GPU-accelerated graph visualization services th
|
|||||||
## 📦 Available Services
|
## 📦 Available Services
|
||||||
|
|
||||||
### 1. Unified GPU Service (`unified_gpu_service.py`)
|
### 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:**
|
**Processing Modes:**
|
||||||
| Mode | Description | Requirements |
|
| 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 GPU (cuGraph)** | Full GPU processing on your hardware | NVIDIA GPU + cuGraph |
|
||||||
| **Local CPU** | NetworkX fallback processing | None |
|
| **Local CPU** | NetworkX fallback processing | None |
|
||||||
|
|
||||||
@ -26,8 +27,9 @@ Local GPU processing service with WebSocket support for real-time updates.
|
|||||||
## 🛠️ Setup
|
## 🛠️ Setup
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
- NVIDIA GPU with CUDA support (for GPU mode)
|
- NVIDIA GPU with CUDA support (for GPU modes)
|
||||||
- RAPIDS cuGraph (for local GPU processing)
|
- RAPIDS cuGraph (for local GPU processing)
|
||||||
|
- PyGraphistry account (for cloud mode)
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
@ -92,8 +94,9 @@ Response:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"processing_modes": {
|
"processing_modes": {
|
||||||
"local_gpu": {"available": true, "description": "Local GPU processing with cuGraph/RAPIDS"},
|
"pygraphistry_cloud": {"available": true, "description": "..."},
|
||||||
"local_cpu": {"available": true, "description": "Local CPU fallback processing with NetworkX"}
|
"local_gpu": {"available": true, "description": "..."},
|
||||||
|
"local_cpu": {"available": true, "description": "..."}
|
||||||
},
|
},
|
||||||
"has_rapids": true,
|
"has_rapids": true,
|
||||||
"gpu_available": true
|
"gpu_available": true
|
||||||
@ -105,18 +108,33 @@ Response:
|
|||||||
The txt2kg frontend includes built-in components for GPU visualization:
|
The txt2kg frontend includes built-in components for GPU visualization:
|
||||||
|
|
||||||
- `UnifiedGPUViewer`: Connects to unified GPU service
|
- `UnifiedGPUViewer`: Connects to unified GPU service
|
||||||
|
- `PyGraphistryViewer`: Direct PyGraphistry cloud integration
|
||||||
- `ForceGraphWrapper`: Three.js WebGPU visualization (default)
|
- `ForceGraphWrapper`: Three.js WebGPU visualization (default)
|
||||||
|
|
||||||
### Using GPU Services in Frontend
|
### Using GPU Services in Frontend
|
||||||
|
|
||||||
The frontend has API routes that can connect to these services:
|
The frontend has API routes that can connect to these services:
|
||||||
|
- `/api/pygraphistry/*`: PyGraphistry integration
|
||||||
- `/api/unified-gpu/*`: Unified GPU service integration
|
- `/api/unified-gpu/*`: Unified GPU service integration
|
||||||
|
|
||||||
To use these services, ensure they are running separately and configure the frontend environment variables accordingly.
|
To use these services, ensure they are running separately and configure the frontend environment variables accordingly.
|
||||||
|
|
||||||
### Processing Graph Data
|
### Mode-Specific Processing
|
||||||
|
|
||||||
```javascript
|
```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
|
// Local GPU mode
|
||||||
const response = await fetch('/api/unified-gpu/visualize', {
|
const response = await fetch('/api/unified-gpu/visualize', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -129,20 +147,15 @@ const response = await fetch('/api/unified-gpu/visualize', {
|
|||||||
compute_centrality: true
|
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
|
## 🔧 Configuration Options
|
||||||
|
|
||||||
|
### PyGraphistry Cloud Mode
|
||||||
|
- `layout_type`: "force", "circular", "hierarchical"
|
||||||
|
- `gpu_acceleration`: true/false
|
||||||
|
- `clustering`: true/false
|
||||||
|
|
||||||
### Local GPU Mode
|
### Local GPU Mode
|
||||||
- `layout_algorithm`: "force_atlas2", "spectral", "fruchterman_reingold"
|
- `layout_algorithm`: "force_atlas2", "spectral", "fruchterman_reingold"
|
||||||
- `clustering_algorithm`: "leiden", "louvain", "spectral"
|
- `clustering_algorithm`: "leiden", "louvain", "spectral"
|
||||||
@ -159,7 +172,8 @@ const response = await fetch('/api/unified-gpu/visualize', {
|
|||||||
"processed_nodes": [...],
|
"processed_nodes": [...],
|
||||||
"processed_edges": [...],
|
"processed_edges": [...],
|
||||||
"processing_mode": "local_gpu",
|
"processing_mode": "local_gpu",
|
||||||
"layout_positions": {...},
|
"embed_url": "https://hub.graphistry.com/...", // Only for cloud mode
|
||||||
|
"layout_positions": {...}, // Only for local GPU mode
|
||||||
"clusters": {...},
|
"clusters": {...},
|
||||||
"centrality": {...},
|
"centrality": {...},
|
||||||
"stats": {
|
"stats": {
|
||||||
@ -173,17 +187,18 @@ const response = await fetch('/api/unified-gpu/visualize', {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🚀 Benefits
|
## 🚀 Benefits of Unified Approach
|
||||||
|
|
||||||
### ✅ Advantages
|
### ✅ Advantages
|
||||||
- **Single service** - One port, one deployment
|
- **Single service** - One port, one deployment
|
||||||
- **Mode switching** - Choose best processing per graph
|
- **Mode switching** - Choose best processing per graph
|
||||||
- **Fallback handling** - Graceful degradation if GPU unavailable
|
- **Fallback handling** - Graceful degradation if GPU unavailable
|
||||||
- **Consistent API** - Same interface for all modes
|
- **Consistent API** - Same interface for all modes
|
||||||
- **No GPL dependencies** - All dependencies are permissively licensed
|
- **Better testing** - Easy comparison between modes
|
||||||
|
|
||||||
### 🎯 Use Cases
|
### 🎯 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
|
- **Local CPU**: Development, testing, small graphs
|
||||||
|
|
||||||
## 🐛 Troubleshooting
|
## 🐛 Troubleshooting
|
||||||
@ -197,6 +212,16 @@ nvidia-smi
|
|||||||
python -c "import cudf, cugraph; print('RAPIDS OK')"
|
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
|
### Service Health
|
||||||
```bash
|
```bash
|
||||||
curl http://localhost:8080/api/health
|
curl http://localhost:8080/api/health
|
||||||
@ -204,13 +229,7 @@ curl http://localhost:8080/api/health
|
|||||||
|
|
||||||
## 📈 Performance Tips
|
## 📈 Performance Tips
|
||||||
|
|
||||||
1. **Large graphs (>100k nodes)**: Use `local_gpu` mode with RAPIDS cuGraph
|
1. **Large graphs (>100k nodes)**: Use `local_gpu` mode
|
||||||
2. **Development**: Use `local_cpu` mode for speed and simplicity
|
2. **Sharing/demos**: Use `pygraphistry_cloud` mode
|
||||||
3. **Mixed workloads**: Switch modes dynamically based on graph size and GPU availability
|
3. **Development**: Use `local_cpu` mode for speed
|
||||||
|
4. **Mixed workloads**: Switch modes dynamically based on graph size
|
||||||
## 📝 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)
|
|
||||||
@ -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 os
|
||||||
import json
|
import json
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|||||||
@ -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)
|
||||||
@ -1,4 +1,20 @@
|
|||||||
#!/usr/bin/env python3
|
#!/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
|
Remote GPU Rendering Service
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/usr/bin/env python3
|
#!/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
|
Remote WebGPU Clustering Service - CuPy Version with Semantic Clustering
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/usr/bin/env python3
|
#!/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
|
Remote WebGPU Clustering Service - CuPy Version
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
graphistry>=0.32.0
|
||||||
pandas>=2.0.0
|
pandas>=2.0.0
|
||||||
numpy>=1.24.0
|
numpy>=1.24.0
|
||||||
fastapi>=0.104.0
|
fastapi>=0.104.0
|
||||||
@ -6,6 +7,7 @@ pydantic>=2.0.0
|
|||||||
networkx>=3.0 # For efficient graph generation algorithms
|
networkx>=3.0 # For efficient graph generation algorithms
|
||||||
# cudf, cuml, cugraph are already included in PyG container
|
# cudf, cuml, cugraph are already included in PyG container
|
||||||
# cupy>=12.0.0 # 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
|
scikit-learn>=1.3.0 # For additional ML features
|
||||||
requests>=2.31.0
|
requests>=2.31.0
|
||||||
aiofiles>=23.0.0
|
aiofiles>=23.0.0
|
||||||
|
|||||||
@ -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
|
Semantic Clustering Service for Knowledge Graphs
|
||||||
Groups nodes by semantic similarity of names, types, and content rather than just spatial coordinates
|
Groups nodes by semantic similarity of names, types, and content rather than just spatial coordinates
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/usr/bin/env python3
|
#!/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
|
Simple WebGPU clustering test service
|
||||||
Minimal implementation to test basic functionality
|
Minimal implementation to test basic functionality
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/bin/bash
|
#!/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
|
# Start Remote GPU Rendering Services
|
||||||
# This script starts the custom remote GPU rendering service as an alternative to PyGraphistry cloud
|
# This script starts the custom remote GPU rendering service as an alternative to PyGraphistry cloud
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/bin/bash
|
#!/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
|
# Stop Remote GPU Rendering Services
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,25 @@
|
|||||||
#!/usr/bin/env python3
|
#!/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
|
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
|
import os
|
||||||
@ -22,6 +39,9 @@ from concurrent.futures import ThreadPoolExecutor
|
|||||||
import networkx as nx
|
import networkx as nx
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
|
# PyGraphistry imports
|
||||||
|
import graphistry
|
||||||
|
|
||||||
# GPU-accelerated imports (available in NVIDIA PyG container)
|
# GPU-accelerated imports (available in NVIDIA PyG container)
|
||||||
try:
|
try:
|
||||||
import cudf
|
import cudf
|
||||||
@ -48,6 +68,7 @@ logging.basicConfig(level=logging.INFO)
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class ProcessingMode(str, Enum):
|
class ProcessingMode(str, Enum):
|
||||||
|
PYGRAPHISTRY_CLOUD = "pygraphistry_cloud"
|
||||||
LOCAL_GPU = "local_gpu"
|
LOCAL_GPU = "local_gpu"
|
||||||
LOCAL_CPU = "local_cpu"
|
LOCAL_CPU = "local_cpu"
|
||||||
|
|
||||||
@ -75,7 +96,12 @@ class GraphGenerationRequest(BaseModel):
|
|||||||
|
|
||||||
class UnifiedVisualizationRequest(BaseModel):
|
class UnifiedVisualizationRequest(BaseModel):
|
||||||
graph_data: GraphData
|
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
|
# Local GPU options
|
||||||
layout_algorithm: Optional[str] = "force_atlas2"
|
layout_algorithm: Optional[str] = "force_atlas2"
|
||||||
@ -90,144 +116,8 @@ class GraphGenerationStatus(BaseModel):
|
|||||||
result: Optional[Dict[str, Any]] = None
|
result: Optional[Dict[str, Any]] = None
|
||||||
error: Optional[str] = None
|
error: Optional[str] = None
|
||||||
|
|
||||||
class LargeGraphGenerator:
|
# Import graph generation classes (keeping existing code)
|
||||||
"""Optimized graph generation using NetworkX and NumPy for performance"""
|
from pygraphistry_service import LargeGraphGenerator, init_graphistry
|
||||||
|
|
||||||
@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 LocalGPUProcessor:
|
class LocalGPUProcessor:
|
||||||
"""GPU-accelerated graph processing using cuGraph"""
|
"""GPU-accelerated graph processing using cuGraph"""
|
||||||
@ -333,10 +223,109 @@ class LocalGPUProcessor:
|
|||||||
logger.error(f"GPU centrality computation failed: {e}")
|
logger.error(f"GPU centrality computation failed: {e}")
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
class UnifiedGPUService:
|
class PyGraphistryProcessor:
|
||||||
"""Unified service offering local GPU and CPU processing"""
|
"""PyGraphistry cloud processing (existing functionality)"""
|
||||||
|
|
||||||
def __init__(self):
|
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.local_gpu_processor = LocalGPUProcessor()
|
||||||
self.generation_tasks = {}
|
self.generation_tasks = {}
|
||||||
self.executor = ThreadPoolExecutor(max_workers=4)
|
self.executor = ThreadPoolExecutor(max_workers=4)
|
||||||
@ -345,8 +334,12 @@ class UnifiedGPUService:
|
|||||||
async def process_graph(self, request: UnifiedVisualizationRequest) -> Dict[str, Any]:
|
async def process_graph(self, request: UnifiedVisualizationRequest) -> Dict[str, Any]:
|
||||||
"""Process graph with selected processing mode"""
|
"""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)
|
return await self._process_with_local_gpu(request)
|
||||||
|
|
||||||
else: # LOCAL_CPU
|
else: # LOCAL_CPU
|
||||||
return await self._process_with_local_cpu(request)
|
return await self._process_with_local_cpu(request)
|
||||||
|
|
||||||
@ -458,7 +451,7 @@ service = UnifiedGPUService()
|
|||||||
|
|
||||||
@app.post("/api/visualize")
|
@app.post("/api/visualize")
|
||||||
async def visualize_graph(request: UnifiedVisualizationRequest):
|
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)
|
result = await service.process_graph(request)
|
||||||
|
|
||||||
# Broadcast to connected WebSocket clients
|
# Broadcast to connected WebSocket clients
|
||||||
@ -485,13 +478,17 @@ async def get_capabilities():
|
|||||||
"""Get GPU capabilities and available processing modes"""
|
"""Get GPU capabilities and available processing modes"""
|
||||||
return {
|
return {
|
||||||
"processing_modes": {
|
"processing_modes": {
|
||||||
|
"pygraphistry_cloud": {
|
||||||
|
"available": service.pygraphistry_processor.initialized,
|
||||||
|
"description": "PyGraphistry cloud GPU processing with interactive embeds"
|
||||||
|
},
|
||||||
"local_gpu": {
|
"local_gpu": {
|
||||||
"available": HAS_RAPIDS,
|
"available": HAS_RAPIDS,
|
||||||
"description": "Local GPU processing with cuGraph/RAPIDS"
|
"description": "Local GPU processing with cuGraph/RAPIDS"
|
||||||
},
|
},
|
||||||
"local_cpu": {
|
"local_cpu": {
|
||||||
"available": True,
|
"available": True,
|
||||||
"description": "Local CPU fallback processing with NetworkX"
|
"description": "Local CPU fallback processing"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"has_rapids": HAS_RAPIDS,
|
"has_rapids": HAS_RAPIDS,
|
||||||
@ -543,6 +540,7 @@ async def health_check():
|
|||||||
"""Health check endpoint"""
|
"""Health check endpoint"""
|
||||||
return {
|
return {
|
||||||
"status": "healthy",
|
"status": "healthy",
|
||||||
|
"pygraphistry_initialized": service.pygraphistry_processor.initialized,
|
||||||
"local_gpu_available": HAS_RAPIDS,
|
"local_gpu_available": HAS_RAPIDS,
|
||||||
"torch_geometric": HAS_TORCH_GEOMETRIC,
|
"torch_geometric": HAS_TORCH_GEOMETRIC,
|
||||||
"timestamp": datetime.now().isoformat()
|
"timestamp": datetime.now().isoformat()
|
||||||
@ -573,6 +571,7 @@ async def get_visualization_page():
|
|||||||
<div>
|
<div>
|
||||||
<label>Processing Mode:</label>
|
<label>Processing Mode:</label>
|
||||||
<select id="processingMode">
|
<select id="processingMode">
|
||||||
|
<option value="pygraphistry_cloud">PyGraphistry Cloud</option>
|
||||||
<option value="local_gpu">Local GPU (cuGraph)</option>
|
<option value="local_gpu">Local GPU (cuGraph)</option>
|
||||||
<option value="local_cpu">Local CPU</option>
|
<option value="local_cpu">Local CPU</option>
|
||||||
</select>
|
</select>
|
||||||
@ -757,8 +756,23 @@ def startup_diagnostics():
|
|||||||
else:
|
else:
|
||||||
print("⚠ PyTorch Geometric not available")
|
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("")
|
||||||
print("🎯 Available Processing Modes:")
|
print("🎯 Available Processing Modes:")
|
||||||
|
print(" ☁️ PyGraphistry Cloud - Interactive GPU embeds (requires credentials)")
|
||||||
print(" 🚀 Local GPU (cuGraph) - Full local GPU processing")
|
print(" 🚀 Local GPU (cuGraph) - Full local GPU processing")
|
||||||
print(" 💻 Local CPU - NetworkX fallback")
|
print(" 💻 Local CPU - NetworkX fallback")
|
||||||
print("")
|
print("")
|
||||||
|
|||||||
@ -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
|
# WebGL-Enhanced Remote GPU Rendering Service
|
||||||
# Using Three.js for GPU-accelerated visualization
|
# Using Three.js for GPU-accelerated visualization
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM ollama/ollama:latest
|
FROM ollama/ollama:0.12.6
|
||||||
|
|
||||||
# Copy the entrypoint script
|
# Copy the entrypoint script
|
||||||
COPY entrypoint.sh /entrypoint.sh
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
|||||||
@ -1,5 +1,21 @@
|
|||||||
#!/bin/bash
|
#!/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
|
# Clear buffer cache and restart Ollama to fix unified memory detection
|
||||||
# This script addresses the issue where Ollama can't see full GPU memory
|
# This script addresses the issue where Ollama can't see full GPU memory
|
||||||
# due to buffer cache not being reclaimable in unified memory systems
|
# due to buffer cache not being reclaimable in unified memory systems
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/bin/bash
|
#!/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
|
set -e
|
||||||
|
|
||||||
# Start Ollama server in the background
|
# Start Ollama server in the background
|
||||||
|
|||||||
@ -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 flask import Flask, request, jsonify
|
||||||
from sentence_transformers import SentenceTransformer
|
from sentence_transformers import SentenceTransformer
|
||||||
import os
|
import os
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/bin/bash
|
#!/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
|
# Use latest stable vLLM release for better compute capability 12.1 support
|
||||||
# Clone the vLLM GitHub repo and use latest stable release.
|
# Clone the vLLM GitHub repo and use latest stable release.
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/bin/bash
|
#!/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
|
# Launch vLLM with NVIDIA Triton Inference Server optimized build
|
||||||
# This should have proper support for compute capability 12.1 (DGX Spark)
|
# This should have proper support for compute capability 12.1 (DGX Spark)
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/bin/bash
|
#!/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
|
# vLLM Llama3 8B Benchmark Runner
|
||||||
# Uses NVIDIA vLLM container for optimal performance
|
# Uses NVIDIA vLLM container for optimal performance
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/bin/bash
|
#!/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
|
# 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
|
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
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/bin/bash
|
#!/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
|
# vLLM startup script with NVFP4 quantization support for Llama 4 Scout
|
||||||
# Optimized for NVIDIA Blackwell and Hopper architectures
|
# Optimized for NVIDIA Blackwell and Hopper architectures
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/usr/bin/env python3
|
#!/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.
|
Download and process the MTEB raw_biorxiv dataset for txt2kg demo.
|
||||||
Filter for genetics/genomics categories and create individual txt files.
|
Filter for genetics/genomics categories and create individual txt files.
|
||||||
|
|||||||
@ -1,4 +1,20 @@
|
|||||||
#!/usr/bin/env python3
|
#!/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.
|
Download and process the marianna13/biorxiv dataset for txt2kg demo.
|
||||||
Filter for Creative Commons licensed papers and create individual txt files.
|
Filter for Creative Commons licensed papers and create individual txt files.
|
||||||
|
|||||||
@ -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')
|
console.log('This is mock data to avoid SSR issues')
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import remoteBackend from '@/lib/remote-backend';
|
import remoteBackend from '@/lib/remote-backend';
|
||||||
import type { Triple } from '@/types/graph';
|
import type { Triple } from '@/types/graph';
|
||||||
|
|||||||
@ -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";
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { EmbeddingsService } from '@/lib/embeddings';
|
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) {
|
export async function POST(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
@ -39,14 +55,14 @@ export async function POST(request: NextRequest) {
|
|||||||
const embeddings = await embeddingsService.encode(chunks);
|
const embeddings = await embeddingsService.encode(chunks);
|
||||||
console.log(`Generated ${embeddings.length} embeddings`);
|
console.log(`Generated ${embeddings.length} embeddings`);
|
||||||
|
|
||||||
// Initialize PineconeService
|
// Initialize QdrantService
|
||||||
const pineconeService = PineconeService.getInstance();
|
const pineconeService = QdrantService.getInstance();
|
||||||
|
|
||||||
// Check if Pinecone server is running
|
// Check if Qdrant server is running
|
||||||
const isPineconeRunning = await pineconeService.isPineconeRunning();
|
const isPineconeRunning = await pineconeService.isQdrantRunning();
|
||||||
if (!isPineconeRunning) {
|
if (!isPineconeRunning) {
|
||||||
return NextResponse.json(
|
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 }
|
{ status: 503 }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { RemoteBackendService } from '@/lib/remote-backend';
|
import { RemoteBackendService } from '@/lib/remote-backend';
|
||||||
|
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { processDocument, TextProcessor } from '@/lib/text-processor';
|
import { processDocument, TextProcessor } from '@/lib/text-processor';
|
||||||
import { llmService } from '@/lib/llm-service';
|
import { llmService } from '@/lib/llm-service';
|
||||||
@ -29,7 +45,8 @@ export async function POST(req: NextRequest) {
|
|||||||
ollamaModel,
|
ollamaModel,
|
||||||
ollamaBaseUrl,
|
ollamaBaseUrl,
|
||||||
vllmModel,
|
vllmModel,
|
||||||
vllmBaseUrl
|
vllmBaseUrl,
|
||||||
|
nvidiaModel
|
||||||
} = body;
|
} = body;
|
||||||
|
|
||||||
if (!text || typeof text !== 'string') {
|
if (!text || typeof text !== 'string') {
|
||||||
@ -136,7 +153,8 @@ export async function POST(req: NextRequest) {
|
|||||||
ollamaModel: ollamaModel,
|
ollamaModel: ollamaModel,
|
||||||
ollamaBaseUrl: ollamaBaseUrl,
|
ollamaBaseUrl: ollamaBaseUrl,
|
||||||
vllmModel: vllmModel,
|
vllmModel: vllmModel,
|
||||||
vllmBaseUrl: vllmBaseUrl
|
vllmBaseUrl: vllmBaseUrl,
|
||||||
|
nvidiaModel: nvidiaModel
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import queryLoggerService, { QueryLogEntry } from '@/lib/query-logger';
|
import queryLoggerService, { QueryLogEntry } from '@/lib/query-logger';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
|||||||
@ -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"
|
import { type NextRequest, NextResponse } from "next/server"
|
||||||
|
|
||||||
// Utility function to generate UUID with fallback
|
// Utility function to generate UUID with fallback
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { getGraphDbService } from '@/lib/graph-db-util';
|
import { getGraphDbService } from '@/lib/graph-db-util';
|
||||||
import { getGraphDbType } from '../../settings/route';
|
import { getGraphDbType } from '../../settings/route';
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { getGraphDbService } from '@/lib/graph-db-util';
|
import { getGraphDbService } from '@/lib/graph-db-util';
|
||||||
import { getGraphDbType } from '../../settings/route';
|
import { getGraphDbType } from '../../settings/route';
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { getGraphDbService } from '@/lib/graph-db-util';
|
import { getGraphDbService } from '@/lib/graph-db-util';
|
||||||
import { getGraphDbType } from '../settings/route';
|
import { getGraphDbType } from '../settings/route';
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { getGraphDbService } from '@/lib/graph-db-util';
|
import { getGraphDbService } from '@/lib/graph-db-util';
|
||||||
import { getGraphDbType } from '../../settings/route';
|
import { getGraphDbType } from '../../settings/route';
|
||||||
@ -160,6 +176,16 @@ export async function POST(req: NextRequest) {
|
|||||||
// Store triples in the graph database
|
// Store triples in the graph database
|
||||||
await graphDbService.importTriples(validTriples);
|
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 success response
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
success: true,
|
success: true,
|
||||||
|
|||||||
@ -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 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import remoteBackendInstance from '@/lib/remote-backend';
|
import remoteBackendInstance from '@/lib/remote-backend';
|
||||||
import { Neo4jService } from '@/lib/neo4j';
|
import { getGraphDbService } from '@/lib/graph-db-util';
|
||||||
import neo4jService from '@/lib/neo4j';
|
import { getGraphDbType } from '../settings/route';
|
||||||
import { PineconeService } from '@/lib/pinecone';
|
import { QdrantService } from '@/lib/qdrant';
|
||||||
import RAGService from '@/lib/rag';
|
import RAGService from '@/lib/rag';
|
||||||
import queryLoggerService, { QueryLogSummary } from '@/lib/query-logger';
|
import queryLoggerService, { QueryLogSummary } from '@/lib/query-logger';
|
||||||
|
|
||||||
@ -11,16 +27,31 @@ import queryLoggerService, { QueryLogSummary } from '@/lib/query-logger';
|
|||||||
*/
|
*/
|
||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
// Initialize services
|
// Initialize services with the correct graph database type
|
||||||
const neo4j = Neo4jService.getInstance();
|
const graphDbType = getGraphDbType();
|
||||||
const pineconeService = PineconeService.getInstance();
|
const graphDbService = getGraphDbService(graphDbType);
|
||||||
|
const pineconeService = QdrantService.getInstance();
|
||||||
|
|
||||||
if (!neo4j.isInitialized()) {
|
// Initialize graph database if needed
|
||||||
neo4j.initialize();
|
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
|
// Get graph stats from the active graph database
|
||||||
const graphData = await neo4j.getGraphData();
|
const graphData = await graphDbService.getGraphData();
|
||||||
|
|
||||||
// Get unique entities (nodes)
|
// Get unique entities (nodes)
|
||||||
const uniqueEntities = new Set<string>();
|
const uniqueEntities = new Set<string>();
|
||||||
@ -56,6 +87,7 @@ export async function GET(request: NextRequest) {
|
|||||||
let f1Score = 0;
|
let f1Score = 0;
|
||||||
let avgQueryTime = vectorStats.avgQueryTime || 0;
|
let avgQueryTime = vectorStats.avgQueryTime || 0;
|
||||||
let avgRelevance = 0;
|
let avgRelevance = 0;
|
||||||
|
let queryTimesByMode: Record<string, number> = {};
|
||||||
|
|
||||||
// Get query logs from file-based logger instead of Neo4j
|
// Get query logs from file-based logger instead of Neo4j
|
||||||
try {
|
try {
|
||||||
@ -91,6 +123,23 @@ export async function GET(request: NextRequest) {
|
|||||||
avgRelevance = logsWithRelevance.reduce((sum, log) => sum + (log.metrics.avgRelevanceScore || 0), 0) / logsWithRelevance.length;
|
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<string, typeof queryLogs>);
|
||||||
|
|
||||||
|
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) {
|
} catch (error) {
|
||||||
console.warn('Error getting query logs from file:', error);
|
console.warn('Error getting query logs from file:', error);
|
||||||
// Keep values at 0 instead of using defaults
|
// Keep values at 0 instead of using defaults
|
||||||
@ -117,6 +166,7 @@ export async function GET(request: NextRequest) {
|
|||||||
recall,
|
recall,
|
||||||
f1Score,
|
f1Score,
|
||||||
topQueries,
|
topQueries,
|
||||||
|
queryTimesByMode: queryTimesByMode || {},
|
||||||
// Add metadata about query logs
|
// Add metadata about query logs
|
||||||
queryLogStats: {
|
queryLogStats: {
|
||||||
totalQueryLogs: queryLogs.length,
|
totalQueryLogs: queryLogs.length,
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { Neo4jService } from '@/lib/neo4j';
|
import { Neo4jService } from '@/lib/neo4j';
|
||||||
|
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { llmService, LLMMessage } from '@/lib/llm-service';
|
import { llmService, LLMMessage } from '@/lib/llm-service';
|
||||||
|
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { llmService } from '@/lib/llm-service';
|
import { llmService } from '@/lib/llm-service';
|
||||||
|
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { PineconeService } from '@/lib/pinecone';
|
import { QdrantService } from '@/lib/qdrant';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all data from the Pinecone vector database
|
* Clear all data from the Pinecone vector database
|
||||||
@ -7,7 +23,7 @@ import { PineconeService } from '@/lib/pinecone';
|
|||||||
*/
|
*/
|
||||||
export async function POST() {
|
export async function POST() {
|
||||||
// Get the Pinecone service instance
|
// Get the Pinecone service instance
|
||||||
const pineconeService = PineconeService.getInstance();
|
const pineconeService = QdrantService.getInstance();
|
||||||
|
|
||||||
// Clear all vectors from the database
|
// Clear all vectors from the database
|
||||||
const deleteSuccess = await pineconeService.deleteAllEntities();
|
const deleteSuccess = await pineconeService.deleteAllEntities();
|
||||||
|
|||||||
@ -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 { NextResponse } from 'next/server';
|
||||||
import { PineconeService } from '@/lib/pinecone';
|
import { QdrantService } from '@/lib/qdrant';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create Pinecone index API endpoint
|
* Create Pinecone index API endpoint
|
||||||
@ -8,7 +24,7 @@ import { PineconeService } from '@/lib/pinecone';
|
|||||||
export async function POST() {
|
export async function POST() {
|
||||||
try {
|
try {
|
||||||
// Get the Pinecone service instance
|
// Get the Pinecone service instance
|
||||||
const pineconeService = PineconeService.getInstance();
|
const pineconeService = QdrantService.getInstance();
|
||||||
|
|
||||||
// Force re-initialization to create the index
|
// Force re-initialization to create the index
|
||||||
(pineconeService as any).initialized = false;
|
(pineconeService as any).initialized = false;
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { PineconeService } from '@/lib/pinecone';
|
import { QdrantService } from '@/lib/qdrant';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Pinecone vector database stats
|
* Get Pinecone vector database stats
|
||||||
@ -7,7 +23,7 @@ import { PineconeService } from '@/lib/pinecone';
|
|||||||
export async function GET() {
|
export async function GET() {
|
||||||
try {
|
try {
|
||||||
// Initialize Pinecone service
|
// Initialize Pinecone service
|
||||||
const pineconeService = PineconeService.getInstance();
|
const pineconeService = QdrantService.getInstance();
|
||||||
|
|
||||||
// We can now directly call getStats() which handles initialization and error recovery
|
// We can now directly call getStats() which handles initialization and error recovery
|
||||||
const stats = await pineconeService.getStats();
|
const stats = await pineconeService.getStats();
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { RemoteBackendService } from '@/lib/remote-backend';
|
import { RemoteBackendService } from '@/lib/remote-backend';
|
||||||
import { EmbeddingsService } from '@/lib/embeddings';
|
import { EmbeddingsService } from '@/lib/embeddings';
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server'
|
||||||
|
|
||||||
const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080'
|
const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080'
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server'
|
||||||
|
|
||||||
const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080'
|
const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080'
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server'
|
||||||
|
|
||||||
const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080'
|
const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080'
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server'
|
||||||
|
|
||||||
const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080'
|
const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080'
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server'
|
||||||
|
|
||||||
const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080'
|
const PYGRAPHISTRY_SERVICE_URL = process.env.PYGRAPHISTRY_SERVICE_URL || 'http://localhost:8080'
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import neo4jService from '@/lib/neo4j';
|
import neo4jService from '@/lib/neo4j';
|
||||||
|
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import queryLoggerService from '@/lib/query-logger';
|
import queryLoggerService from '@/lib/query-logger';
|
||||||
|
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import neo4jService from '@/lib/neo4j';
|
import neo4jService from '@/lib/neo4j';
|
||||||
|
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import backendService from '@/lib/backend-service';
|
import backendService from '@/lib/backend-service';
|
||||||
import type { Triple } from '@/types/graph';
|
import type { Triple } from '@/types/graph';
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import RAGService from '@/lib/rag';
|
import RAGService from '@/lib/rag';
|
||||||
|
|
||||||
@ -20,17 +36,20 @@ export async function POST(req: NextRequest) {
|
|||||||
const ragService = RAGService;
|
const ragService = RAGService;
|
||||||
await ragService.initialize();
|
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
|
// 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
|
// 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 the results
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
answer,
|
answer: result.answer,
|
||||||
|
documentCount: result.documentCount,
|
||||||
usedFallback: isGeneralKnowledgeFallback,
|
usedFallback: isGeneralKnowledgeFallback,
|
||||||
success: true
|
success: true
|
||||||
});
|
});
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server'
|
||||||
|
|
||||||
// Proxy route specifically for WebRTC streaming frames
|
// Proxy route specifically for WebRTC streaming frames
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server'
|
||||||
|
|
||||||
// Proxy route for remote WebGPU clustering service
|
// Proxy route for remote WebGPU clustering service
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { processSentenceEmbeddings, SentenceEmbedding } from '@/lib/text-processor';
|
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
|
* API endpoint for splitting text into sentences and generating embeddings
|
||||||
@ -49,7 +65,7 @@ export async function POST(req: NextRequest) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Store in Pinecone
|
// Store in Pinecone
|
||||||
const pineconeService = PineconeService.getInstance();
|
const pineconeService = QdrantService.getInstance();
|
||||||
await pineconeService.storeEmbeddingsWithMetadata(
|
await pineconeService.storeEmbeddingsWithMetadata(
|
||||||
embeddingsMap,
|
embeddingsMap,
|
||||||
textContentMap,
|
textContentMap,
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { GraphDBType } from '@/lib/graph-db-service';
|
import { GraphDBType } from '@/lib/graph-db-service';
|
||||||
|
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server'
|
||||||
|
|
||||||
// Global flag to track if embeddings generation should be stopped
|
// Global flag to track if embeddings generation should be stopped
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server'
|
||||||
|
|
||||||
// Global flag to track if processing should be stopped
|
// Global flag to track if processing should be stopped
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import RAGService from '@/lib/rag';
|
import RAGService from '@/lib/rag';
|
||||||
|
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server'
|
||||||
|
|
||||||
// Simple test endpoint to verify proxy connectivity
|
// Simple test endpoint to verify proxy connectivity
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server'
|
||||||
|
|
||||||
const UNIFIED_GPU_SERVICE_URL = process.env.UNIFIED_GPU_SERVICE_URL || 'http://localhost:8080'
|
const UNIFIED_GPU_SERVICE_URL = process.env.UNIFIED_GPU_SERVICE_URL || 'http://localhost:8080'
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server'
|
||||||
|
|
||||||
const UNIFIED_GPU_SERVICE_URL = process.env.UNIFIED_GPU_SERVICE_URL || 'http://localhost:8080'
|
const UNIFIED_GPU_SERVICE_URL = process.env.UNIFIED_GPU_SERVICE_URL || 'http://localhost:8080'
|
||||||
|
|||||||
@ -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 { NextRequest, NextResponse } from 'next/server';
|
||||||
import { LLMService } from '@/lib/llm-service';
|
import { LLMService } from '@/lib/llm-service';
|
||||||
|
|
||||||
|
|||||||
@ -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";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
|
|||||||
@ -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 { DocumentsTable } from "@/components/documents-table";
|
||||||
import { DocumentProcessor } from "@/components/document-processor";
|
import { DocumentProcessor } from "@/components/document-processor";
|
||||||
|
|
||||||
|
|||||||
@ -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"
|
"use client"
|
||||||
|
|
||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
|
|||||||
@ -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"
|
"use client"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -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 React from "react"
|
||||||
import type { Metadata } from "next"
|
import type { Metadata } from "next"
|
||||||
import { Inter } from "next/font/google"
|
import { Inter } from "next/font/google"
|
||||||
@ -43,9 +59,6 @@ export default function RootLayout({
|
|||||||
<NvidiaIcon className="h-8 w-8" />
|
<NvidiaIcon className="h-8 w-8" />
|
||||||
<div>
|
<div>
|
||||||
<span className="text-xl font-bold gradient-text">txt2kg</span>
|
<span className="text-xl font-bold gradient-text">txt2kg</span>
|
||||||
<span className="ml-2 text-xs bg-primary/20 text-[#76b900] px-2 py-0.5 rounded-full">
|
|
||||||
Powered by NVIDIA AI
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
|
|||||||
@ -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"
|
"use client"
|
||||||
|
|
||||||
import { useState, useEffect } from "react"
|
import { useState, useEffect } from "react"
|
||||||
|
|||||||
@ -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";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
@ -17,6 +33,7 @@ interface MetricsData {
|
|||||||
recall: number;
|
recall: number;
|
||||||
f1Score: number;
|
f1Score: number;
|
||||||
topQueries: { query: string; count: number }[];
|
topQueries: { query: string; count: number }[];
|
||||||
|
queryTimesByMode?: Record<string, number>;
|
||||||
queryLogStats?: {
|
queryLogStats?: {
|
||||||
totalQueryLogs: number;
|
totalQueryLogs: number;
|
||||||
totalExecutions: number;
|
totalExecutions: number;
|
||||||
|
|||||||
@ -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";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
@ -12,6 +28,7 @@ import { ArrowLeft, BarChart2, Search as SearchIcon } from "lucide-react";
|
|||||||
export default function RagPage() {
|
export default function RagPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [results, setResults] = useState<Triple[] | null>(null);
|
const [results, setResults] = useState<Triple[] | null>(null);
|
||||||
|
const [llmAnswer, setLlmAnswer] = useState<string | null>(null);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
||||||
const [vectorEnabled, setVectorEnabled] = useState(false);
|
const [vectorEnabled, setVectorEnabled] = useState(false);
|
||||||
@ -20,6 +37,7 @@ export default function RagPage() {
|
|||||||
avgRelevance: number;
|
avgRelevance: number;
|
||||||
precision: number;
|
precision: number;
|
||||||
recall: number;
|
recall: number;
|
||||||
|
queryTimesByMode?: Record<string, number>;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
const [currentParams, setCurrentParams] = useState<RagParams>({
|
const [currentParams, setCurrentParams] = useState<RagParams>({
|
||||||
kNeighbors: 4096,
|
kNeighbors: 4096,
|
||||||
@ -64,7 +82,8 @@ export default function RagPage() {
|
|||||||
avgQueryTime: data.avgQueryTime,
|
avgQueryTime: data.avgQueryTime,
|
||||||
avgRelevance: data.avgRelevance,
|
avgRelevance: data.avgRelevance,
|
||||||
precision: data.precision,
|
precision: data.precision,
|
||||||
recall: data.recall
|
recall: data.recall,
|
||||||
|
queryTimesByMode: data.queryTimesByMode
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -84,12 +103,20 @@ export default function RagPage() {
|
|||||||
let resultCount = 0;
|
let resultCount = 0;
|
||||||
let relevanceScore = 0;
|
let relevanceScore = 0;
|
||||||
|
|
||||||
|
// Debug logging
|
||||||
|
console.log('🔍 Query params:', {
|
||||||
|
usePureRag: params.usePureRag,
|
||||||
|
useVectorSearch: params.useVectorSearch,
|
||||||
|
vectorEnabled,
|
||||||
|
queryMode: params.queryMode
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// If using pure RAG (Pinecone + LangChain) without graph search
|
// If using pure RAG (Pinecone + LangChain) without graph search
|
||||||
if (params.usePureRag) {
|
if (params.usePureRag) {
|
||||||
queryMode = 'pure-rag';
|
queryMode = 'pure-rag';
|
||||||
try {
|
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', {
|
const ragResponse = await fetch('/api/rag-query', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
@ -101,17 +128,22 @@ export default function RagPage() {
|
|||||||
|
|
||||||
if (ragResponse.ok) {
|
if (ragResponse.ok) {
|
||||||
const data = await ragResponse.json();
|
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
|
// Handle the answer - we might need to display differently than triples
|
||||||
if (data.answer) {
|
if (data.answer) {
|
||||||
// Special UI handling for text answer rather than triples
|
console.log('✅ Setting answer in results:', data.answer.substring(0, 100) + '...');
|
||||||
setResults([{
|
|
||||||
subject: 'Answer',
|
|
||||||
predicate: '',
|
|
||||||
object: data.answer,
|
|
||||||
usedFallback: data.usedFallback
|
|
||||||
}]);
|
|
||||||
|
|
||||||
resultCount = 1;
|
// 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;
|
relevanceScore = data.relevanceScore || 0;
|
||||||
|
|
||||||
// Log the query with performance metrics
|
// Log the query with performance metrics
|
||||||
@ -121,7 +153,7 @@ export default function RagPage() {
|
|||||||
resultCount
|
resultCount
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Pure RAG query completed successfully');
|
console.log(`✅ Pure RAG query completed. Retrieved ${resultCount} document chunks`);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -136,8 +168,8 @@ export default function RagPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have vector embeddings, use enhanced query with metadata
|
// If we have vector embeddings AND explicitly selected vector search, use enhanced query with metadata
|
||||||
if (vectorEnabled && params.useVectorSearch) {
|
if (vectorEnabled && params.useVectorSearch && !params.usePureRag) {
|
||||||
queryMode = 'vector-search';
|
queryMode = 'vector-search';
|
||||||
try {
|
try {
|
||||||
console.log('Using enhanced RAG with LangChain for query:', query);
|
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';
|
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',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
query,
|
query,
|
||||||
kNeighbors: params.kNeighbors,
|
topK: params.topK || 5,
|
||||||
fanout: params.fanout,
|
useTraditional: true,
|
||||||
numHops: params.numHops,
|
llmModel,
|
||||||
topK: params.topK,
|
llmProvider
|
||||||
queryMode: queryMode, // Explicitly pass the query mode
|
|
||||||
useTraditional: true // Force use of the direct pattern matching approach
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json();
|
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();
|
const data = await response.json();
|
||||||
|
|
||||||
// Update the results
|
// Log sample of retrieved triples for debugging
|
||||||
setResults(data.relevantTriples || []);
|
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 with the triples (for display)
|
||||||
|
setResults(data.triples || []);
|
||||||
resultCount = data.count || 0;
|
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
|
// Log the query with performance metrics
|
||||||
logQuery(query, queryMode, {
|
logQuery(query, queryMode, {
|
||||||
@ -279,6 +347,7 @@ export default function RagPage() {
|
|||||||
|
|
||||||
const clearResults = () => {
|
const clearResults = () => {
|
||||||
setResults(null);
|
setResults(null);
|
||||||
|
setLlmAnswer(null);
|
||||||
setErrorMessage(null);
|
setErrorMessage(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -318,22 +387,34 @@ export default function RagPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-3 text-sm">
|
<div className="space-y-3 text-sm">
|
||||||
|
{/* Query times by mode */}
|
||||||
|
{metrics.queryTimesByMode && Object.keys(metrics.queryTimesByMode).length > 0 ? (
|
||||||
|
<>
|
||||||
|
{metrics.queryTimesByMode['pure-rag'] !== undefined && (
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<span className="text-muted-foreground">Pure RAG:</span>
|
||||||
|
<span className="font-medium">{(metrics.queryTimesByMode['pure-rag'] / 1000).toFixed(2)}s</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{metrics.queryTimesByMode['traditional'] !== undefined && (
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<span className="text-muted-foreground">Graph Search:</span>
|
||||||
|
<span className="font-medium">{(metrics.queryTimesByMode['traditional'] / 1000).toFixed(2)}s</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{metrics.queryTimesByMode['vector-search'] !== undefined && (
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<span className="text-muted-foreground">GraphRAG:</span>
|
||||||
|
<span className="font-medium">{(metrics.queryTimesByMode['vector-search'] / 1000).toFixed(2)}s</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-muted-foreground">Avg. Query Time:</span>
|
<span className="text-muted-foreground">Avg. Query Time:</span>
|
||||||
<span className="font-medium">{metrics.avgQueryTime > 0 ? `${metrics.avgQueryTime.toFixed(2)}ms` : "No data"}</span>
|
<span className="font-medium">{metrics.avgQueryTime > 0 ? `${metrics.avgQueryTime.toFixed(2)}ms` : "No data"}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
)}
|
||||||
<span className="text-muted-foreground">Relevance Score:</span>
|
|
||||||
<span className="font-medium">{metrics.avgRelevance > 0 ? `${(metrics.avgRelevance * 100).toFixed(1)}%` : "No data"}</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between">
|
|
||||||
<span className="text-muted-foreground">Precision:</span>
|
|
||||||
<span className="font-medium">{metrics.precision > 0 ? `${(metrics.precision * 100).toFixed(1)}%` : "No data"}</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between">
|
|
||||||
<span className="text-muted-foreground">Recall:</span>
|
|
||||||
<span className="font-medium">{metrics.recall > 0 ? `${(metrics.recall * 100).toFixed(1)}%` : "No data"}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -349,14 +430,81 @@ export default function RagPage() {
|
|||||||
vectorEnabled={vectorEnabled}
|
vectorEnabled={vectorEnabled}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* LLM Answer Section */}
|
||||||
|
{llmAnswer && (
|
||||||
|
<div className="mt-8 nvidia-build-card">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<div className="w-6 h-6 rounded-md bg-nvidia-green/15 flex items-center justify-center">
|
||||||
|
<SearchIcon className="h-3 w-3 text-nvidia-green" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-lg font-semibold text-foreground">Answer</h3>
|
||||||
|
{currentParams.queryMode && (
|
||||||
|
<span className="text-xs px-2.5 py-1 rounded-full font-medium bg-nvidia-green/10 text-nvidia-green border border-nvidia-green/20">
|
||||||
|
{currentParams.queryMode === 'pure-rag' ? 'Pure RAG' :
|
||||||
|
currentParams.queryMode === 'vector-search' ? 'GraphRAG' :
|
||||||
|
'Graph Search'}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="prose prose-sm dark:prose-invert max-w-none">
|
||||||
|
{(() => {
|
||||||
|
// Parse <think> tags
|
||||||
|
const thinkMatch = llmAnswer.match(/<think>([\s\S]*?)<\/think>/);
|
||||||
|
const thinkContent = thinkMatch ? thinkMatch[1].trim() : null;
|
||||||
|
const mainAnswer = thinkContent
|
||||||
|
? llmAnswer.replace(/<think>[\s\S]*?<\/think>/, '').trim()
|
||||||
|
: llmAnswer;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{thinkContent && (
|
||||||
|
<details className="mb-4 bg-muted/10 border border-border/20 rounded-xl overflow-hidden group">
|
||||||
|
<summary className="cursor-pointer p-4 hover:bg-muted/20 transition-colors flex items-center gap-2">
|
||||||
|
<svg className="w-4 h-4 transform transition-transform group-open:rotate-90" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||||
|
</svg>
|
||||||
|
<span className="text-sm font-medium text-muted-foreground">Reasoning Process</span>
|
||||||
|
</summary>
|
||||||
|
<div className="p-4 pt-0 text-sm text-muted-foreground leading-relaxed whitespace-pre-wrap border-t border-border/10">
|
||||||
|
{thinkContent}
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
)}
|
||||||
|
<div className="bg-muted/20 border border-border/20 p-6 rounded-xl">
|
||||||
|
<div
|
||||||
|
className="text-foreground leading-relaxed whitespace-pre-wrap"
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: mainAnswer
|
||||||
|
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
||||||
|
.replace(/\*(.*?)\*/g, '<em>$1</em>')
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Results Section */}
|
{/* Results Section */}
|
||||||
{results && results.length > 0 && (
|
{results && results.length > 0 && !currentParams.usePureRag && (
|
||||||
<div className="mt-8 nvidia-build-card">
|
<div className="mt-8 nvidia-build-card">
|
||||||
<div className="flex items-center gap-3 mb-6">
|
<div className="flex items-center gap-3 mb-6">
|
||||||
<div className="w-6 h-6 rounded-md bg-nvidia-green/15 flex items-center justify-center">
|
<div className="w-6 h-6 rounded-md bg-nvidia-green/15 flex items-center justify-center">
|
||||||
<SearchIcon className="h-3 w-3 text-nvidia-green" />
|
<SearchIcon className="h-3 w-3 text-nvidia-green" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-lg font-semibold text-foreground">Results ({results.length})</h3>
|
<h3 className="text-lg font-semibold text-foreground">
|
||||||
|
{llmAnswer ? `Retrieved Knowledge (${results.length})` : `Results (${results.length})`}
|
||||||
|
</h3>
|
||||||
|
{results.some((r: any) => r.pathLength && r.pathLength > 1) && (
|
||||||
|
<span className="text-xs px-2.5 py-1 rounded-full font-medium bg-amber-500/10 text-amber-600 dark:text-amber-400 border border-amber-500/20 flex items-center gap-1.5">
|
||||||
|
<svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||||
|
</svg>
|
||||||
|
Multi-hop enabled
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{results.map((triple, index) => (
|
{results.map((triple, index) => (
|
||||||
@ -389,8 +537,33 @@ export default function RagPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{triple.confidence && !currentParams.usePureRag && (
|
{triple.confidence && !currentParams.usePureRag && (
|
||||||
<div className="mt-2 text-xs text-muted-foreground">
|
<div className="mt-3 flex items-center gap-4 text-xs">
|
||||||
Confidence: {(triple.confidence * 100).toFixed(1)}%
|
<div className="flex items-center gap-1.5">
|
||||||
|
<div className="w-2 h-2 rounded-full bg-nvidia-green/60"></div>
|
||||||
|
<span className="text-muted-foreground">
|
||||||
|
Confidence: <span className="font-medium text-foreground">{(triple.confidence * 100).toFixed(1)}%</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{triple.depth !== undefined && (
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
<svg className="w-3 h-3 text-nvidia-green/60" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 7l5 5m0 0l-5 5m5-5H6" />
|
||||||
|
</svg>
|
||||||
|
<span className="text-muted-foreground">
|
||||||
|
Hop: <span className="font-medium text-foreground">{triple.depth + 1}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{triple.pathLength !== undefined && triple.pathLength > 1 && (
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
<svg className="w-3 h-3 text-amber-500/60" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" />
|
||||||
|
</svg>
|
||||||
|
<span className="text-amber-600/80 dark:text-amber-400/80">
|
||||||
|
Multi-hop path (length: <span className="font-medium">{triple.pathLength}</span>)
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -399,7 +572,7 @@ export default function RagPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{results && results.length === 0 && !isLoading && (
|
{results && results.length === 0 && !isLoading && !currentParams.usePureRag && (
|
||||||
<div className="mt-8 nvidia-build-card border-dashed">
|
<div className="mt-8 nvidia-build-card border-dashed">
|
||||||
<div className="text-center py-8">
|
<div className="text-center py-8">
|
||||||
<div className="w-12 h-12 rounded-xl bg-muted/30 flex items-center justify-center mx-auto mb-4">
|
<div className="w-12 h-12 rounded-xl bg-muted/30 flex items-center justify-center mx-auto mb-4">
|
||||||
|
|||||||
@ -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"
|
"use client"
|
||||||
|
|
||||||
import React, { useState, useEffect } from "react"
|
import React, { useState, useEffect } from "react"
|
||||||
|
|||||||
@ -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"
|
"use client"
|
||||||
|
|
||||||
import React, { useState, useEffect, useCallback, useMemo } from "react"
|
import React, { useState, useEffect, useCallback, useMemo } from "react"
|
||||||
|
|||||||
@ -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"
|
"use client"
|
||||||
|
|
||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
|||||||
@ -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 React, { useState } from "react";
|
||||||
import { ChevronDown, ChevronRight } from "lucide-react";
|
import { ChevronDown, ChevronRight } from "lucide-react";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|||||||
@ -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"
|
"use client"
|
||||||
|
|
||||||
import type React from "react"
|
import type React from "react"
|
||||||
|
|||||||
@ -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"
|
"use client"
|
||||||
|
|
||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
|
|||||||
@ -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"
|
"use client"
|
||||||
|
|
||||||
import { useState, useEffect } from "react"
|
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 { Badge } from '@/components/ui/badge'
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
@ -163,8 +179,13 @@ export function DatabaseConnection({ className }: DatabaseConnectionProps) {
|
|||||||
nodes: typeof data.totalVectorCount === 'number' ? data.totalVectorCount : 0,
|
nodes: typeof data.totalVectorCount === 'number' ? data.totalVectorCount : 0,
|
||||||
relationships: 0, // Vector DB doesn't store relationships
|
relationships: 0, // Vector DB doesn't store relationships
|
||||||
source: data.source || 'unknown',
|
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 we have a healthy HTTP connection, we're connected
|
||||||
if (data.httpHealthy) {
|
if (data.httpHealthy) {
|
||||||
@ -364,39 +385,65 @@ export function DatabaseConnection({ className }: DatabaseConnectionProps) {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={checkGraphConnection}
|
onClick={checkGraphConnection}
|
||||||
disabled={graphConnectionStatus === "checking"}
|
disabled={graphConnectionStatus === "checking"}
|
||||||
className="flex-1 text-xs h-7"
|
className="flex-1 text-xs h-7 px-2"
|
||||||
>
|
>
|
||||||
{graphConnectionStatus === "checking" ? "Checking..." : "Refresh"}
|
<RefreshCw className={`h-3 w-3 ${graphConnectionStatus === "checking" ? "animate-spin" : ""}`} />
|
||||||
</Button>
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>{graphConnectionStatus === "checking" ? "Checking..." : "Refresh connection"}</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
{graphConnectionStatus === "connected" ? (
|
{graphConnectionStatus === "connected" ? (
|
||||||
<>
|
<>
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={disconnectGraph}
|
onClick={disconnectGraph}
|
||||||
className="flex-1 text-xs h-7"
|
className="flex-1 text-xs h-7 px-2"
|
||||||
>
|
>
|
||||||
Disconnect
|
<LogOut className="h-3 w-3" />
|
||||||
</Button>
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>Disconnect</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
<Dialog open={showClearDialog} onOpenChange={setShowClearDialog}>
|
<Dialog open={showClearDialog} onOpenChange={setShowClearDialog}>
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="flex-1 text-xs h-7"
|
className="flex-1 text-xs h-7 px-2"
|
||||||
disabled={isClearingDB}
|
disabled={isClearingDB}
|
||||||
>
|
>
|
||||||
<Trash2 className="h-3 w-3 mr-1" />
|
<Trash2 className="h-3 w-3" />
|
||||||
Clear
|
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>Clear database</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle className="text-destructive">Clear Database</DialogTitle>
|
<DialogTitle className="text-destructive">Clear Database</DialogTitle>
|
||||||
@ -487,21 +534,33 @@ export function DatabaseConnection({ className }: DatabaseConnectionProps) {
|
|||||||
<>
|
<>
|
||||||
<div className="flex items-center gap-2 text-xs md:text-sm">
|
<div className="flex items-center gap-2 text-xs md:text-sm">
|
||||||
<span className="text-foreground font-medium">
|
<span className="text-foreground font-medium">
|
||||||
Pinecone
|
Qdrant
|
||||||
</span>
|
</span>
|
||||||
<span className="text-foreground font-mono text-[11px] bg-secondary/50 px-2 py-0.5 rounded truncate max-w-full">
|
<span className="text-foreground font-mono text-[11px] bg-secondary/50 px-2 py-0.5 rounded truncate max-w-full">
|
||||||
direct-http
|
{(vectorStats as any).url || 'http://qdrant:6333'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{vectorStats.nodes > 0 && (
|
<div className="text-xs md:text-sm text-muted-foreground space-y-1">
|
||||||
<div className="text-xs md:text-sm text-muted-foreground">
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Database className="h-3.5 w-3.5" />
|
<Database className="h-3.5 w-3.5" />
|
||||||
<span>{vectorStats.nodes.toLocaleString()} vectors</span>
|
<span>{vectorStats.nodes.toLocaleString()} vectors indexed</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{(vectorStats as any).status && (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Zap className="h-3.5 w-3.5" />
|
||||||
|
<span>Status: <span className="capitalize">{(vectorStats as any).status}</span></span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{(vectorStats as any).vectorSize && (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<InfoIcon className="h-3.5 w-3.5" />
|
||||||
|
<span>{(vectorStats as any).vectorSize}d ({(vectorStats as any).distance})</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -520,51 +579,77 @@ export function DatabaseConnection({ className }: DatabaseConnectionProps) {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={checkVectorConnection}
|
onClick={checkVectorConnection}
|
||||||
disabled={vectorConnectionStatus === "checking"}
|
disabled={vectorConnectionStatus === "checking"}
|
||||||
className="flex-1 text-xs h-7"
|
className="flex-1 text-xs h-7 px-2"
|
||||||
>
|
>
|
||||||
{vectorConnectionStatus === "checking" ? "Checking..." : "Refresh"}
|
<RefreshCw className={`h-3 w-3 ${vectorConnectionStatus === "checking" ? "animate-spin" : ""}`} />
|
||||||
</Button>
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>{vectorConnectionStatus === "checking" ? "Checking..." : "Refresh connection"}</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
{vectorConnectionStatus === "connected" ? (
|
{vectorConnectionStatus === "connected" ? (
|
||||||
<>
|
<>
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={disconnectVector}
|
onClick={disconnectVector}
|
||||||
className="flex-1 text-xs h-7"
|
className="flex-1 text-xs h-7 px-2"
|
||||||
>
|
>
|
||||||
Disconnect
|
<LogOut className="h-3 w-3" />
|
||||||
</Button>
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>Disconnect</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
<Dialog open={showClearVectorDialog} onOpenChange={setShowClearVectorDialog}>
|
<Dialog open={showClearVectorDialog} onOpenChange={setShowClearVectorDialog}>
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="flex-1 text-xs h-7"
|
className="flex-1 text-xs h-7 px-2"
|
||||||
disabled={isClearingVectorDB}
|
disabled={isClearingVectorDB}
|
||||||
>
|
>
|
||||||
<Trash2 className="h-3 w-3 mr-1" />
|
<Trash2 className="h-3 w-3" />
|
||||||
Clear
|
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>Clear database</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle className="text-destructive">Clear Pinecone Database</DialogTitle>
|
<DialogTitle className="text-destructive">Clear Qdrant Database</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
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.
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<Alert variant="destructive" className="mt-2">
|
<Alert variant="destructive" className="mt-2">
|
||||||
<AlertCircle className="h-4 w-4" />
|
<AlertCircle className="h-4 w-4" />
|
||||||
<AlertTitle>Warning</AlertTitle>
|
<AlertTitle>Warning</AlertTitle>
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
This will permanently delete all vectors from the Pinecone database.
|
This will permanently delete all vectors from the Qdrant database.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
<DialogFooter className="gap-2 mt-4">
|
<DialogFooter className="gap-2 mt-4">
|
||||||
|
|||||||
@ -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"
|
"use client"
|
||||||
|
|
||||||
import { FC, useState, useEffect } from 'react'
|
import { FC, useState, useEffect } from 'react'
|
||||||
|
|||||||
@ -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";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|||||||
@ -1,20 +1,30 @@
|
|||||||
|
//
|
||||||
|
// 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"
|
"use client"
|
||||||
|
|
||||||
import { useState, useEffect } from "react"
|
import { useState, useEffect } from "react"
|
||||||
import { useDocuments } from "@/contexts/document-context"
|
import { useDocuments } from "@/contexts/document-context"
|
||||||
import { CheckCircle, Loader2, FileText, AlertCircle, X } from "lucide-react"
|
import { CheckCircle, Loader2, FileText, AlertCircle, X } from "lucide-react"
|
||||||
import { Switch } from "@/components/ui/switch"
|
|
||||||
import { Label } from "@/components/ui/label"
|
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
|
|
||||||
import { useRouter } from "next/navigation"
|
import { useRouter } from "next/navigation"
|
||||||
import { useShiftSelect } from "@/hooks/use-shift-select"
|
import { useShiftSelect } from "@/hooks/use-shift-select"
|
||||||
|
|
||||||
export function DocumentSelection() {
|
export function DocumentSelection() {
|
||||||
const { documents, processDocuments, isProcessing } = useDocuments()
|
const { documents, processDocuments, isProcessing } = useDocuments()
|
||||||
const [useLangChain, setUseLangChain] = useState(false)
|
|
||||||
const [useSentenceChunking, setUseSentenceChunking] = useState(true)
|
|
||||||
const [useEntityExtraction, setUseEntityExtraction] = useState(true)
|
|
||||||
const [processingStatus, setProcessingStatus] = useState("")
|
const [processingStatus, setProcessingStatus] = useState("")
|
||||||
const [error, setError] = useState<string | null>(null)
|
const [error, setError] = useState<string | null>(null)
|
||||||
const [forceUpdate, setForceUpdate] = useState(0)
|
const [forceUpdate, setForceUpdate] = useState(0)
|
||||||
@ -108,7 +118,7 @@ export function DocumentSelection() {
|
|||||||
|
|
||||||
// Call processDocuments with the selected document IDs
|
// Call processDocuments with the selected document IDs
|
||||||
await processDocuments(selectedDocs, {
|
await processDocuments(selectedDocs, {
|
||||||
useLangChain,
|
useLangChain: false,
|
||||||
useGraphTransformer: false,
|
useGraphTransformer: false,
|
||||||
promptConfigs: undefined
|
promptConfigs: undefined
|
||||||
})
|
})
|
||||||
@ -157,65 +167,6 @@ export function DocumentSelection() {
|
|||||||
<h3 className="text-md font-medium">Document Selection</h3>
|
<h3 className="text-md font-medium">Document Selection</h3>
|
||||||
<p className="text-sm text-muted-foreground mb-2">Select which documents to process for triple extraction</p>
|
<p className="text-sm text-muted-foreground mb-2">Select which documents to process for triple extraction</p>
|
||||||
|
|
||||||
<div className="space-y-3 pt-2 mb-4">
|
|
||||||
<h4 className="text-sm font-medium">Processing Options</h4>
|
|
||||||
|
|
||||||
<div className="space-y-2">
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<Switch
|
|
||||||
id="use-langchain"
|
|
||||||
checked={useLangChain}
|
|
||||||
onCheckedChange={(value) => {
|
|
||||||
setUseLangChain(value);
|
|
||||||
// Dispatch custom event to update other components
|
|
||||||
window.dispatchEvent(new CustomEvent('langChainToggled', {
|
|
||||||
detail: { useLangChain: value }
|
|
||||||
}));
|
|
||||||
}}
|
|
||||||
disabled={isProcessing}
|
|
||||||
/>
|
|
||||||
<Label htmlFor="use-langchain" className="text-sm cursor-pointer">Use LangChain</Label>
|
|
||||||
</div>
|
|
||||||
{/* <p className="text-xs text-muted-foreground pl-7">
|
|
||||||
Leverages LangChain for knowledge extraction from documents
|
|
||||||
</p> */}
|
|
||||||
|
|
||||||
{useLangChain && (
|
|
||||||
<>
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<Switch
|
|
||||||
id="use-sentence-chunking"
|
|
||||||
checked={useSentenceChunking}
|
|
||||||
onCheckedChange={setUseSentenceChunking}
|
|
||||||
disabled={isProcessing}
|
|
||||||
/>
|
|
||||||
<Label htmlFor="use-sentence-chunking" className="text-sm cursor-pointer">
|
|
||||||
Use Sentence Chunking
|
|
||||||
</Label>
|
|
||||||
</div>
|
|
||||||
<p className="text-xs text-muted-foreground pl-7">
|
|
||||||
Split documents into sentences for more accurate triple extraction
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<Switch
|
|
||||||
id="use-entity-extraction"
|
|
||||||
checked={useEntityExtraction}
|
|
||||||
onCheckedChange={setUseEntityExtraction}
|
|
||||||
disabled={isProcessing}
|
|
||||||
/>
|
|
||||||
<Label htmlFor="use-entity-extraction" className="text-sm cursor-pointer">
|
|
||||||
Entity Extraction
|
|
||||||
</Label>
|
|
||||||
</div>
|
|
||||||
<p className="text-xs text-muted-foreground pl-7">
|
|
||||||
Automatically detect and extract entities from documents
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{error && (
|
{error && (
|
||||||
<div className="bg-destructive/10 border border-destructive rounded-md p-4 flex items-start gap-3">
|
<div className="bg-destructive/10 border border-destructive rounded-md p-4 flex items-start gap-3">
|
||||||
<AlertCircle className="h-5 w-5 text-destructive mt-0.5 flex-shrink-0" />
|
<AlertCircle className="h-5 w-5 text-destructive mt-0.5 flex-shrink-0" />
|
||||||
|
|||||||
@ -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"
|
"use client"
|
||||||
|
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user