diff --git a/docker-compose.yml b/docker-compose.yml
index c9c7927a..e6c6e7bf 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -25,32 +25,25 @@ services:
- NEO4J_USERNAME=${NEO4J_USERNAME:-neo4j}
- NEO4J_PASSWORD=${NEO4J_PASSWORD:-0123456789}
- MILVUS_URI=${MILVUS_URI:-http://milvus:19530}
+ - MILVUS_TOKEN=${MILVUS_TOKEN:-}
- MINERU_OCR_URI=${MINERU_OCR_URI:-http://mineru:30000}
- PADDLEX_URI=${PADDLEX_URI:-http://paddlex-ocr:8080}
- MINIO_URI=${MINIO_URI:-http://milvus-minio:9000}
- # PostgreSQL 配置
- - POSTGRES_URI=postgresql://${POSTGRES_USER:-lightrag}:${POSTGRES_PASSWORD:-lightrag}@postgres-lightrag:5432/${POSTGRES_DATABASE:-lightrag}
- - POSTGRES_HOST=${POSTGRES_HOST:-postgres-lightrag}
- - POSTGRES_PORT=${POSTGRES_PORT:-5432}
- - POSTGRES_DATABASE=${POSTGRES_DATABASE:-lightrag}
- - POSTGRES_USER=${POSTGRES_USER:-lightrag}
- - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-lightrag}
- # 连接池配置
- - POSTGRES_MAX_CONNECTIONS=50
- - POSTGRES_MIN_CONNECTIONS=5
- MODEL_DIR=/models
- RUNNING_IN_DOCKER=true
+ - NO_PROXY=localhost,127.0.0.1,milvus,graph,milvus-minio,milvus-etcd-dev,etcd,minio
+ - no_proxy=localhost,127.0.0.1,milvus,graph,milvus-minio,milvus-etcd-dev,etcd,minio
command: uv run uvicorn server.main:app --host 0.0.0.0 --port 5050 --reload
restart: unless-stopped
healthcheck:
- test: ["CMD-SHELL", "curl -f http://localhost:5050/health || exit 1"]
+ test: ["CMD-SHELL", "curl -f http://localhost:5050/api/health || exit 1"]
interval: 30s
timeout: 15s
retries: 8
start_period: 180s
depends_on:
- postgres:
- condition: service_healthy
+ # postgres:
+ # condition: service_healthy
milvus:
condition: service_healthy
minio:
@@ -80,31 +73,31 @@ services:
# PostgreSQL 服务 - 基于官方推荐的 shangor/postgres-for-rag 镜像
# 提供 KV store, VectorDB (pgvector) 和 GraphDB (Apache AGE) 功能
- postgres:
- image: shangor/postgres-for-rag:v1.0
- container_name: postgres-lightrag
- environment:
- - POSTGRES_DATABASE=${POSTGRES_DATABASE:-lightrag}
- - POSTGRES_USER=${POSTGRES_USER:-lightrag}
- - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-lightrag}
- - POSTGRES_HOST_AUTH_METHOD=md5
- # 启用必要的扩展
- - POSTGRES_INITDB_ARGS=--auth-host=md5
- volumes:
- - ./docker/volumes/postgres/data:/var/lib/postgresql/data
- - ./docker/init-postgres.sh:/init-postgres.sh
- ports:
- - "5432:5432"
- healthcheck:
- test: ["CMD-SHELL", "PGPASSWORD=${POSTGRES_PASSWORD:-lightrag} psql -h localhost -U ${POSTGRES_USER:-lightrag} -d ${POSTGRES_DATABASE:-lightrag} -c \"SELECT ag_catalog.create_graph('test_ready');\" || PGPASSWORD=${POSTGRES_PASSWORD:-lightrag} psql -h localhost -U ${POSTGRES_USER:-lightrag} -d ${POSTGRES_DATABASE:-lightrag} -c 'SELECT 1'"]
- interval: 30s
- timeout: 15s
- retries: 15
- start_period: 120s
- networks:
- - app-network
- restart: unless-stopped
- command: ["bash", "/init-postgres.sh"]
+ # postgres:
+ # image: shangor/postgres-for-rag:v1.0
+ # container_name: postgres-lightrag
+ # environment:
+ # - POSTGRES_DATABASE=${POSTGRES_DATABASE:-lightrag}
+ # - POSTGRES_USER=${POSTGRES_USER:-lightrag}
+ # - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-lightrag}
+ # - POSTGRES_HOST_AUTH_METHOD=md5
+ # # 启用必要的扩展
+ # - POSTGRES_INITDB_ARGS=--auth-host=md5
+ # volumes:
+ # - ./docker/volumes/postgres/data:/var/lib/postgresql/data
+ # - ./docker/init-postgres.sh:/init-postgres.sh
+ # ports:
+ # - "5432:5432"
+ # healthcheck:
+ # test: ["CMD-SHELL", "PGPASSWORD=${POSTGRES_PASSWORD:-lightrag} psql -h localhost -U ${POSTGRES_USER:-lightrag} -d ${POSTGRES_DATABASE:-lightrag} -c \"SELECT ag_catalog.create_graph('test_ready');\" || PGPASSWORD=${POSTGRES_PASSWORD:-lightrag} psql -h localhost -U ${POSTGRES_USER:-lightrag} -d ${POSTGRES_DATABASE:-lightrag} -c 'SELECT 1'"]
+ # interval: 30s
+ # timeout: 15s
+ # retries: 15
+ # start_period: 120s
+ # networks:
+ # - app-network
+ # restart: unless-stopped
+ # command: ["bash", "/init-postgres.sh"]
graph:
image: neo4j:5.26
diff --git a/docker/api.Dockerfile b/docker/api.Dockerfile
index e4b1fc4c..ea5779c7 100644
--- a/docker/api.Dockerfile
+++ b/docker/api.Dockerfile
@@ -29,6 +29,11 @@ COPY ../pyproject.toml /app/pyproject.toml
COPY ../.python-version /app/.python-version
# 安装依赖项
+ENV HTTP_PROXY=http://172.19.13.5:7890 \
+ HTTPS_PROXY=http://172.19.13.5:7890 \
+ http_proxy=http://172.19.13.5:7890 \
+ https_proxy=http://172.19.13.5:7890
+
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --no-install-project
@@ -38,4 +43,7 @@ COPY ../server /app/server
# 同步项目
RUN --mount=type=cache,target=/root/.cache/uv \
- uv sync
\ No newline at end of file
+ uv sync
+
+# 取消代理
+RUN unset HTTP_PROXY HTTPS_PROXY http_proxy https_proxy
\ No newline at end of file
diff --git a/docker/init-postgres.sh b/docker/init-postgres.sh
deleted file mode 100644
index f4227a03..00000000
--- a/docker/init-postgres.sh
+++ /dev/null
@@ -1,358 +0,0 @@
-#!/bin/bash
-
-# PostgreSQL 初始化脚本
-# 适用于 shangor/postgres-for-rag 镜像
-
-set -e
-
-echo "Starting PostgreSQL initialization..."
-
-# 启动 PostgreSQL 服务
-service postgresql start
-sleep 10
-
-echo "PostgreSQL service started, waiting for it to be ready..."
-
-# 等待 PostgreSQL 完全启动
-while ! su - postgres -c "pg_isready" > /dev/null 2>&1; do
- echo "Waiting for PostgreSQL to be ready..."
- sleep 5
-done
-
-# 额外等待以确保数据库完全启动
-echo "PostgreSQL is ready, waiting additional time for full initialization..."
-sleep 10
-
-echo "PostgreSQL is ready, creating user and database..."
-
-# 创建用户(如果不存在)
-if ! su - postgres -c "psql -tAc \"SELECT 1 FROM pg_roles WHERE rolname='${POSTGRES_USER:-lightrag}'\"" | grep -q 1; then
- echo "Creating user ${POSTGRES_USER:-lightrag}..."
- su - postgres -c "createuser -s ${POSTGRES_USER:-lightrag}"
-else
- echo "User ${POSTGRES_USER:-lightrag} already exists"
-fi
-
-# 创建数据库(如果不存在)
-if ! su - postgres -c "psql -tAc \"SELECT 1 FROM pg_database WHERE datname='${POSTGRES_DATABASE:-lightrag}'\"" | grep -q 1; then
- echo "Creating database ${POSTGRES_DATABASE:-lightrag}..."
- su - postgres -c "createdb -O ${POSTGRES_USER:-lightrag} ${POSTGRES_DATABASE:-lightrag}"
-else
- echo "Database ${POSTGRES_DATABASE:-lightrag} already exists"
-fi
-
-# 设置密码
-echo "Setting password for user ${POSTGRES_USER:-lightrag}..."
-su - postgres -c "psql -c \"ALTER USER ${POSTGRES_USER:-lightrag} PASSWORD '${POSTGRES_PASSWORD:-lightrag}';\""
-
-# 配置 pg_hba.conf 以允许密码认证
-echo "Configuring PostgreSQL authentication..."
-PG_HBA_CONF="/etc/postgresql/16/main/pg_hba.conf"
-# 备份原始配置
-cp $PG_HBA_CONF $PG_HBA_CONF.backup
-
-# 创建新的 pg_hba.conf 文件,确保 lightrag 用户的规则在前面
-cat > $PG_HBA_CONF << EOF
-# PostgreSQL Client Authentication Configuration File
-# ===================================================
-
-# TYPE DATABASE USER ADDRESS METHOD
-
-# LightRAG user authentication (must be first to take precedence)
-local ${POSTGRES_DATABASE:-lightrag} ${POSTGRES_USER:-lightrag} md5
-host ${POSTGRES_DATABASE:-lightrag} ${POSTGRES_USER:-lightrag} 127.0.0.1/32 md5
-host ${POSTGRES_DATABASE:-lightrag} ${POSTGRES_USER:-lightrag} ::1/128 md5
-host ${POSTGRES_DATABASE:-lightrag} ${POSTGRES_USER:-lightrag} 0.0.0.0/0 md5
-
-# Default configurations
-local all postgres peer
-local all all peer
-host all all 127.0.0.1/32 scram-sha-256
-host all all ::1/128 scram-sha-256
-local replication all peer
-host replication all 127.0.0.1/32 scram-sha-256
-host replication all ::1/128 scram-sha-256
-EOF
-
-# 重启 PostgreSQL 以应用 pg_hba.conf 更改
-echo "Restarting PostgreSQL to apply authentication changes..."
-service postgresql restart
-sleep 5
-
-echo "Installing extensions..."
-
-# 安装 vector 扩展
-echo "Installing vector extension..."
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"CREATE EXTENSION IF NOT EXISTS vector;\""
-
-# 安装 age 扩展
-echo "Installing age extension..."
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"CREATE EXTENSION IF NOT EXISTS age;\""
-
-echo "Configuring AGE extension..."
-
-# 加载 AGE 扩展
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"LOAD 'age';\""
-
-# 设置搜索路径
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"SET search_path = ag_catalog, public;\""
-
-# 创建图(如果不存在)
-echo "Creating LightRAG graph..."
-if su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -tAc \"SELECT 1 FROM ag_catalog.ag_graph WHERE name='lightrag'\"" | grep -q 1; then
- echo "Graph 'lightrag' already exists"
-else
- su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"SELECT ag_catalog.create_graph('lightrag');\""
- echo "Graph 'lightrag' created successfully"
-fi
-
-echo "Creating LightRAG application tables..."
-
-# 创建 LightRAG 需要的基础表
-echo "Creating lightrag_kv_store table..."
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"
-CREATE TABLE IF NOT EXISTS lightrag_kv_store (
- key VARCHAR PRIMARY KEY,
- value JSONB,
- created_at TIMESTAMP DEFAULT NOW(),
- updated_at TIMESTAMP DEFAULT NOW()
-);
-\""
-
-echo "Creating lightrag_doc_status table..."
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"
-CREATE TABLE IF NOT EXISTS lightrag_doc_status (
- doc_id VARCHAR PRIMARY KEY,
- status VARCHAR NOT NULL,
- metadata JSONB,
- created_at TIMESTAMP DEFAULT NOW(),
- updated_at TIMESTAMP DEFAULT NOW()
-);
-\""
-
-echo "Creating indexes for performance optimization..."
-
-# 为应用表创建索引
-echo "Creating KV store indexes..."
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"
-CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_lightrag_kv_store_updated_at ON lightrag_kv_store(updated_at);
-\""
-
-echo "Creating doc status indexes..."
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"
-CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_lightrag_doc_status_status ON lightrag_doc_status(status);
-CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_lightrag_doc_status_updated_at ON lightrag_doc_status(updated_at);
-\""
-
-# 等待图表创建完成后创建 AGE 相关索引
-echo "Waiting for graph tables to be fully initialized..."
-sleep 15
-
-# 验证 AGE 扩展是否正确加载
-echo "Verifying AGE extension is working..."
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"SELECT ag_catalog.create_graph('test_graph'); SELECT ag_catalog.drop_graph('test_graph', true);\"" || echo "AGE extension verification failed, but continuing..."
-
-echo "Creating AGE performance indexes..."
-
-# 检查并创建 Entity 表索引
-echo "Creating Entity table indexes..."
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"
-DO \$\$
-BEGIN
- -- Entity 表索引
- IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'lightrag' AND table_name = 'Entity') THEN
- PERFORM 1;
- -- 主键索引通常自动创建,这里创建其他有用的索引
- IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE schemaname = 'lightrag' AND tablename = 'Entity' AND indexname = 'entity_node_id_gin_idx') THEN
- CREATE INDEX CONCURRENTLY entity_node_id_gin_idx ON lightrag.\\\"Entity\\\" USING gin(properties);
- END IF;
- END IF;
-EXCEPTION
- WHEN OTHERS THEN
- RAISE NOTICE 'Entity table not ready yet, skipping indexes';
-END
-\$\$;
-\""
-
-# 检查并创建 DIRECTED 关系表索引
-echo "Creating DIRECTED relationship indexes..."
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"
-DO \$\$
-BEGIN
- -- DIRECTED 关系表索引
- IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'lightrag' AND table_name = 'DIRECTED') THEN
- IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE schemaname = 'lightrag' AND tablename = 'DIRECTED' AND indexname = 'directed_eid_idx') THEN
- CREATE INDEX CONCURRENTLY directed_eid_idx ON lightrag.\\\"DIRECTED\\\" (end_id);
- END IF;
- IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE schemaname = 'lightrag' AND tablename = 'DIRECTED' AND indexname = 'directed_sid_idx') THEN
- CREATE INDEX CONCURRENTLY directed_sid_idx ON lightrag.\\\"DIRECTED\\\" (start_id);
- END IF;
- IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE schemaname = 'lightrag' AND tablename = 'DIRECTED' AND indexname = 'directed_seid_idx') THEN
- CREATE INDEX CONCURRENTLY directed_seid_idx ON lightrag.\\\"DIRECTED\\\" (start_id, end_id);
- END IF;
- END IF;
-EXCEPTION
- WHEN OTHERS THEN
- RAISE NOTICE 'DIRECTED table not ready yet, skipping indexes';
-END
-\$\$;
-\""
-
-# 检查并创建 Edge 表索引
-echo "Creating Edge table indexes..."
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"
-DO \$\$
-BEGIN
- -- Edge 表索引
- IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'lightrag' AND table_name = '_ag_label_edge') THEN
- IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE schemaname = 'lightrag' AND tablename = '_ag_label_edge' AND indexname = 'edge_sid_idx') THEN
- CREATE INDEX CONCURRENTLY edge_sid_idx ON lightrag.\\\"_ag_label_edge\\\" (start_id);
- END IF;
- IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE schemaname = 'lightrag' AND tablename = '_ag_label_edge' AND indexname = 'edge_eid_idx') THEN
- CREATE INDEX CONCURRENTLY edge_eid_idx ON lightrag.\\\"_ag_label_edge\\\" (end_id);
- END IF;
- IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE schemaname = 'lightrag' AND tablename = '_ag_label_edge' AND indexname = 'edge_seid_idx') THEN
- CREATE INDEX CONCURRENTLY edge_seid_idx ON lightrag.\\\"_ag_label_edge\\\" (start_id, end_id);
- END IF;
- END IF;
-EXCEPTION
- WHEN OTHERS THEN
- RAISE NOTICE 'Edge table not ready yet, skipping indexes';
-END
-\$\$;
-\""
-
-echo "Setting up permissions..."
-
-# 授权给 lightrag 用户
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"
-GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO ${POSTGRES_USER:-lightrag};
-GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO ${POSTGRES_USER:-lightrag};
-GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO ${POSTGRES_USER:-lightrag};
-GRANT USAGE ON SCHEMA public TO ${POSTGRES_USER:-lightrag};
-\""
-
-# 为 AGE 图授权
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"
-GRANT ALL PRIVILEGES ON SCHEMA lightrag TO ${POSTGRES_USER:-lightrag};
-GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA lightrag TO ${POSTGRES_USER:-lightrag};
-GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA lightrag TO ${POSTGRES_USER:-lightrag};
-GRANT USAGE ON SCHEMA lightrag TO ${POSTGRES_USER:-lightrag};
-\""
-
-echo "Applying PostgreSQL performance configuration..."
-
-# 应用性能配置
-su - postgres -c "psql -c \"ALTER SYSTEM SET shared_preload_libraries = 'age';\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET max_connections = 200;\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET shared_buffers = '256MB';\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET effective_cache_size = '1GB';\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET maintenance_work_mem = '64MB';\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET random_page_cost = 1.1;\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET effective_io_concurrency = 200;\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET work_mem = '8MB';\""
-
-# 连接和查询超时配置
-su - postgres -c "psql -c \"ALTER SYSTEM SET statement_timeout = '300000';\"" # 5分钟查询超时
-su - postgres -c "psql -c \"ALTER SYSTEM SET idle_in_transaction_session_timeout = '600000';\"" # 10分钟事务超时
-su - postgres -c "psql -c \"ALTER SYSTEM SET tcp_keepalives_idle = '600';\"" # TCP keepalive 设置
-su - postgres -c "psql -c \"ALTER SYSTEM SET tcp_keepalives_interval = '30';\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET tcp_keepalives_count = '3';\""
-
-# 查询优化配置
-su - postgres -c "psql -c \"ALTER SYSTEM SET max_parallel_workers_per_gather = '2';\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET max_parallel_workers = '4';\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET enable_parallel_hash = 'on';\""
-
-# 内存和查询限制优化
-su - postgres -c "psql -c \"ALTER SYSTEM SET temp_buffers = '16MB';\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET max_stack_depth = '2MB';\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET huge_pages = 'try';\""
-
-# 启用查询计划缓存和日志记录
-su - postgres -c "psql -c \"ALTER SYSTEM SET plan_cache_mode = 'auto';\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET log_statement = 'all';\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET log_duration = 'on';\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET log_min_duration_statement = '1000';\"" # 记录超过1秒的查询
-su - postgres -c "psql -c \"ALTER SYSTEM SET log_disconnections = 'on';\""
-su - postgres -c "psql -c \"ALTER SYSTEM SET log_connections = 'on';\""
-
-# 重新加载配置
-su - postgres -c "psql -c \"SELECT pg_reload_conf();\""
-
-echo "Restarting PostgreSQL to apply configuration changes..."
-service postgresql restart
-sleep 5
-
-echo "Verifying setup..."
-
-# 验证扩展
-echo "Installed extensions:"
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"\\dx\""
-
-# 验证图
-echo "Available graphs:"
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"SELECT name FROM ag_catalog.ag_graph;\""
-
-# 验证表
-echo "Created tables:"
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"
-SELECT schemaname, tablename
-FROM pg_tables
-WHERE schemaname IN ('public', 'lightrag')
-ORDER BY schemaname, tablename;
-\""
-
-# 验证索引
-echo "Created indexes:"
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"
-SELECT schemaname, tablename, indexname, indexdef
-FROM pg_indexes
-WHERE schemaname IN ('public', 'lightrag')
-ORDER BY schemaname, tablename, indexname;
-\""
-
-# 测试连接
-echo "Testing database connection..."
-export PGPASSWORD="${POSTGRES_PASSWORD:-lightrag}"
-if PGPASSWORD="${POSTGRES_PASSWORD:-lightrag}" psql -h localhost -p 5432 -U ${POSTGRES_USER:-lightrag} -d ${POSTGRES_DATABASE:-lightrag} -c "SELECT version();" > /dev/null 2>&1; then
- echo "✅ Database connection test successful!"
-else
- echo "❌ Database connection test failed!"
- echo "Checking pg_hba.conf..."
- cat $PG_HBA_CONF | head -20
- echo "Checking PostgreSQL logs..."
- tail -20 /var/log/postgresql/postgresql-16-main.log
-fi
-
-echo "✅ PostgreSQL setup completed successfully!"
-echo "Database: ${POSTGRES_DATABASE:-lightrag}"
-echo "User: ${POSTGRES_USER:-lightrag}"
-echo "Extensions: vector, age"
-echo "Graph: lightrag"
-echo "Tables: lightrag_kv_store, lightrag_doc_status + AGE graph tables"
-echo "Connection: postgresql://${POSTGRES_USER:-lightrag}:***@localhost:5432/${POSTGRES_DATABASE:-lightrag}"
-
-# 最终验证数据库完全准备就绪
-echo "Performing final readiness check..."
-sleep 5
-if PGPASSWORD="${POSTGRES_PASSWORD:-lightrag}" psql -h localhost -p 5432 -U ${POSTGRES_USER:-lightrag} -d ${POSTGRES_DATABASE:-lightrag} -c "SELECT ag_catalog.create_graph('final_test'); SELECT ag_catalog.drop_graph('final_test', true);" > /dev/null 2>&1; then
- echo "✅ Database is fully ready for LightRAG operations!"
-else
- echo "⚠️ Database basic operations work, but AGE may need more time to be fully ready"
-fi
-
-# 显示数据库统计信息
-echo "Database statistics:"
-su - postgres -c "psql -d ${POSTGRES_DATABASE:-lightrag} -c \"
-SELECT
- schemaname,
- COUNT(*) as table_count
-FROM pg_tables
-WHERE schemaname IN ('public', 'lightrag')
-GROUP BY schemaname;
-\""
-
-# 保持容器运行并显示日志
-echo "PostgreSQL is ready for connections on port 5432"
-tail -f /var/log/postgresql/postgresql-16-main.log
\ No newline at end of file
diff --git a/docker/init-postgres.sql b/docker/init-postgres.sql
deleted file mode 100644
index b9f2b95a..00000000
--- a/docker/init-postgres.sql
+++ /dev/null
@@ -1,72 +0,0 @@
--- LightRAG PostgreSQL 初始化脚本
--- 基于官方文档建议: https://github.com/HKUDS/LightRAG
-
--- 创建必要的扩展
-CREATE EXTENSION IF NOT EXISTS vector;
-CREATE EXTENSION IF NOT EXISTS age;
-
--- 加载 AGE 扩展
-LOAD 'age';
-
--- 设置搜索路径
-SET search_path = ag_catalog, "$user", public;
-
--- 创建 LightRAG 图(如果不存在)
--- 注意:这里使用 'lightrag' 作为图名,可以根据需要修改
-SELECT create_graph('lightrag');
-
--- 为 AGE 创建索引以提高性能
--- 替换下面的 'lightrag' 为您的实际图名
-
--- Entity 表索引
-CREATE INDEX CONCURRENTLY IF NOT EXISTS entity_p_idx ON lightrag."Entity" (id);
-CREATE INDEX CONCURRENTLY IF NOT EXISTS entity_idx_node_id ON lightrag."Entity" (ag_catalog.agtype_access_operator(properties, '"node_id"'::agtype));
-CREATE INDEX CONCURRENTLY IF NOT EXISTS entity_node_id_gin_idx ON lightrag."Entity" using gin(properties);
-
--- Vertex 表索引
-CREATE INDEX CONCURRENTLY IF NOT EXISTS vertex_p_idx ON lightrag."_ag_label_vertex" (id);
-CREATE INDEX CONCURRENTLY IF NOT EXISTS vertex_idx_node_id ON lightrag."_ag_label_vertex" (ag_catalog.agtype_access_operator(properties, '"node_id"'::agtype));
-
--- DIRECTED 关系表索引
-CREATE INDEX CONCURRENTLY IF NOT EXISTS directed_p_idx ON lightrag."DIRECTED" (id);
-CREATE INDEX CONCURRENTLY IF NOT EXISTS directed_eid_idx ON lightrag."DIRECTED" (end_id);
-CREATE INDEX CONCURRENTLY IF NOT EXISTS directed_sid_idx ON lightrag."DIRECTED" (start_id);
-CREATE INDEX CONCURRENTLY IF NOT EXISTS directed_seid_idx ON lightrag."DIRECTED" (start_id,end_id);
-
--- Edge 表索引
-CREATE INDEX CONCURRENTLY IF NOT EXISTS edge_p_idx ON lightrag."_ag_label_edge" (id);
-CREATE INDEX CONCURRENTLY IF NOT EXISTS edge_sid_idx ON lightrag."_ag_label_edge" (start_id);
-CREATE INDEX CONCURRENTLY IF NOT EXISTS edge_eid_idx ON lightrag."_ag_label_edge" (end_id);
-CREATE INDEX CONCURRENTLY IF NOT EXISTS edge_seid_idx ON lightrag."_ag_label_edge" (start_id,end_id);
-
--- 集群表以提高性能
-ALTER TABLE lightrag."DIRECTED" CLUSTER ON directed_sid_idx;
-
--- 创建 LightRAG 需要的基础表(如果使用 PostgreSQL 作为 KV store)
-CREATE TABLE IF NOT EXISTS lightrag_kv_store (
- key VARCHAR PRIMARY KEY,
- value JSONB,
- created_at TIMESTAMP DEFAULT NOW(),
- updated_at TIMESTAMP DEFAULT NOW()
-);
-
--- 创建索引
-CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_lightrag_kv_store_updated_at ON lightrag_kv_store(updated_at);
-
--- 创建文档状态表
-CREATE TABLE IF NOT EXISTS lightrag_doc_status (
- doc_id VARCHAR PRIMARY KEY,
- status VARCHAR NOT NULL,
- metadata JSONB,
- created_at TIMESTAMP DEFAULT NOW(),
- updated_at TIMESTAMP DEFAULT NOW()
-);
-
--- 授权给 lightrag 用户
-GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO lightrag;
-GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO lightrag;
-GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO lightrag;
-
--- 为 AGE 图授权
-GRANT ALL PRIVILEGES ON SCHEMA lightrag TO lightrag;
-GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA lightrag TO lightrag;
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index 3830fe67..65ff10bb 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -10,7 +10,6 @@ dependencies = [
"dashscope>=1.23.2",
"docx2txt>=0.9",
"fastapi>=0.115.12",
- "graspologic>=3.3.0",
"langchain-community>=0.3.22",
"langchain-deepseek>=0.1.3",
"langchain-huggingface>=0.2.0",
@@ -42,7 +41,6 @@ dependencies = [
"tavily-python>=0.7.0",
"unstructured>=0.17.2",
"uvicorn[standard]>=0.34.2",
- "zhipuai>=2.1.5.20250421",
]
[tool.ruff]
line-length = 210 # 代码最大行宽
@@ -59,11 +57,3 @@ dev = [
"ruff>=0.12.1",
"vllm>=0.8.5.post1",
]
-
-# uv 配置 - 使用清华大学镜像源
-[tool.uv]
-index-url = "https://pypi.tuna.tsinghua.edu.cn/simple/"
-extra-index-url = [
- "https://mirrors.aliyun.com/pypi/simple/",
- "https://pypi.douban.com/simple/"
-]
diff --git a/server/routers/graph_router.py b/server/routers/graph_router.py
index 00eb546d..2068b1d4 100644
--- a/server/routers/graph_router.py
+++ b/server/routers/graph_router.py
@@ -1,8 +1,4 @@
-import json
-import os
-import asyncio
import traceback
-from typing import List, Dict, Any, Optional
from fastapi import APIRouter, Query, HTTPException, Depends
from server.utils.auth_middleware import get_admin_user
from server.models.user_model import User
@@ -23,13 +19,13 @@ async def get_subgraph(
):
"""
使用 LightRAG 原生方法获取知识图谱子图
-
+
Args:
db_id: LightRAG 数据库实例ID
node_label: 节点标签,用于查找起始节点,使用 "*" 获取全图
max_depth: 子图的最大深度
max_nodes: 返回的最大节点数量
-
+
Returns:
包含节点和边的知识图谱数据
"""
@@ -95,10 +91,10 @@ async def get_graph_labels(
):
"""
获取知识图谱中的所有标签
-
+
Args:
db_id: LightRAG 数据库实例ID
-
+
Returns:
图谱中所有可用的标签列表
"""
@@ -132,7 +128,7 @@ async def get_available_databases(
):
"""
获取所有可用的 LightRAG 数据库
-
+
Returns:
可用的数据库列表
"""
diff --git a/src/core/graphbase.py b/src/core/graphbase.py
index 3a5fcd5a..67c7f23f 100644
--- a/src/core/graphbase.py
+++ b/src/core/graphbase.py
@@ -7,7 +7,7 @@ from neo4j import GraphDatabase as GD
from neo4j import Query
from src import config
-from src.models.embedding import get_embedding_model
+from src.models import select_embedding_model
from src.utils import logger
warnings.filterwarnings("ignore", category=UserWarning)
@@ -22,7 +22,7 @@ class GraphDatabase:
self.status = "closed"
self.kgdb_name = "neo4j"
self.embed_model_name = os.getenv("GRAPH_EMBED_MODEL_NAME") or "siliconflow/BAAI/bge-m3"
- self.embed_model = get_embedding_model(self.embed_model_name)
+ self.embed_model = select_embedding_model(self.embed_model_name)
self.work_dir = os.path.join(config.save_dir, "knowledge_graph", self.kgdb_name)
os.makedirs(self.work_dir, exist_ok=True)
@@ -590,9 +590,11 @@ class GraphDatabase:
source_id = source.element_id
target_id = target.element_id
- assert node_dict is not None, "node_dict is required"
- source_name = node_dict[source_id]["name"] if source_name is None else source_name
- target_name = node_dict[target_id]["name"] if target_name is None else target_name
+ # 如果没有提供 source_name 或 target_name,则需要 node_dict
+ if source_name is None or target_name is None:
+ assert node_dict is not None, "node_dict is required when source_name or target_name is None"
+ source_name = node_dict[source_id]["name"] if source_name is None else source_name
+ target_name = node_dict[target_id]["name"] if target_name is None else target_name
relationship_type = relationship._properties.get("type", "unknown")
if relationship_type == "unknown":
diff --git a/src/core/lightrag_based_kb.py b/src/core/lightrag_based_kb.py
index 68b7c109..2292f049 100644
--- a/src/core/lightrag_based_kb.py
+++ b/src/core/lightrag_based_kb.py
@@ -92,11 +92,12 @@ class LightRagBasedKB:
# 使用配置的 LLM 和 embedding 函数
rag = LightRAG(
working_dir=working_dir,
+ workspace=db_id,
llm_model_func=self._get_llm_func(llm_info),
embedding_func=self._get_embedding_func(embed_info),
vector_storage="MilvusVectorDBStorage",
kv_storage="JsonKVStorage",
- graph_storage="PGGraphStorage",
+ graph_storage="Neo4JStorage",
doc_status_storage="JsonDocStatusStorage",
log_file_path=os.path.join(self.work_dir, db_id, "lightrag.log"),
)
@@ -127,16 +128,16 @@ class LightRagBasedKB:
# provider_info = config.model_names[llm_info.get("provider")]
# api_key = os.getenv(provider_info.get("env")[0] or "OPENAI_API_KEY") or "no_api_key"
# base_url = get_docker_safe_url(provider_info.get("base_url", "http://localhost:8081/v1"))
- from src.models import get_custom_model
- llm_info = get_custom_model("qwen3:32b-RFnC")
+ from src.models import select_model
+ model = select_model("dashscope", "qwen-max-latest")
async def llm_model_func(prompt, system_prompt=None, history_messages=[], **kwargs):
return await openai_complete_if_cache(
- llm_info.get("name", "qwen3-1.7b"),
- prompt,
+ model=model.model_name,
+ prompt=prompt,
system_prompt=system_prompt,
history_messages=history_messages,
- api_key=llm_info.get("api_key"),
- base_url=get_docker_safe_url(llm_info.get("api_base")),
+ api_key=model.api_key,
+ base_url=model.base_url,
extra_body={"enable_thinking": False},
**kwargs,
)
@@ -144,16 +145,16 @@ class LightRagBasedKB:
def _get_embedding_func(self, embed_info: dict):
"""获取 embedding 函数"""
- api_key = os.getenv(embed_info.get("api_key", "OPENAI_API_KEY")) or "no_api_key"
- base_url = embed_info.get("base_url", "http://localhost:8081/v1").replace("/embeddings", "")
+ from src.models import select_embedding_model
+ model = select_embedding_model("siliconflow/BAAI/bge-m3")
return EmbeddingFunc(
- embedding_dim=embed_info.get("dimension") or 1024,
+ embedding_dim=model.dimension,
max_token_size=4096,
func=lambda texts: openai_embed(
texts=texts,
- model=embed_info.get("model_name") or "Qwen3-Embedding-0.6B",
- api_key=api_key,
- base_url=get_docker_safe_url(base_url)
+ model=model.model,
+ api_key=model.api_key,
+ base_url=model.base_url.replace("/embeddings", ""),
),
)
@@ -335,7 +336,8 @@ class LightRagBasedKB:
# 根据内容类型处理内容
if content_type == "file":
markdown_content = await self._process_file_to_markdown(item, params=params)
- logger.info(f"Markdown content: {markdown_content[:100].replace('\n', ' ')}...")
+ markdown_content_lines = markdown_content[:100].replace('\n', ' ')
+ logger.info(f"Markdown content: {markdown_content_lines}...")
else: # URL
markdown_content = await self._process_url_to_markdown(item, params=params)
diff --git a/src/models/__init__.py b/src/models/__init__.py
index 885ebdb1..87316f2a 100644
--- a/src/models/__init__.py
+++ b/src/models/__init__.py
@@ -4,6 +4,7 @@ import traceback
from src import config
from src.utils.logging_config import logger
from src.models.chat_model import OpenAIBase
+from src.models.embedding import OllamaEmbedding, OtherEmbedding
def select_model(model_provider, model_name=None):
"""根据模型提供者选择模型"""
@@ -38,6 +39,24 @@ def select_model(model_provider, model_name=None):
except Exception as e:
raise ValueError(f"Model provider {model_provider} load failed, {e} \n {traceback.format_exc()}")
+
+def select_embedding_model(model_id):
+ provider, model_name = model_id.split('/', 1) if model_id else ("", "")
+ support_embed_models = config.embed_model_names.keys()
+ assert model_id in support_embed_models, f"Unsupported embed model: {model_id}, only support {support_embed_models}"
+ logger.debug(f"Loading embedding model {model_id}")
+ if provider == "local":
+ raise ValueError("Local embedding model is not supported, please use other embedding models")
+
+ elif provider == "ollama":
+ model = OllamaEmbedding(model_id)
+
+ else:
+ model = OtherEmbedding(model_id)
+
+ return model
+
+
def get_custom_model(model_id):
"""return model_info"""
assert config.custom_models is not None, "custom_models is not set"
diff --git a/src/models/embedding.py b/src/models/embedding.py
index 9cfb9afb..02bac5a5 100644
--- a/src/models/embedding.py
+++ b/src/models/embedding.py
@@ -3,7 +3,6 @@ import json
import requests
import asyncio
from abc import abstractmethod
-from zhipuai import ZhipuAI
from langchain_huggingface import HuggingFaceEmbeddings
from src import config
@@ -19,6 +18,7 @@ class BaseEmbeddingModel:
self.model = self.info["name"]
self.dimension = self.info.get("dimension", None)
self.url = get_docker_safe_url(self.info["base_url"])
+ self.base_url = get_docker_safe_url(self.info["base_url"])
self.api_key = os.getenv(self.info["api_key"], self.info["api_key"])
@abstractmethod
@@ -110,19 +110,3 @@ class OtherEmbedding(BaseEmbeddingModel):
"model": self.model,
"input": message,
}
-
-def get_embedding_model(model_id):
- provider, model_name = model_id.split('/', 1) if model_id else ("", "")
- support_embed_models = config.embed_model_names.keys()
- assert model_id in support_embed_models, f"Unsupported embed model: {model_id}, only support {support_embed_models}"
- logger.debug(f"Loading embedding model {model_id}")
- if provider == "local":
- raise ValueError("Local embedding model is not supported, please use other embedding models")
-
- elif provider == "ollama":
- model = OllamaEmbedding(model_id)
-
- else:
- model = OtherEmbedding(model_id)
-
- return model
diff --git a/web/src/stores/graphStore.js b/web/src/stores/graphStore.js
index aa38968a..0903bd0b 100644
--- a/web/src/stores/graphStore.js
+++ b/web/src/stores/graphStore.js
@@ -47,19 +47,19 @@ export const useGraphStore = defineStore('graph', {
// 首先尝试通过dynamicId匹配
let foundEdge = state.rawGraph.edges.find(edge => edge.dynamicId === state.selectedEdge)
if (foundEdge) return foundEdge
-
+
// 如果没找到,尝试通过原始ID匹配
foundEdge = state.rawGraph.edges.find(edge => edge.id === state.selectedEdge)
if (foundEdge) return foundEdge
-
+
// 最后尝试通过source->target格式匹配
const [source, target] = state.selectedEdge.split('->')
if (source && target) {
- foundEdge = state.rawGraph.edges.find(edge =>
+ foundEdge = state.rawGraph.edges.find(edge =>
edge.source === source.trim() && edge.target === target.trim()
)
}
-
+
return foundEdge || null
},
@@ -200,7 +200,7 @@ export const useGraphStore = defineStore('graph', {
const nodeId = String(node.id)
const labels = node.labels || [node.entity_type || 'unknown']
const entityType = node.entity_type || labels[0] || 'unknown'
-
+
const processedNode = {
id: nodeId,
labels: Array.isArray(labels) ? labels.map(String) : [String(labels)],
@@ -246,10 +246,10 @@ export const useGraphStore = defineStore('graph', {
const sourceId = String(edge.source)
const targetId = String(edge.target)
const dynamicId = `${sourceId}-${targetId}-${index}`
-
+
// 适配新的LightRAG API格式
const weight = Number(edge.properties?.weight || edge.weight || 1.0)
-
+
const processedEdge = {
id: String(edge.id),
source: sourceId,
@@ -345,7 +345,7 @@ export const useGraphStore = defineStore('graph', {
try {
// 使用动态ID作为Sigma边ID,避免重复
const sigmaEdgeId = edge.dynamicId || `${edge.source}->${edge.target}`
-
+
// 检查是否已存在相同的边
if (!sigmaGraph.hasEdge(sigmaEdgeId)) {
sigmaGraph.addEdgeWithKey(sigmaEdgeId, String(edge.source), String(edge.target), edgeAttributes)
diff --git a/web/src/views/DataBaseInfoView.vue b/web/src/views/DataBaseInfoView.vue
index 1865e706..629c99e6 100644
--- a/web/src/views/DataBaseInfoView.vue
+++ b/web/src/views/DataBaseInfoView.vue
@@ -289,20 +289,6 @@
片段最大Token数:
-关系描述最大Token数:
-实体描述最大Token数:
-