Skip to content

Commit 15473ec

Browse files
committed
docs: Update README and Docker Compose files to clarify API key configuration and enhance deployment instructions
1 parent 310441c commit 15473ec

File tree

9 files changed

+417
-98
lines changed

9 files changed

+417
-98
lines changed

README.md

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -88,56 +88,47 @@ GC-QA-RAG 是一个**企业级的检索增强生成(RAG)系统**。我们通
8888
git clone https://github.com/GrapeCity-AI/gc-qa-rag.git
8989
cd gc-qa-rag
9090

91-
# 2. 配置API密钥 (必须!)
92-
# 编辑 sources/gc-qa-rag-etl/.config.production.json
93-
# 编辑 sources/gc-qa-rag-server/.config.production.json
94-
# 填入您的API密钥
91+
# 2. 编辑 ETL 配置
92+
cd sources/gc-qa-rag-etl/deploy
93+
# 编辑 docker-compose.dockerhub.yml,取消注释并填入你的API密钥:
94+
# GC_QA_RAG_LLM_API_KEY: "your_llm_api_key_here"
95+
# GC_QA_RAG_EMBEDDING_API_KEY: "your_embedding_api_key_here"
9596

96-
# 3. 进入部署目录
97+
# 3. 启动 ETL 服务
98+
docker compose -f docker-compose.dockerhub.yml up -d
99+
100+
# 4. 编辑 RAG 配置
97101
cd sources/gc-qa-rag-server/deploy
102+
# 编辑 docker-compose.dockerhub.yml,取消注释并填入你的API密钥:
103+
# GC_QA_RAG_LLM_DEFAULT_API_KEY: "your_llm_api_key_here"
104+
# GC_QA_RAG_EMBEDDING_API_KEY: "your_embedding_api_key_here"
98105

99-
# 4. 使用 Docker Hub 镜像启动服务
106+
# 5. 启动 RAG 服务
100107
docker compose -f docker-compose.dockerhub.yml up -d
101108
```
102109

103-
#### 方法二:本地构建镜像
110+
#### 方法二:本地手动构建镜像
104111

105112
```bash
106113
# 1. 克隆项目
107114
git clone https://github.com/GrapeCity-AI/gc-qa-rag.git
108115
cd gc-qa-rag
109116

110117
# 2. 配置API密钥 (必须!)
111-
# 编辑 sources/gc-qa-rag-etl/.config.production.json
112-
# 编辑 sources/gc-qa-rag-server/.config.production.json
118+
# 编辑 sources/gc-qa-rag-etl/.config.production.json 或 .env 文件
119+
# 编辑 sources/gc-qa-rag-server/.config.production.json 或 .env 文件
113120
# 填入您的API密钥
114121

115-
# 3. 进入部署目录
116-
cd sources/gc-qa-rag-server/deploy
117-
118-
# 4. 启动所有服务
119-
docker compose up -d --build
120-
```
121-
122-
ETL 管理后台部署:
123-
124-
#### 方法一:使用 Docker Hub 镜像(推荐)
125-
126-
```bash
127-
# 1. 进入 ETL 目录
122+
# 3. 进入 ETL 目录
128123
cd sources/gc-qa-rag-etl/deploy
129124

130-
# 2. 使用 Docker Hub 镜像启动服务
131-
docker compose -f docker-compose.dockerhub.yml up -d
132-
```
133-
134-
#### 方法二:本地构建镜像
125+
# 4. 构建 ETL 镜像,并启动服务
126+
docker compose up -d --build
135127

136-
```bash
137-
# 1. 进入 ETL 目录
138-
cd sources/gc-qa-rag-etl/deploy
128+
# 5. 进入 RAG 目录
129+
cd sources/gc-qa-rag-server/deploy
139130

140-
# 2. 构建 Docker 镜像
131+
# 6. 构建 RAG 服务镜像,并启动服务
141132
docker compose up -d --build
142133
```
143134

@@ -172,6 +163,15 @@ docker compose up -d --build
172163
- MySQL
173164
- Qdrant
174165

166+
### 📋 配置说明
167+
168+
使用官方 Docker 镜像时,需要在 docker-compose.dockerhub.yml 文件中配置环境变量传递给容器。系统支持优先级为:**Docker 环境变量 > .env 文件 > JSON 配置文件**
169+
170+
**完整的环境变量列表请查看:**
171+
172+
- RAG 服务:[`sources/gc-qa-rag-server/env.example`](./sources/gc-qa-rag-server/env.example)
173+
- ETL 服务:[`sources/gc-qa-rag-etl/env.example`](./sources/gc-qa-rag-etl/env.example)
174+
175175
**重要**:无论选择哪种部署方式,都需要先配置 API 密钥!
176176

177177
详细步骤请参考我们的[《快速开始指南》](./quickstart.md)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
version: "3.8"
2+
3+
# 这是一个完整的环境变量配置示例
4+
# 复制此文件为 docker-compose.yml 并填入你的API密钥
5+
6+
services:
7+
rag-etl:
8+
image: grapecitysoftware/gc-qa-rag-etl:latest
9+
container_name: rag_etl_container
10+
restart: on-failure
11+
ports:
12+
- "8001:8001"
13+
environment:
14+
# 基础配置
15+
GC_QA_RAG_ENV: production
16+
17+
# === 必需配置 ===
18+
# 大语言模型API密钥(必需)
19+
GC_QA_RAG_LLM_API_KEY: "your_llm_api_key_here"
20+
# 嵌入模型API密钥(必需)
21+
GC_QA_RAG_EMBEDDING_API_KEY: "your_embedding_api_key_here"
22+
23+
# === 可选配置 ===
24+
# LLM设置
25+
GC_QA_RAG_LLM_API_BASE: "https://dashscope.aliyuncs.com/compatible-mode/v1"
26+
GC_QA_RAG_LLM_MODEL_NAME: "qwen-plus"
27+
GC_QA_RAG_LLM_MAX_RPM: "100"
28+
29+
# 向量数据库配置
30+
GC_QA_RAG_VECTOR_DB_HOST: "http://host.docker.internal:6333"
31+
32+
# 存储配置
33+
GC_QA_RAG_ROOT_PATH: "/app/.rag-cache"
34+
GC_QA_RAG_LOG_PATH: "/app/logs"
35+
36+
# DAS配置(可选,用于文档爬取)
37+
# GC_QA_RAG_DAS_BASE_URL_PAGE: ""
38+
# GC_QA_RAG_DAS_BASE_URL_THREAD: ""
39+
# GC_QA_RAG_DAS_TOKEN: ""
40+
volumes:
41+
- rag-etl-cache:/app/.rag-cache
42+
- rag-etl-logs:/app/logs
43+
44+
volumes:
45+
rag-etl-cache:
46+
rag-etl-logs:

sources/gc-qa-rag-etl/deploy/docker-compose.dockerhub.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ services:
88
restart: on-failure
99
environment:
1010
GC_QA_RAG_ENV: production
11+
# === 必需配置 - 请填入你的API密钥 ===
12+
# GC_QA_RAG_LLM_API_KEY: "your_llm_api_key_here"
13+
# GC_QA_RAG_EMBEDDING_API_KEY: "your_embedding_api_key_here"
14+
# === 可选配置 ===
15+
# GC_QA_RAG_LLM_API_BASE: "https://dashscope.aliyuncs.com/compatible-mode/v1"
16+
# GC_QA_RAG_LLM_MODEL_NAME: "qwen-plus"
17+
# GC_QA_RAG_VECTOR_DB_HOST: "http://host.docker.internal:6333"
1118
ports:
1219
- "8001:8001"
1320
volumes:

sources/gc-qa-rag-etl/env.example

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# GC-QA-RAG ETL Service Environment Variables
2+
# Copy this file to .env and fill in your values
3+
# Or set these as Docker environment variables
4+
5+
# Environment (optional, defaults to "production")
6+
GC_QA_RAG_ENV=production
7+
8+
# === Required Configuration ===
9+
# LLM API base URL (optional, defaults to Alibaba DashScope)
10+
GC_QA_RAG_LLM_API_BASE=https://dashscope.aliyuncs.com/compatible-mode/v1
11+
# LLM model name (optional, defaults to qwen-plus)
12+
GC_QA_RAG_LLM_MODEL_NAME=qwen-plus
13+
# LLM API key (required)
14+
GC_QA_RAG_LLM_API_KEY=your_llm_api_key_here
15+
16+
# Embedding API key (required)
17+
GC_QA_RAG_EMBEDDING_API_KEY=your_embedding_api_key_here
18+
19+
# === Optional Configuration ===
20+
# Max requests per minute (optional, defaults to 100)
21+
GC_QA_RAG_LLM_MAX_RPM=100
22+
23+
# Vector database host (optional, defaults to docker internal)
24+
GC_QA_RAG_VECTOR_DB_HOST=http://host.docker.internal:6333
25+
26+
# Storage paths (optional, uses system defaults)
27+
GC_QA_RAG_ROOT_PATH=./.rag-cache
28+
GC_QA_RAG_LOG_PATH=./
29+
30+
# === DAS Configuration (Optional for document crawling) ===
31+
GC_QA_RAG_DAS_BASE_URL_PAGE=
32+
GC_QA_RAG_DAS_BASE_URL_THREAD=
33+
GC_QA_RAG_DAS_TOKEN=

sources/gc-qa-rag-etl/etlapp/common/config.py

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import os
22
import json
3-
from typing import Optional
3+
from typing import Optional, Union
44
from dataclasses import dataclass
55
from pathlib import Path
66
from dotenv import load_dotenv
@@ -32,6 +32,45 @@ class VectorDbConfig:
3232
host: str
3333

3434

35+
def _get_config_value(key: str, config_raw: dict, default: Optional[str] = None) -> str:
36+
"""Get configuration value with priority: ENV > .env > JSON."""
37+
# First check environment variables
38+
env_value = os.getenv(key)
39+
if env_value is not None:
40+
return env_value
41+
42+
# Then check nested JSON structure
43+
keys = key.lower().split('_')
44+
# Skip the 'gc_qa_rag' prefix for JSON lookup
45+
if len(keys) >= 4 and keys[0] == 'gc' and keys[1] == 'qa' and keys[2] == 'rag':
46+
keys = keys[3:]
47+
48+
current = config_raw
49+
try:
50+
for k in keys:
51+
current = current[k]
52+
return str(current)
53+
except (KeyError, TypeError):
54+
pass
55+
56+
# Return default if provided
57+
if default is not None:
58+
return default
59+
60+
raise ValueError(f"Configuration value not found for key: {key}")
61+
62+
63+
def _get_config_int(key: str, config_raw: dict, default: Optional[int] = None) -> int:
64+
"""Get integer configuration value with priority: ENV > .env > JSON."""
65+
value = _get_config_value(key, config_raw, str(default) if default is not None else None)
66+
try:
67+
return int(value)
68+
except (ValueError, TypeError):
69+
if default is not None:
70+
return default
71+
raise ValueError(f"Invalid integer value for key {key}: {value}")
72+
73+
3574
@dataclass
3675
class Config:
3776
environment: str
@@ -45,47 +84,46 @@ class Config:
4584
@classmethod
4685
def from_environment(cls, environment: str) -> "Config":
4786
"""Create a Config instance from environment name."""
87+
# Load .env file first (lower priority than direct env vars)
88+
load_dotenv()
89+
90+
# Try to load JSON config, but make it optional
91+
config_raw = {}
4892
config_path = Path(f".config.{environment}.json")
49-
if not config_path.exists():
50-
raise FileNotFoundError(f"Configuration file not found: {config_path}")
51-
52-
try:
53-
with open(config_path) as f:
54-
config_raw = json.load(f)
55-
except json.JSONDecodeError as e:
56-
raise ValueError(f"Invalid JSON in configuration file: {e}")
93+
if config_path.exists():
94+
try:
95+
with open(config_path) as f:
96+
config_raw = json.load(f)
97+
except json.JSONDecodeError as e:
98+
print(f"Warning: Invalid JSON in configuration file: {e}")
5799

58100
return cls(
59101
environment=environment,
60102
das=DasConfig(
61-
base_url_page=config_raw["das"]["base_url_page"],
62-
base_url_thread=config_raw["das"]["base_url_thread"],
63-
token=config_raw["das"]["token"],
103+
base_url_page=_get_config_value("GC_QA_RAG_DAS_BASE_URL_PAGE", config_raw, ""),
104+
base_url_thread=_get_config_value("GC_QA_RAG_DAS_BASE_URL_THREAD", config_raw, ""),
105+
token=_get_config_value("GC_QA_RAG_DAS_TOKEN", config_raw, ""),
64106
),
65107
llm=LlmConfig(
66-
api_key=config_raw["llm"]["api_key"],
67-
api_base=config_raw["llm"]["api_base"],
68-
model_name=config_raw["llm"]["model_name"],
69-
max_rpm=config_raw["llm"].get("max_rpm", 100),
108+
api_key=_get_config_value("GC_QA_RAG_LLM_API_KEY", config_raw),
109+
api_base=_get_config_value("GC_QA_RAG_LLM_API_BASE", config_raw, "https://dashscope.aliyuncs.com/compatible-mode/v1"),
110+
model_name=_get_config_value("GC_QA_RAG_LLM_MODEL_NAME", config_raw, "qwen-plus"),
111+
max_rpm=_get_config_int("GC_QA_RAG_LLM_MAX_RPM", config_raw, 100),
70112
),
71-
embedding=EmbeddingConfig(api_key=config_raw["embedding"]["api_key"]),
72-
vector_db=VectorDbConfig(host=config_raw["vector_db"]["host"]),
73-
root_path=config_raw.get(
74-
"root_path", user_cache_dir("gc-qa-rag", ensure_exists=True)
113+
embedding=EmbeddingConfig(
114+
api_key=_get_config_value("GC_QA_RAG_EMBEDDING_API_KEY", config_raw)
75115
),
76-
log_path=config_raw.get(
77-
"log_path", user_log_dir("gc-qa-rag", ensure_exists=True)
116+
vector_db=VectorDbConfig(
117+
host=_get_config_value("GC_QA_RAG_VECTOR_DB_HOST", config_raw, "http://host.docker.internal:6333")
78118
),
119+
root_path=_get_config_value("GC_QA_RAG_ROOT_PATH", config_raw, user_cache_dir("gc-qa-rag", ensure_exists=True)),
120+
log_path=_get_config_value("GC_QA_RAG_LOG_PATH", config_raw, user_log_dir("gc-qa-rag", ensure_exists=True)),
79121
)
80122

81123

82124
def get_config() -> Config:
83125
"""Get the application configuration."""
84-
load_dotenv()
85-
environment = os.getenv("GC_QA_RAG_ENV")
86-
if not environment:
87-
raise ValueError("GC_QA_RAG_ENV environment variable is not set")
88-
126+
environment = os.getenv("GC_QA_RAG_ENV", "production")
89127
return Config.from_environment(environment)
90128

91129

0 commit comments

Comments
 (0)