diff --git a/.env.example b/.env.example index 49a8c170f5bc192213a0b778467b96816a291962..1ccd07c02d2893f54e1f50014fdc0dfa83f35811 100644 --- a/.env.example +++ b/.env.example @@ -12,4 +12,29 @@ RAG_VL_URL= RAG_VL_API_KEY= RAG_VL_MODEL= -RAGFLOW_API_BASE= \ No newline at end of file +RAGFLOW_API_BASE= + +# ======================================== +# Workspace Configuration (通用工作路径配置) +# ======================================== +# 使用相对路径还是 base_url 模式返回图表图片 URL +# - relative: 直接返回图片相对路径,适合本地命令行,如:/deepinsight/charts/image/chart_123.png +# - base_url: 拼接 base_url,适合api模式,如:http://127.0.0.1:8888/api/v1/deepinsight/charts/image/chart_123.png +WORKSPACE_IMAGE_PATH_MODE="relative" + +# 图表图片的 base URL(当 image_path_mode 为 base_url 时使用) +# WORKSPACE_IMAGE_BASE_URL="http://127.0.0.1:8888/api/v1/deepinsight/charts/image" + +# 在 Markdown 中由 DeepInsight 生成的图片等超链接资源使用的 uri 前缀 +# - 对于本地运行模式,总是保持 ../../ +# - 对于使用 S3 兼容的 OBS 且允许匿名 GET 请求,可以将其设置为 OBS 服务相对浏览器的地址 +# - 由于 file_storage.remote_access 未启用,当前暂不支持使用本地存储且需要由 http 访问的场景 +# 其他可选值示例: +# - "http://127.0.0.1:8888/api/v1/deepinsight/res/" (浏览器使用自定义转发服务时) +# - "http://127.0.0.1:9000/" (浏览器直接访问OBS时) +WORKSPACE_RESOURCE_BASE_URI="../../" + + +# ======================================== +# File Storage Configuration (文件存储配置) +# ======================================== diff --git a/Dockerfile b/Dockerfile index dec18657d4cbebed466f3a9a6df1a08de69e943e..f447fdf88ebfabd4149b5a200c8d90e2e9298740 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,6 +22,19 @@ COPY pyproject.toml poetry.lock ./ RUN uv pip install --system -r pyproject.toml --extra-index-url ${PIP_INDEX_URL} +# 设置 HuggingFace 模型缓存目录和镜像站点 +ENV HF_HOME=/deepinsight/models +ENV TRANSFORMERS_CACHE=/deepinsight/models +ENV SENTENCE_TRANSFORMERS_HOME=/deepinsight/models +ENV HF_ENDPOINT=https://hf-mirror.com + +# 复制配置文件和下载脚本 +COPY config.yaml ./ +COPY scripts/download_models.py ./scripts/ + +# 根据 config.yaml 动态下载模型 +RUN python3 scripts/download_models.py + COPY . . RUN pip install --no-deps . diff --git a/config.yaml b/config.yaml index 3ae71a13e0cd2c14cf0f9782533fab3c0db50335..f1d60d88e9b4dca23e28208ca46e76bbf4aa3c65 100644 --- a/config.yaml +++ b/config.yaml @@ -44,18 +44,9 @@ workspace: # 会议洞察报告 PPT 模板路径(支持环境变量展开,如 ${PPT_TEMPLATE_PATH}) conference_ppt_template_path: ./templates/conference_template.pptx chart_image_dir: charts - # 使用相对路径还是 base_url 模式返回图表图片 URL - # - relative: 直接返回图片相对路径,适合本地命令行,如:/deepinsight/charts/image/chart_123.png - # - base_url: 拼接 base_url,适合api模式,如:http://127.0.0.1:8888/api/v1/deepinsight/charts/image/chart_123.png - image_path_mode: base_url - image_base_url: http://127.0.0.1:8888/api/v1/deepinsight/charts/image - # 在 Markdown 中由 DeepInsight 生成的图片等超链接资源使用的 uri 前缀。 - # 对于本地运行模式,总是保持 ../../ - # 对于使用 S3 兼容的 OBS 且允许匿名 GET 请求,可以将其设置为 OBS 服务相对浏览器的地址 - # 由于 file_storage.remote_access 未启用,当前暂不支持使用本地存储且需要由 http 访问的场景 - resource_base_uri: "../../" -# resource_base_uri: "http://127.0.0.1:8888/api/v1/deepinsight/res/". # 浏览器使用自定义转发服务时 -# resource_base_uri: "http://127.0.0.1:9000/". # 浏览器直接访问OBS时 + image_path_mode: ${WORKSPACE_IMAGE_PATH_MODE} + image_base_url: ${WORKSPACE_IMAGE_BASE_URL} + resource_base_uri: ${WORKSPACE_RESOURCE_BASE_URI} # RAG 相关工作路径配置 # 将作为所有 RAG 本地数据的前缀目录,例如: diff --git a/deepinsight/service/rag/backends/llama_index_backend.py b/deepinsight/service/rag/backends/llama_index_backend.py index d5b55c3039fbabaa933458b3fbcf5da0521a4ba9..6febaaa95742992d5dfb22be3471024052c1d403 100644 --- a/deepinsight/service/rag/backends/llama_index_backend.py +++ b/deepinsight/service/rag/backends/llama_index_backend.py @@ -92,10 +92,36 @@ class LlamaIndexBackend(BaseRAGBackend): def _init_global_settings(self) -> None: - Settings.embed_model = HuggingFaceEmbedding( - model_name=self._engine_cfg.embed_model, - device=self._engine_cfg.embed_device, - ) + import logging + logger = logging.getLogger(__name__) + + # Get model name and device + model_name = self._engine_cfg.embed_model + device = self._engine_cfg.embed_device + + # Check for local model cache + cache_dir = os.environ.get('SENTENCE_TRANSFORMERS_HOME') or os.environ.get('HF_HOME') + + try: + logger.info(f"Loading embedding model: {model_name}, device: {device}") + if cache_dir: + logger.info(f"Model cache directory: {cache_dir}") + + Settings.embed_model = HuggingFaceEmbedding( + model_name=model_name, + device=device, + cache_folder=cache_dir, + ) + logger.info(f"Embedding model loaded successfully: {model_name}") + except Exception as e: + logger.error(f"Failed to load embedding model: {model_name}") + logger.error(f"Error details: {str(e)}") + logger.error(f"Please ensure:") + logger.error(f" 1. Network access to HuggingFace (https://huggingface.co)") + logger.error(f" 2. Or model is downloaded to local cache directory: {cache_dir}") + logger.error(f" 3. Or use mirror site by setting HF_ENDPOINT environment variable") + raise + llm_model = self._engine_cfg.llm_model llm_api_key = self._engine_cfg.llm_api_key llm_base_url = self._engine_cfg.llm_base_url diff --git a/scripts/download_models.py b/scripts/download_models.py new file mode 100644 index 0000000000000000000000000000000000000000..e9cee8a4b50692dfe99c0c8a19c3c6f2b7576a87 --- /dev/null +++ b/scripts/download_models.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +""" +从 config.yaml 读取模型配置并下载到本地 +""" +import os +import sys +import yaml + +def download_models(): + # 读取配置文件 (在 Docker 中,config.yaml 在 /deepinsight/ 目录) + config_path = '/deepinsight/config.yaml' + + # 如果不在 Docker 环境,尝试相对路径 + if not os.path.exists(config_path): + config_path = os.path.join(os.path.dirname(__file__), '..', 'config.yaml') + + if not os.path.exists(config_path): + print(f"错误: 找不到配置文件 {config_path}") + sys.exit(1) + + print(f"读取配置文件: {config_path}") + + with open(config_path, 'r', encoding='utf-8') as f: + config = yaml.safe_load(f) + + # 获取模型配置 + rag_config = config.get('rag', {}) + engine_config = rag_config.get('engine', {}) + engine_type = engine_config.get('type', 'llamaindex') + + # 设置缓存目录 + cache_dir = os.environ.get('SENTENCE_TRANSFORMERS_HOME', '/deepinsight/models') + os.makedirs(cache_dir, exist_ok=True) + + print(f"RAG 引擎类型: {engine_type}") + print(f"模型缓存目录: {cache_dir}") + + # 根据引擎类型下载对应的模型 + if engine_type == 'llamaindex': + llamaindex_config = engine_config.get('llamaindex', {}) + embed_model = llamaindex_config.get('embed_model', 'BAAI/bge-small-en-v1.5') + + print(f"\n正在下载 LlamaIndex 嵌入模型: {embed_model}") + + try: + from sentence_transformers import SentenceTransformer + model = SentenceTransformer(embed_model, cache_folder=cache_dir) + print(f"✅ 模型下载成功: {embed_model}") + except Exception as e: + print(f"❌ 模型下载失败: {e}") + sys.exit(1) + + elif engine_type == 'lightrag': + lightrag_config = engine_config.get('lightrag', {}) + embed_model = lightrag_config.get('embedding_model', 'sentence-transformers/all-MiniLM-L6-v2') + + print(f"\n正在下载 LightRAG 嵌入模型: {embed_model}") + + try: + from sentence_transformers import SentenceTransformer + model = SentenceTransformer(embed_model, cache_folder=cache_dir) + print(f"✅ 模型下载成功: {embed_model}") + except Exception as e: + print(f"❌ 模型下载失败: {e}") + sys.exit(1) + else: + print(f"⚠️ 未知的引擎类型: {engine_type}") + + print(f"\n所有模型已下载到: {cache_dir}") + +if __name__ == '__main__': + download_models()