280 lines
11 KiB
Python
280 lines
11 KiB
Python
"""
|
||
项目配置文件
|
||
从.env文件读取配置
|
||
"""
|
||
import os
|
||
from dotenv import load_dotenv
|
||
from contextvars import ContextVar
|
||
from typing import Optional, Dict, Any
|
||
|
||
# 加载.env文件
|
||
load_dotenv()
|
||
|
||
# ==================== 大模型配置 ====================
|
||
LLM_CONFIG = {
|
||
# "model": "Qwen3.5-35B-A3B",
|
||
"model": "46-qwen3.5-35B",
|
||
# "model": "Qwen3-14B",
|
||
"base_url": "http://192.168.0.46:59800/v1",
|
||
"api_key": "gpustack_dee9ca823290886c_5edfc86aeeeceb1e9ee5162941cb2cb5",
|
||
"temperature": float("0.1"),
|
||
"max_tokens": int("9216"),
|
||
"timeout": int("30")
|
||
}
|
||
|
||
# ==================== 嵌入模型配置 ====================
|
||
EMBEDDING_CONFIG = {
|
||
"model": "bge-m3",
|
||
"base_url": "http://192.168.0.46:59700/v1/embeddings",
|
||
"api_key": "gpustack_dee9ca823290886c_5edfc86aeeeceb1e9ee5162941cb2cb5",
|
||
"base_url_v2" : "http://192.168.0.46:59700/v1",
|
||
}
|
||
|
||
|
||
# ==================== 线程安全的请求上下文配置 ====================
|
||
# 使用 contextvars 存储每个请求的用户配置,确保多用户并发时不会相互干扰
|
||
_request_user_config: ContextVar[Optional[Dict[str, str]]] = ContextVar('request_user_config', default=None)
|
||
|
||
# RAG配置的默认值
|
||
_RAG_CONFIG_DEFAULT = {
|
||
"search_endpoint": "http://192.168.0.46:11000/api/v1/knowledge/search/",
|
||
"x-user-id": "1",
|
||
"x-user-name": "testuser",
|
||
"x-role": "admin",
|
||
"kb-id": None,
|
||
"file-id": None
|
||
}
|
||
|
||
class DynamicRAGConfig(dict):
|
||
"""
|
||
动态RAG配置类,支持线程安全的请求级配置
|
||
当访问用户相关配置时,自动从当前请求上下文读取
|
||
其他配置项直接返回默认值
|
||
兼容字典的所有操作方式(如 get(), [], in 等)
|
||
"""
|
||
def __getitem__(self, key: str):
|
||
# 如果是用户相关配置或知识库参数,从当前请求上下文读取
|
||
if key in ["x-user-id", "x-user-name", "x-role", "kb-id", "file-id"]:
|
||
request_config = _request_user_config.get()
|
||
if request_config and key in request_config:
|
||
return request_config[key]
|
||
# 如果没有设置,返回默认值
|
||
return _RAG_CONFIG_DEFAULT[key]
|
||
# 其他配置项直接返回默认值
|
||
return _RAG_CONFIG_DEFAULT.get(key)
|
||
|
||
def get(self, key: str, default=None):
|
||
"""支持 get() 方法"""
|
||
try:
|
||
return self[key]
|
||
except KeyError:
|
||
return default
|
||
|
||
def __contains__(self, key: str):
|
||
"""支持 in 操作符"""
|
||
return key in _RAG_CONFIG_DEFAULT
|
||
|
||
def keys(self):
|
||
"""返回所有键"""
|
||
return _RAG_CONFIG_DEFAULT.keys()
|
||
|
||
def values(self):
|
||
"""返回所有值(动态读取用户配置)"""
|
||
return [self[key] for key in _RAG_CONFIG_DEFAULT.keys()]
|
||
|
||
def items(self):
|
||
"""返回所有键值对(动态读取用户配置)"""
|
||
return [(key, self[key]) for key in _RAG_CONFIG_DEFAULT.keys()]
|
||
|
||
# ==================== RAG服务配置 ====================
|
||
# 使用动态配置类,支持多用户并发时自动读取各自的配置
|
||
RAG_CONFIG = DynamicRAGConfig()
|
||
|
||
# ==================== Wiki pointer layer config ====================
|
||
_HTKNOW_BASE_URL_DEFAULT = (
|
||
_RAG_CONFIG_DEFAULT.get("search_endpoint", "").split("/api/v1/knowledge/search")[0].rstrip("/")
|
||
or "http://htknow:8080"
|
||
)
|
||
WIKI_CONFIG = {
|
||
"enabled": os.getenv("WIKI_ENABLED", "true").lower() == "true",
|
||
"htknow_base_url": os.getenv("HTKNOW_BASE_URL", _HTKNOW_BASE_URL_DEFAULT).rstrip("/"),
|
||
"default_user_id": os.getenv("WIKI_DEFAULT_USER_ID", "1"),
|
||
"default_user_name": os.getenv("WIKI_DEFAULT_USER_NAME", "testuser"),
|
||
"default_role": os.getenv("WIKI_DEFAULT_ROLE", "admin"),
|
||
"default_sync_limit": int(os.getenv("WIKI_DEFAULT_SYNC_LIMIT", "20")),
|
||
"max_slices_per_file": int(os.getenv("WIKI_MAX_SLICES_PER_FILE", "300")),
|
||
"max_pages_per_file": int(os.getenv("WIKI_MAX_PAGES_PER_FILE", "25")),
|
||
"llm_summary_enabled": os.getenv("WIKI_LLM_SUMMARY_ENABLED", "true").lower() == "true",
|
||
"embedding_enabled": os.getenv("WIKI_EMBEDDING_ENABLED", "false").lower() == "true",
|
||
"embedding_batch_size": int(os.getenv("WIKI_EMBEDDING_BATCH_SIZE", "16")),
|
||
"embedding_vector_dim": int(os.getenv("WIKI_EMBEDDING_VECTOR_DIM", "1024")),
|
||
"embedding_text_max_chars": int(os.getenv("WIKI_EMBEDDING_TEXT_MAX_CHARS", "2200")),
|
||
"vector_search_top_k": int(os.getenv("WIKI_VECTOR_SEARCH_TOP_K", "32")),
|
||
"slice_text_search_top_k": int(os.getenv("WIKI_SLICE_TEXT_SEARCH_TOP_K", "32")),
|
||
"page_search_top_k": int(os.getenv("WIKI_PAGE_SEARCH_TOP_K", "12")),
|
||
"vector_min_score": float(os.getenv("WIKI_VECTOR_MIN_SCORE", "0.2")),
|
||
"max_vector_candidates": int(os.getenv("WIKI_MAX_VECTOR_CANDIDATES", "50000")),
|
||
"rrf_k": int(os.getenv("WIKI_RRF_K", "60")),
|
||
"evidence_slices_per_page": int(os.getenv("WIKI_EVIDENCE_SLICES_PER_PAGE", "6")),
|
||
"language": os.getenv("WIKI_LANGUAGE", "Chinese"),
|
||
"extraction_granularity": os.getenv("WIKI_EXTRACTION_GRANULARITY", "standard"),
|
||
"full_content_max_chars": int(os.getenv("WIKI_FULL_CONTENT_MAX_CHARS", "120000")),
|
||
"citation_concurrency": int(os.getenv("WIKI_CITATION_CONCURRENCY", "3")),
|
||
"reduce_concurrency": int(os.getenv("WIKI_REDUCE_CONCURRENCY", "3")),
|
||
"llm_concurrency": int(os.getenv("WIKI_LLM_CONCURRENCY", "4")),
|
||
"llm_cache_enabled": os.getenv("WIKI_LLM_CACHE_ENABLED", "true").lower() == "true",
|
||
"llm_cache_ttl_seconds": int(os.getenv("WIKI_LLM_CACHE_TTL_SECONDS", str(7 * 24 * 3600))),
|
||
"llm_retry_count": int(os.getenv("WIKI_LLM_RETRY_COUNT", "2")),
|
||
"structured_template_enabled": os.getenv("WIKI_STRUCTURED_TEMPLATE_ENABLED", "true").lower() == "true",
|
||
"stage_progress_enabled": os.getenv("WIKI_STAGE_PROGRESS_ENABLED", "true").lower() == "true",
|
||
"finalize_enabled": os.getenv("WIKI_FINALIZE_ENABLED", "true").lower() == "true",
|
||
"finalize_debounce_seconds": int(os.getenv("WIKI_FINALIZE_DEBOUNCE_SECONDS", "20")),
|
||
"slug_lock_ttl_seconds": int(os.getenv("WIKI_SLUG_LOCK_TTL_SECONDS", "600")),
|
||
"queue_enabled": os.getenv("WIKI_QUEUE_ENABLED", "true").lower() == "true",
|
||
"queue_worker_concurrency": int(os.getenv("WIKI_QUEUE_WORKER_CONCURRENCY", "2")),
|
||
"queue_per_kb_concurrency": int(os.getenv("WIKI_QUEUE_PER_KB_CONCURRENCY", "2")),
|
||
"queue_claim_stale_seconds": int(os.getenv("WIKI_QUEUE_CLAIM_STALE_SECONDS", "1800")),
|
||
"queue_max_retries": int(os.getenv("WIKI_QUEUE_MAX_RETRIES", "3")),
|
||
}
|
||
|
||
# ==================== Rerank 服务配置 ====================
|
||
RERANK_CONFIG = {
|
||
"enabled": os.getenv("RERANK_ENABLED", "true").lower() == "true",
|
||
"endpoint": os.getenv("RERANK_ENDPOINT", "http://192.168.0.46:59600/v1/rerank"),
|
||
"model": os.getenv("RERANK_MODEL", "bge-rerank"),
|
||
"timeout": float(os.getenv("RERANK_TIMEOUT", "30")),
|
||
"max_candidates": int(os.getenv("RERANK_MAX_CANDIDATES", "24")),
|
||
"top_k": int(os.getenv("RERANK_TOP_K", "10")),
|
||
}
|
||
|
||
def set_request_user_config(x_user_id: Optional[str] = None,
|
||
x_user_name: Optional[str] = None,
|
||
x_role: Optional[str] = None,
|
||
text_kb_id: Optional[str] = None,
|
||
text_file_id: Optional[str] = None):
|
||
"""
|
||
设置当前请求的用户配置和知识库参数(线程安全)
|
||
|
||
Args:
|
||
x_user_id: 用户ID
|
||
x_user_name: 用户名称
|
||
x_role: 角色
|
||
text_kb_id: 文本检索知识库ID
|
||
text_file_id: 文本检索文件ID
|
||
"""
|
||
config = {}
|
||
if x_user_id is not None:
|
||
config["x-user-id"] = x_user_id
|
||
if x_user_name is not None:
|
||
config["x-user-name"] = x_user_name
|
||
if x_role is not None:
|
||
config["x-role"] = x_role
|
||
# 仅当非空字符串时才设置,空字符串时不传入 RAG 接口
|
||
if text_kb_id is not None and str(text_kb_id).strip():
|
||
config["kb-id"] = str(text_kb_id).strip()
|
||
if text_file_id is not None and str(text_file_id).strip():
|
||
config["file-id"] = str(text_file_id).strip()
|
||
_request_user_config.set(config if config else None)
|
||
|
||
# ==================== 图谱检索服务配置 ====================
|
||
GRAPH_SEARCH_CONFIG = {
|
||
"search_endpoint": "http://192.168.0.46:59085/search_graph",
|
||
"graph_timeout": float("30.0"),
|
||
"default_top_k": int("10"),
|
||
"operation_search_endpoint": "http://192.168.0.46:59085/operation_graph_search"
|
||
}
|
||
|
||
# ==================== 设备到系统检索服务配置 ====================
|
||
DEVICE_SYSTEM_CONFIG = {
|
||
"endpoint": "http://192.168.0.46:59085/device_to_system",
|
||
"timeout": float("30.0"),
|
||
"default_min_hops": int("2"),
|
||
"default_max_hops": int("8"),
|
||
"default_top_k": int("10")
|
||
}
|
||
|
||
# ==================== 图册检索服务配置 ====================
|
||
ATLAS_CONFIG = {
|
||
"endpoint": "http://192.168.0.46:59085/atlas_retrieval",
|
||
"timeout": float("30.0"),
|
||
"default_top_k": int("10")
|
||
}
|
||
|
||
# ==================== 工作流配置 ====================
|
||
WORKFLOW_CONFIG = {
|
||
"max_retry_count": int("2"), # 最大重试次数
|
||
"image_clarity_threshold": float("0.7"), # 图片清晰度阈值
|
||
"default_timeout": int("30") # 默认超时时间(秒)
|
||
}
|
||
|
||
# ==================== 服务器配置 ====================
|
||
SERVER_CONFIG = {
|
||
"host": "192.168.0.46",
|
||
"port": "59088",
|
||
"base_url": "http://192.168.0.46:59088"
|
||
}
|
||
|
||
# ==================== ASR服务配置 ====================
|
||
ASR_CONFIG = {
|
||
"api_base": "http://192.168.0.46:59900/v1",
|
||
"model": "base",
|
||
"language": "zh",
|
||
"timeout": int("30")
|
||
}
|
||
|
||
# ==================== VLM服务配置 ====================
|
||
VLM_CONFIG = {
|
||
"api_base" : "http://192.168.0.46:59801/v1",
|
||
"model" : "Qwen3-VL-8B"
|
||
}
|
||
|
||
# ==================== Neo4J配置 ====================
|
||
NEO4J_CONFIG = {
|
||
"uri": "neo4j://192.168.0.46:57687",
|
||
"user": "neo4j",
|
||
"password": "zdht123@"
|
||
}
|
||
|
||
# ==================== 知识库匹配配置 ====================
|
||
KB_TREE_CONFIG = {
|
||
"url": "http://192.168.0.46:11000/api/v1/knowledge/knowledge_base/tree"
|
||
}
|
||
|
||
# ==================== 维修反馈统计配置 ====================
|
||
REPAIR_FEEDBACK_CONFIG = {
|
||
"url": "http://192.168.0.46:22000",
|
||
"email": "15088888888@163.com",
|
||
"password": "11223344"
|
||
}
|
||
|
||
# ==================== 数据库配置 ====================
|
||
POSTGRES_CONNECTION_STRING = "postgresql://postgres:password@192.168.0.46:5432/an_webui"
|
||
#POSTGRES_CONNECTION_STRING = "postgresql+psycopg://postgres:password@192.168.0.46:5432/an_webui"
|
||
POSTGRES_SQLALCHEMY_URL = "postgresql+psycopg://postgres:password@192.168.0.46:5432/an_webui"
|
||
|
||
|
||
# ==================== 索引配置 ====================
|
||
INDEX_CONFIG = {
|
||
"NAME_PROPERTY" : "名称",
|
||
"FULLTEXT_PROPERTY" :"fulltext",
|
||
"EMBEDDING_PROPERTY" : "embedding",
|
||
"SEARCH_LABEL" : "Searchable",
|
||
"VECTOR_INDEX_NAME" : "global_searchable_embedding",
|
||
"FULLTEXT_INDEX_NAME" : "global_searchable_content_search"
|
||
}
|
||
|
||
# ==================== sql表格字段与neo4j节点映射 ====================
|
||
MAP_INS={
|
||
"故障模式" : "fault",
|
||
"系统" : "system_name",
|
||
"设备" : "device_name",
|
||
"舷号" : "ship_number",
|
||
}
|
||
|
||
# ==================== neo4j配置 ====================
|
||
NEO4J_CONFIG = {
|
||
"uri": "neo4j://192.168.0.46:57687",
|
||
"user": "neo4j",
|
||
"password": "zdht123@"
|
||
}
|