Files
WeKnora/.env.example
T
issunion 4cce6f2e99 feat(retriever): 接入 Apache Doris 4.1 作为向量数据库
为 RetrieveEngine 体系新增 Doris 后端,与现有 Qdrant/Milvus/Weaviate
等保持完整能力对齐:向量检索、关键词检索、健康检查、环境变量与多实例
DB 配置、前端类型注册、单元测试、Docker Compose 模板。

实现要点:
- 协议分工:主链路用 MySQL 协议(database/sql + go-sql-driver/mysql)
  做 DDL / 查询 / 删除;批量更新走 Stream Load HTTP API,并启用
  partial_update=true、merge_type=APPEND,自动按 1MiB 切分批次并处理
  307 重定向。
- 表结构:UNIQUE KEY(id) + enable_unique_key_merge_on_write=true 以
  支持 upsert/部分列更新;按维度分表(<base>_<dim>),每张表上建
  HNSW ANN 索引(metric_type=cosine_distance)和 INVERTED 索引
  (parser=chinese)。
- 分数语义:使用 cosine_distance_approximate,再以 1 - dist 转换为
  "越大越相似",与现有 KVHybridRetrieveEngine 约定一致。
- 异步索引:ANN 索引为后台构建,ensureTable 通过轮询 SHOW INDEX 等
  待索引就绪后再放行写入,避免首次检索召回为空。
- ARRAY<FLOAT> 序列化:go-sql-driver/mysql 不支持数组占位符,
  embeddingLiteral 将 []float32 转成 SQL 字面量字符串再拼接。

新增文件:
- internal/application/repository/retriever/doris/{structs,schema,
  query,repository,streamload,repository_test}.go
- scripts/e2e-doris.sh:E2E 验证清单
- docs/wiki/集成扩展/Doris改动与上游同步.md:fork-and-rebase 工作流
  与改动清单

修改文件(接线 + 文档):
- internal/types/{retriever,tenant,vectorstore}.go:新增
  DorisRetrieverEngineType、env 解析、表单 schema 与索引参数校验
- internal/container/{container,engine_factory}.go:环境变量驱动
  与 VectorStore 配置驱动两条路径都支持 Doris
- internal/application/service/vectorstore{,_healthcheck}.go:连接
  校验 + Ping/Version 健康检查
- docker-compose.yml:新增 doris-fe / doris-be 服务(profile=doris)
- .env.example:DORIS_* 环境变量与示例
- docs/{使用其他向量数据库,wiki/集成扩展/集成向量数据库}.md:
  使用说明与索引/分数行为说明

依赖:go.mod/go.sum 新增 github.com/go-sql-driver/mysql(运行时)和
github.com/DATA-DOG/go-sqlmock(测试)。

测试:repository 层 SQL 形状、Stream Load HTTP 行为、whereBuilder
逻辑、embeddingLiteral 往返、健康检查错误路径均有单测覆盖。
2026-05-08 21:59:35 +08:00

472 lines
16 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 使用说明
# 1. 复制此文件为 .env
# 2. 替换所有占位符为实际值
# 3. 确保 .env 文件不会被提交到版本控制系统
# ========== 镜像版本 ==========
# WeKnora 镜像版本标签,可选值: latest(稳定版), main(最新开发版)
# WEKNORA_VERSION=latest
# gin mod
# 可选值: debug(开发模式,有详细日志), release(生产模式,禁用Swagger文档)
GIN_MODE=release
# 日志级别,可选值:debug, info, warn, error, fatal,默认为debug
# LOG_LEVEL=debug
# LLM 调试日志:将每次大模型调用的完整请求和响应写入独立日志文件,便于排查上下文问题
# 可选值:true(自动放在 LOG_PATH 同目录下 llm_debug.log)、false/空(关闭)、或指定文件路径
# LLM_DEBUG_LOG=true
# ========== Langfuse 可观测性(可选) ==========
# 用于追踪 chat / embedding / rerank / VLM / ASR 模型调用,统计 token 消耗。
# 详细说明:docs/Langfuse集成.md
#
# 方案 A:接入 Langfuse Cloud(最简单)
# 1) 登录 https://cloud.langfuse.com 生成 API Key
# 2) 填入下方 PUBLIC_KEY / SECRET_KEY
# 3) docker compose up -d app
#
# 方案 B:自建 Langfuse(局域网/内网环境)
# 1) 启动自建栈:docker compose --profile langfuse up -d
# 首次启动后 ClickHouse 迁移约 1-2 分钟,耐心等待 langfuse-web 健康
# 2) 浏览器打开 http://localhost:3000 注册管理员账号并生成 API Key
# 3) 取消注释下方 LANGFUSE_HOST=http://langfuse-web:3000
# 填入刚生成的 PUBLIC_KEY / SECRET_KEY
# 4) docker compose up -d app
#
# 只要同时设置了 PUBLIC_KEY + SECRET_KEY 就会自动启用,无需显式开关。
LANGFUSE_PUBLIC_KEY=pk-lf-xxxxxxxx
LANGFUSE_SECRET_KEY=sk-lf-xxxxxxxx
LANGFUSE_HOST=http://langfuse-web:3000
# 自建模式下改成:LANGFUSE_HOST=http://langfuse-web:3000
#
# 可选:显式开关(true/false,默认根据 key 自动判断)
# LANGFUSE_ENABLED=true
# 可选:版本 / 环境标签,便于在 Langfuse UI 过滤
# LANGFUSE_RELEASE=v0.4.2
# LANGFUSE_ENVIRONMENT=production
# 可选:批量上报与采样策略(生产高流量建议调大 FLUSH_AT、降低 SAMPLE_RATE
# LANGFUSE_FLUSH_AT=15
# LANGFUSE_FLUSH_INTERVAL=3s
# LANGFUSE_QUEUE_SIZE=2048
# LANGFUSE_REQUEST_TIMEOUT=10s
# LANGFUSE_SAMPLE_RATE=1.0
# LANGFUSE_DEBUG=false
# ========== Langfuse 自建栈配置(仅在使用 --profile langfuse 时需要) ==========
# 设计说明:为了最小化资源占用,Langfuse 自建栈会**复用** WeKnora 已有的
# - postgres:创建独立的 "langfuse" 数据库(由 langfuse-db-init 容器一次性创建)
# - redis :使用独立的 Redis DB 号(默认 1WeKnora 用 0
# 真正新增的只有 3 个常驻容器:langfuse-web、langfuse-worker、langfuse-clickhouse
# + 1 个专用 S3langfuse-minio
# + 1 个一次性 initlangfuse-db-init
#
# Langfuse Web UI 对外端口
# LANGFUSE_WEB_PORT=3000
#
# Langfuse 专用 MinIO 端口(避免和 WeKnora 主 MinIO 9000/9001 冲突)
# LANGFUSE_MINIO_S3_PORT=9100
# LANGFUSE_MINIO_CONSOLE_PORT=9101
#
# 在 WeKnora-postgres 中创建的 Langfuse 库名
# LANGFUSE_DB_NAME=langfuse
#
# 在 WeKnora-redis 中使用的 DB 号(1~15,不要和 WeKnora 的 0 冲突)
# LANGFUSE_REDIS_DB=1
#
# ClickHouse / Langfuse 专用 MinIO 凭证(生产请务必修改)
# LANGFUSE_CLICKHOUSE_USER=clickhouse
# LANGFUSE_CLICKHOUSE_PASSWORD=clickhouse
# LANGFUSE_MINIO_USER=langfuseminio
# LANGFUSE_MINIO_PASSWORD=langfuseminiosecret
#
# Langfuse 核心安全字段,生产必须重新生成:
# LANGFUSE_SALT=$(openssl rand -base64 32)
# LANGFUSE_ENCRYPTION_KEY=$(openssl rand -hex 32)
# LANGFUSE_NEXTAUTH_SECRET=$(openssl rand -base64 32)
# LANGFUSE_SALT=
# LANGFUSE_ENCRYPTION_KEY=
# LANGFUSE_NEXTAUTH_SECRET=
# LANGFUSE_NEXTAUTH_URL=http://localhost:3000
# LANGFUSE_TELEMETRY_ENABLED=false
#
# 可选:自动化首次启动(填写后直接注入管理员+项目,跳过 UI 注册)
# LANGFUSE_INIT_ORG_NAME=WeKnora
# LANGFUSE_INIT_PROJECT_NAME=WeKnora
# LANGFUSE_INIT_PROJECT_PUBLIC_KEY=pk-lf-weknora-init
# LANGFUSE_INIT_PROJECT_SECRET_KEY=sk-lf-weknora-init
# LANGFUSE_INIT_USER_EMAIL=admin@example.com
# LANGFUSE_INIT_USER_NAME=Admin
# LANGFUSE_INIT_USER_PASSWORD=change-me-please
# 时区设置,默认为 Asia/Shanghai
# 影响系统时间显示和日志时间戳
# 常用值:Asia/Shanghai, Asia/Tokyo, America/New_York, Europe/London, UTC
TZ=Asia/Shanghai
# 系统默认语言(BCP-47 格式),用于 Prompt 中 {{language}} 占位符的回退值
# 优先级:Accept-Language 请求头 > 此环境变量 > 内置默认值 (en-US)
# 常用值:zh-CN, en-US, ja-JP, ko-KR, ru-RU
# WEKNORA_LANGUAGE=zh-CN
# 禁止新用户注册(生产环境建议设为 true)
DISABLE_REGISTRATION=false
# Ollama 服务的基准 URL,用于连接本地/其他服务器上运行的 Ollama 服务
OLLAMA_BASE_URL=http://host.docker.internal:11434
# 存储配置
# 主数据库类型(postgres/mysql)
DB_DRIVER=postgres
# 向量存储类型(postgres/elasticsearch_v7/elasticsearch_v8/qdrant/milvus/weaviate/doris)
RETRIEVE_DRIVER=postgres
# 允许用户使用哪些文件存储类型,使用逗号分隔,留空则允许所有类型的存储
# STORAGE_ALLOW_LIST=local,minio,cos,tos,s3
# 文件存储类型(local/minio/cos/tos/s3)
STORAGE_TYPE=local
# 流处理后端(memory/redis)
STREAM_MANAGER_TYPE=redis
# 应用服务主机名,默认为app(Docker内部服务名)
# 如需代理到远程后端,可设为远程地址,如 remote-app.example.com
APP_HOST=app
# 应用服务宿主机映射端口,默认为8080(仅影响宿主机访问,不影响容器间通信)
APP_PORT=8080
# NGINX 代理到后端的目标端口,默认为8080(App容器内部监听端口)
# 本地部署:保持默认即可,无需随 APP_PORT 修改
# 远程部署:设为远程 App 服务的实际端口
# APP_BACKEND_PORT=8080
# NGINX 代理到后端的协议,默认为http
# 远程部署如后端为 HTTPS,需设为 https
# APP_SCHEME=http
# 应用外部访问地址(用于 IM 渠道中生成图片等文件的可访问链接)
# 设置为 WeKnora 实例的外部可访问 URL,如 https://weknora.example.com
# 不设置时,IM 渠道中本地存储的图片将无法正常显示(云存储不受影响)
# APP_EXTERNAL_URL=
# 前端服务端口,默认为80
FRONTEND_PORT=80
# 文档解析模块端口,默认为50051
DOCREADER_PORT=50051
# 数据库主机地址
DB_HOST=localhost
# 数据库端口
DB_PORT=5432
# 数据库用户名
DB_USER=postgres
# 数据库密码
DB_PASSWORD=postgres123!@#
# 数据库名称
DB_NAME=WeKnora
# 如果使用 redis 作为流处理后端,需要配置以下参数
# Redis用户名,Redis 6.0+ ACL 功能支持(可选)
# REDIS_USERNAME=
# Redis密码,如果没有设置密码,可以留空
REDIS_PASSWORD=redis123!@#
# Redis数据库索引,默认为0
REDIS_DB=0
# Redis key的前缀,用于命名空间隔离
REDIS_PREFIX=stream:
# 当使用本地存储时,文件保存的基础目录路径
LOCAL_STORAGE_BASE_DIR=/data/files
# 是否自动恢复脏数据
AUTO_RECOVER_DIRTY=true
TENANT_AES_KEY=weknorarag-api-key-secret-secret
# AES-256 密钥,用于数据库中 API Key 等敏感字段的落盘加密(必须为32字节)
SYSTEM_AES_KEY=weknora-system-aes-key-32bytes!!
# SSRF 校验白名单(可选)。逗号分隔;每条可为:精确域名(api.internal)、通配域名(*.example.com)、
# IPv4203.0.113.5)、IPv62001:db8::1,不带方括号)或 CIDR10.0.0.0/8, 2001:db8::/32)。
# 列入者会在 URL 校验等地方绕过常规 SSRF 规则,生产环境请谨慎配置。
# SSRF_WHITELIST=internal.service,*.corp.example,172.16.0.0/12,2001:db8::1,fd00::/8
# 是否开启知识图谱构建和检索(构建阶段需调用大模型,耗时较长)
ENABLE_GRAPH_RAG=false
# 配置 JWT_SECRET 用于前端登录刷新Token
JWT_SECRET=weknora-jwt-secret
# MinIO端口
# MINIO_PORT=9000
# MinIO控制台端口
# MINIO_CONSOLE_PORT=9001
# Embedding并发数,出现429错误时,可调小此参数
CONCURRENCY_POOL_SIZE=5
# (Removed: IMAGE_MAX_CONCURRENT, OCR_BACKEND — moved to Go App module after lightweight refactoring)
# 如果使用ElasticSearch作为向量存储,需要配置以下参数
# ElasticSearch地址,例如 http://localhost:9200
# ELASTICSEARCH_ADDR=your_elasticsearch_addr
# ElasticSearch用户名,如果需要身份验证
# ELASTICSEARCH_USERNAME=your_elasticsearch_username
# ElasticSearch密码,如果需要身份验证
# ELASTICSEARCH_PASSWORD=your_elasticsearch_password
# ElasticSearch索引名称,用于存储向量数据
# ELASTICSEARCH_INDEX=WeKnora
# 如果使用Qdrant作为向量存储,需要配置以下参数
# Qdrant服务主机地址
# QDRANT_HOST=localhost
# Qdrant服务端口
# QDRANT_PORT=6334
# Qdrant集合名称,用于存储向量数据
# QDRANT_COLLECTION=weknora_embeddings
# Qdrant API密钥,如果需要身份验证(可选)
# QDRANT_API_KEY=your_qdrant_api_key
# 是否启用TLS加密连接(可选,默认为false)
# QDRANT_USE_TLS=false
# 如果使用MinIO作为文件存储,需要配置以下参数
# MinIO访问端点(host:port),连接外部MinIO时需修改
# MINIO_ENDPOINT=minio:9000
# MinIO访问密钥
# MINIO_ACCESS_KEY_ID=your_minio_access_key
# MinIO密钥
# MINIO_SECRET_ACCESS_KEY=your_minio_secret_key
# MinIO桶名称,用于存储文件
# MINIO_BUCKET_NAME=your_minio_bucket_name
# 如果使用腾讯云COS作为文件存储,需要配置以下参数
# 腾讯云COS的访问密钥ID
# COS_SECRET_ID=your_cos_secret_id
# 腾讯云COS的密钥
# COS_SECRET_KEY=your_cos_secret_key
# 腾讯云COS的区域,例如 ap-guangzhou
# COS_REGION=your_cos_region
# 腾讯云COS的桶名称
# COS_BUCKET_NAME=your_cos_bucket_name
# 腾讯云COS的应用ID
# COS_APP_ID=your_cos_app_id
# 腾讯云COS的路径前缀,用于存储文件
# COS_PATH_PREFIX=your_cos_path_prefix
# COS_ENABLE_OLD_DOMAIN=true 表示启用旧的域名格式,默认为 true
COS_ENABLE_OLD_DOMAIN=true
# 如果使用火山引擎TOS作为文件存储,需要配置以下参数
# 火山引擎TOS的访问端点,例如 https://tos-cn-beijing.volces.com
# TOS_ENDPOINT=https://tos-cn-beijing.volces.com
# 火山引擎TOS的区域,例如 cn-beijing
# TOS_REGION=cn-beijing
# 火山引擎TOS访问密钥 Access Key
# TOS_ACCESS_KEY=your_tos_access_key
# 火山引擎TOS访问密钥 Secret Key
# TOS_SECRET_KEY=your_tos_secret_key
# 火山引擎TOS桶名称
# TOS_BUCKET_NAME=your_tos_bucket_name
# 火山引擎TOS可选路径前缀(可选)
# TOS_PATH_PREFIX=your_tos_path_prefix
# 火山引擎TOS临时桶名称(可选,用于存放自动过期临时文件)
# TOS_TEMP_BUCKET_NAME=your_tos_temp_bucket_name
# 火山引擎TOS临时桶区域(可选,默认与主桶相同)
# TOS_TEMP_REGION=your_tos_temp_region
# 如果使用AWS S3作为文件存储,需要配置以下参数
# AWS S3的访问端点,例如 https://s3.amazonaws.com
# S3_ENDPOINT=https://s3.amazonaws.com
# AWS S3的区域,例如 us-east-1
# S3_REGION=us-east-1
# AWS S3访问密钥 Access Key
# S3_ACCESS_KEY=your_s3_access_key
# AWS S3访问密钥 Secret Key
# S3_SECRET_KEY=your_s3_secret_key
# AWS S3桶名称
# S3_BUCKET_NAME=your_s3_bucket_name
# AWS S3可选路径前缀(可选)
# S3_PATH_PREFIX=your_s3_path_prefix
# 如果解析网络连接使用Web代理,需要配置以下参数
# WEB_PROXY=your_web_proxy
# Neo4j 开关
# NEO4J_ENABLE=false
# Neo4j的访问地址
# NEO4J_URI=neo4j://neo4j:7687
# Neo4j的用户名和密码
# NEO4J_USERNAME=neo4j
# Neo4j的密码
# NEO4J_PASSWORD=password
# ========== 文件上传大小限制 ==========
# 统一的文件大小限制(MB),默认为50MB
# 影响:单文件上传、gRPC消息大小、Nginx请求体大小
# MAX_FILE_SIZE_MB=50
# ========== Agent Skills Sandbox 配置 ==========
# Sandbox 模式: docker(默认), local, disabled
WEKNORA_SANDBOX_MODE=docker
# 脚本执行超时时间(秒),默认60
WEKNORA_SANDBOX_TIMEOUT=60
# 自定义 Sandbox Docker 镜像
WEKNORA_SANDBOX_DOCKER_IMAGE=wechatopenai/weknora-sandbox:latest
# ========== Agent 配置 ==========
# 智能体大模型调用默认超时时间(秒),默认 120
# 对于复杂的推理行为,建议调大此值(如 300 或 600)
# 注:此值为全局默认值。若单个智能体在数据库中配置了独立的 llm_call_timeout,则以智能体配置为准(优先级更高)。
# WEKNORA_AGENT_LLM_TIMEOUT=300
# APK 镜像源设置(可选)
APK_MIRROR_ARG=mirrors.tencent.com
# 如果使用Milvus作为向量存储,需要配置以下参数
# Milvus服务地址
# MILVUS_ADDRESS=milvus:19530
# Milvus集合名称,用于存储向量数据
# MILVUS_COLLECTION=weknora_embeddings
# Milvus向量搜索度量类型,支持 IP(默认)、COSINE、L2
# 注意:修改度量类型后需要重建collection才能生效
# MILVUS_METRIC_TYPE=IP
# Milvus 用户名(可选)
# MILVUS_USERNAME=your_milvus_username
# Milvus 密码(可选)
# MILVUS_PASSWORD=your_milvus_password
# Milvus 数据库名称(可选)
# MILVUS_DB_NAME=your_milvus_db_name
# Docreader 地址
DOCREADER_ADDR=docreader:50051
# Docreader 连接方式
DOCREADER_TRANSPORT=grpc
# Docreader 中 DOCX 解析的最大页数,默认 0(不限制)
# 设为正整数(如 500)可限制超大 Word 文档的解析开销;超过页数的内容将不会继续解析
# DOCREADER_DOCX_MAX_PAGES=0
# Docreader 重型解析器并发控制,适合限制多 PDF/OCR 同时导入时的资源占用
# 设为 0 可关闭对应限流;默认 1 更适合普通单机或 GPU 资源有限的部署
# DOCREADER_MARKITDOWN_MAX_WORKERS=1
# DOCREADER_PDF_RENDER_MAX_WORKERS=1
# DOCREADER_PDF_RENDER_DPI=200
# DOCREADER_PDF_JPEG_QUALITY=90
# 如果使用Weaviate作为向量存储,需要配置以下参数
# 注意:容器内访问请使用 service:port(不要用 localhost,也不要用宿主机映射端口)
# Weaviate HTTP 地址(Docker 内:weaviate:8080;宿主机访问:localhost:9035
# WEAVIATE_HOST=weaviate:8080
# Weaviate gRPC 地址(Docker 内:weaviate:50051;宿主机访问:localhost:50052
# WEAVIATE_GRPC_ADDRESS=weaviate:50051
# Weaviate 架构模式
# WEAVIATE_SCHEME=http
# 是否开启认证(如果你在 weaviate 里启用了 APIKey/OIDC 认证,再把这里设为 true 并配置 WEAVIATE_API_KEY
# WEAVIATE_AUTH_ENABLED=false
# API Key(可选)
# WEAVIATE_API_KEY=your_secret_key
# Weaviate 数据库名称(可选)
#WEAVIATE_COLLECTION=your_weaviate_db_name
# 如果使用 Apache Doris 4.1+ 作为向量存储,需要配置以下参数
# Doris FE 的 MySQL 协议地址(host:port)。容器内推荐用服务名 doris-fe:9030。
# DORIS_ADDR=doris-fe:9030
# Doris FE 的 HTTP 端口,用于 Stream Load 批量字段更新(partial update)。
# DORIS_HTTP_PORT=8030
# Doris 目标数据库名(建库语句:CREATE DATABASE weknora;
# DORIS_DATABASE=weknora
# Doris 用户名(默认 root
# DORIS_USERNAME=root
# Doris 密码(默认空)
# DORIS_PASSWORD=
# Doris 表前缀,对应每维度的物理表 <prefix>_<dim>
# DORIS_TABLE_PREFIX=weknora_embeddings
# Tavily Search API Key(可选,启用 Tavily 网页搜索提供者)
# TAVILY_API_KEY=tvly-your_tavily_api_key
# ----- OIDC Auth -----
# 如果需要启用OIDC登录,设为true并填写后续字段
# OIDC_AUTH_ENABLE=false
# (Optional) 用于OIDC自动发现端点配置
# OIDC_AUTH_ISSUER_URL=http://127.0.0.1:5556/dex
# OIDC_AUTH_DISCOVERY_URL=http://127.0.0.1:5556/dex/.well-known/openid-configuration
# OIDC_AUTH_PROVIDER_DISPLAY_NAME=OIDC
# OIDC_AUTH_CLIENT_ID=client_id_for_oidc_client
# OIDC_AUTH_CLIENT_SECRET=secret_for_oidc_client
# (Optional) OIDC 端点配置, 如果上面的OIDC_AUTH_DISCOVERY_URL填过了,下面的这些可以留空
# OIDC_AUTH_AUTHORIZATION_ENDPOINT=http://127.0.0.1:5556/dex/auth
# OIDC_AUTH_TOKEN_ENDPOINT=http://127.0.0.1:5556/dex/token
# OIDC_AUTH_USER_INFO_ENDPOINT=http://127.0.0.1:5556/dex/userinfo
# OIDC_AUTH_SCOPES="openid profile email"
# 用于OIDC用于信息中提取用户数据
# OIDC_USER_INFO_MAPPING_USER_NAME=name
# OIDC_USER_INFO_MAPPING_EMAIL=email