# -*- mode: python ; coding: utf-8 -*- import os from pathlib import Path from PyInstaller.utils.hooks import collect_data_files, collect_submodules, collect_dynamic_libs # 获取项目根目录(spec 文件所在目录) import sys _REPO_DIR = Path(os.getcwd()).resolve() # 根目录执行:pyinstaller --clean main.spec # # --------------------------------------------------------------------------- # 向量「数据库文件」/ 业务数据 —— 明确不打入 onefile EXE # --------------------------------------------------------------------------- # 下列目录为运行时读写或外置分发的数据,禁止加入下方 ``datas``(勿取消注释): # - Schema 侧:环境变量 VECTOR_DB_PATH(默认如 ./data/embeddings/chroma) # - Few-shot 侧:FEWSHOT_CHROMA_PATH(默认如 ./data/embeddings/chroma_fewshot) # 部署:将上述目录放在 exe 同目录旁,或通过 .env 指向可写绝对路径。 # SchemaIndexer 默认使用 PersistentClient(VECTOR_DB_PATH);仅 SCHEMA_INDEXER_EPHEMERAL=true 时为内存索引。 # --------------------------------------------------------------------------- # 可选:仅当需要把 Schema JSON 等打进包时再取消注释(向量库目录仍不要加) datas = [ # ('.env', '.'), # ('data/schemas', 'data/schemas'), # 勿打包 data/embeddings、data/experiences(向量库与样本数据外置) ] # Chroma **Python 包**在 Windows 单文件 exe 下如缺少 native 动态库,可能在初始化时直接退出 # 这里收集的是 chromadb / hnswlib 的 **wheel 内 DLL**,不是用户磁盘上的 Chroma 持久化目录 binaries = [] try: binaries += collect_dynamic_libs("chromadb") except Exception: pass try: binaries += collect_dynamic_libs("hnswlib") except Exception: pass # chromadb 包自带的非 Python 资源(如 migrations),非业务向量库文件 try: datas += collect_data_files("chromadb") except Exception: pass # 收集所有需要的隐藏导入 hiddenimports = [ # Web 框架 'fastapi', 'fastapi.middleware.cors', 'fastapi.responses', 'uvicorn', 'uvicorn.lifespan.on', 'uvicorn.config', 'uvicorn.protocols.http.auto', 'uvicorn.protocols.websockets.auto', 'uvicorn.loops.auto', # Backend 模块(重要!) 'main', # backend/main.py 'backend.main', 'backend.nl_lite_store', 'backend.agents', 'backend.agents.orchestrator', 'backend.agents.schema_linker', 'backend.agents.sql_generator', 'backend.agents.validator', 'backend.config', 'backend.config.prompts', 'backend.config.settings', 'backend.db', 'backend.db.engine', 'backend.db.dbhub_tools', 'backend.db.dbhub_sql_parser', 'backend.db.dbhub_allowed_keywords', 'backend.llm', 'backend.llm.deepseek_client', 'backend.schema', 'backend.schema.manager', 'backend.schema.loader', 'backend.schema.indexer', 'backend.schema.models', 'backend.utils', 'backend.utils.dialog_classifier', 'backend.utils.dialog_context', 'backend.utils.embedding', 'backend.utils.fewshot_selector', 'backend.utils.question_locale', 'backend.utils.sql_parser', 'backend.utils.validators', # 数据库相关 'pymssql', 'sqlalchemy', 'sqlalchemy.dialects.mssql.pymssql', 'sqlalchemy.dialects.mysql', 'sqlalchemy.dialects.postgresql', 'sqlglot', 'sqlglot.dialects', 'sqlparse', # 向量数据库 - 使用 collect_submodules 自动收集所有子模块 # LLM API 'openai', # 数据处理 'numpy', 'jieba', # Pydantic 'pydantic', 'pydantic_settings', 'dotenv', # 工具库 'tenacity', 'structlog', 'tqdm', 'camel_ai', # 标准库中可能被遗漏的 'email.mime.text', 'email.mime.multipart', ] + collect_submodules('chromadb') # 排除不必要的模块以减小体积 excludes = [ 'tkinter', 'matplotlib', 'scipy', 'pandas.tests', 'numpy.testing', 'jupyter', 'notebook', 'IPython', 'pytest', ] a = Analysis( ['api_server.py'], pathex=[str(_REPO_DIR)], binaries=binaries, datas=datas, hiddenimports=hiddenimports, hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=excludes, noarchive=False, optimize=0, ) pyz = PYZ(a.pure) exe = EXE( pyz, a.scripts, a.binaries, a.datas, # 单文件:仅打包 spec 中 datas(chromadb 包资源等),不含业务向量持久化目录 [], name='Backman_Text2SQL_Server', debug=False, bootloader_ignore_signals=False, strip=False, upx=False, # 禁用 UPX,避免兼容性问题 upx_exclude=[], runtime_tmpdir=None, console=True, disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, )