增加exe打包配置
This commit is contained in:
Generated
+8
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
@@ -20,7 +20,7 @@ class SchemaIndexer:
|
||||
功能:
|
||||
1. 为表结构构建向量索引
|
||||
2. 基于问题的表检索
|
||||
3. Chroma 使用内存模式(EphemeralClient),进程退出后不保留;``persist_dir`` 仅作配置/统计引用
|
||||
3. Chroma 使用持久化(PersistentClient),向量与元数据写入 ``persist_dir``,进程重启后可复用
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@@ -34,15 +34,17 @@ class SchemaIndexer:
|
||||
|
||||
Args:
|
||||
embedder: Embedding模型实例
|
||||
persist_dir: 历史配置中的向量库路径(仅展示与统计,不落盘)
|
||||
persist_dir: Chroma 持久化根目录(磁盘路径)
|
||||
collection_name: 集合名称
|
||||
"""
|
||||
self.embedder = embedder
|
||||
self.persist_dir = Path(persist_dir)
|
||||
self.persist_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.collection_name = collection_name
|
||||
|
||||
# 内存 Chroma:不落盘,每次进程需重新 build_index
|
||||
self.client = chromadb.EphemeralClient(
|
||||
# 持久化 Chroma:数据落盘至 persist_dir
|
||||
self.client = chromadb.PersistentClient(
|
||||
path=str(self.persist_dir),
|
||||
settings=ChromaSettings(anonymized_telemetry=False),
|
||||
)
|
||||
|
||||
@@ -53,8 +55,8 @@ class SchemaIndexer:
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"[OK] 初始化SchemaIndexer(Chroma内存): collection={self.collection_name}, "
|
||||
f"配置路径引用={self.persist_dir}"
|
||||
f"[OK] 初始化SchemaIndexer(Chroma持久化): collection={self.collection_name}, "
|
||||
f"path={self.persist_dir}"
|
||||
)
|
||||
|
||||
def build_index(
|
||||
@@ -250,5 +252,5 @@ class SchemaIndexer:
|
||||
"total_columns": total_columns,
|
||||
"avg_columns": total_columns / count if count > 0 else 0,
|
||||
"persist_dir": str(self.persist_dir),
|
||||
"chroma_mode": "memory",
|
||||
"chroma_mode": "persistent",
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -8,6 +8,35 @@ from PyInstaller.utils.hooks import collect_data_files, collect_submodules, coll
|
||||
import sys
|
||||
_REPO_DIR = Path(os.getcwd()).resolve()
|
||||
|
||||
|
||||
def _strip_msvc_runtime_binaries(bin_list):
|
||||
"""
|
||||
从 ``collect_dynamic_libs`` 等额外收集的 binaries 中移除 MSVC 运行库 DLL。
|
||||
|
||||
chromadb / hnswlib 等 wheel 常自带 ``MSVCP140.dll`` 等;与 PyInstaller 已为
|
||||
``python.exe`` 解析到的 CRT 一并打入单文件包时,易在运行期混用多份 CRT
|
||||
导致 ``MSVCP140.dll`` 内 ``0xc0000005``。统一依赖解释器自带的 CRT 集更安全。
|
||||
"""
|
||||
skip = frozenset({
|
||||
'msvcp140.dll',
|
||||
'msvcp140_1.dll',
|
||||
'msvcp140_2.dll',
|
||||
'msvcp140_atomic_wait.dll',
|
||||
'msvcp140_codecvt_ids.dll',
|
||||
'vcruntime140.dll',
|
||||
'vcruntime140_1.dll',
|
||||
'concrt140.dll',
|
||||
})
|
||||
out = []
|
||||
for item in bin_list:
|
||||
dest = item[0]
|
||||
base = Path(dest).name.lower()
|
||||
if base in skip:
|
||||
continue
|
||||
out.append(item)
|
||||
return out
|
||||
|
||||
|
||||
# 根目录执行:pyinstaller --clean main.spec
|
||||
# 收集配置文件夹和数据文件
|
||||
datas = [
|
||||
@@ -36,6 +65,62 @@ try:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
binaries = _strip_msvc_runtime_binaries(binaries)
|
||||
|
||||
|
||||
def _dedupe_msvc_runtime_in_analysis_binaries(toc):
|
||||
"""
|
||||
对 ``Analysis`` 产出的 ``a.binaries`` 去重:同名 MSVC 运行库 DLL 只保留一份。
|
||||
|
||||
PyInstaller 会从 Python 安装目录、numpy、torch、chromadb 等多个依赖各自打入
|
||||
同名 ``MSVCP140.dll`` 等;单文件解压到 ``_MEI*`` 后若出现多份或加载顺序混乱,
|
||||
易在 ``MSVCP140.dll`` 内触发 ``0xc0000005``。优先保留 **源路径位于**
|
||||
``sys.base_prefix`` 下的条目(与解释器主 CRT 一致)。
|
||||
"""
|
||||
vc_names = frozenset({
|
||||
'msvcp140.dll',
|
||||
'msvcp140_1.dll',
|
||||
'msvcp140_2.dll',
|
||||
'msvcp140_atomic_wait.dll',
|
||||
'msvcp140_codecvt_ids.dll',
|
||||
'vcruntime140.dll',
|
||||
'vcruntime140_1.dll',
|
||||
'concrt140.dll',
|
||||
})
|
||||
try:
|
||||
base_root = str(Path(sys.base_prefix).resolve()).lower()
|
||||
except OSError:
|
||||
base_root = str(Path(sys.base_prefix)).lower()
|
||||
|
||||
rest = []
|
||||
vc_groups = {}
|
||||
for item in toc:
|
||||
dest = item[0]
|
||||
bname = Path(dest).name.lower()
|
||||
if bname not in vc_names:
|
||||
rest.append(item)
|
||||
continue
|
||||
vc_groups.setdefault(bname, []).append(item)
|
||||
|
||||
picked = []
|
||||
for bname, items in vc_groups.items():
|
||||
if len(items) == 1:
|
||||
picked.append(items[0])
|
||||
continue
|
||||
|
||||
def _score(it):
|
||||
try:
|
||||
sp = str(Path(it[1]).resolve()).lower()
|
||||
except OSError:
|
||||
sp = str(it[1]).lower()
|
||||
under = 0 if sp.startswith(base_root) else 1
|
||||
return (under, len(sp))
|
||||
|
||||
items_sorted = sorted(items, key=_score)
|
||||
picked.append(items_sorted[0])
|
||||
|
||||
return rest + picked
|
||||
|
||||
# 收集所有需要的隐藏导入
|
||||
hiddenimports = [
|
||||
# Web 框架
|
||||
@@ -48,7 +133,7 @@ hiddenimports = [
|
||||
'uvicorn.protocols.http.auto',
|
||||
'uvicorn.protocols.websockets.auto',
|
||||
'uvicorn.loops.auto',
|
||||
|
||||
|
||||
# Backend 模块(重要!)
|
||||
'main', # backend/main.py
|
||||
'backend.main',
|
||||
@@ -81,7 +166,7 @@ hiddenimports = [
|
||||
'backend.utils.question_locale',
|
||||
'backend.utils.sql_parser',
|
||||
'backend.utils.validators',
|
||||
|
||||
|
||||
# 数据库相关
|
||||
'pymssql',
|
||||
'sqlalchemy',
|
||||
@@ -91,27 +176,32 @@ hiddenimports = [
|
||||
'sqlglot',
|
||||
'sqlglot.dialects',
|
||||
'sqlparse',
|
||||
|
||||
|
||||
# 向量数据库 - 使用 collect_submodules 自动收集所有子模块
|
||||
|
||||
# Embedding 相关
|
||||
'sentencepiece',
|
||||
'accelerate',
|
||||
'safetensors',
|
||||
|
||||
# LLM API
|
||||
'openai',
|
||||
|
||||
|
||||
# 数据处理
|
||||
'numpy',
|
||||
'jieba',
|
||||
|
||||
|
||||
# Pydantic
|
||||
'pydantic',
|
||||
'pydantic_settings',
|
||||
'dotenv',
|
||||
|
||||
|
||||
# 工具库
|
||||
'tenacity',
|
||||
'structlog',
|
||||
'tqdm',
|
||||
'camel_ai',
|
||||
|
||||
|
||||
# 标准库中可能被遗漏的
|
||||
'email.mime.text',
|
||||
'email.mime.multipart',
|
||||
@@ -137,11 +227,15 @@ a = Analysis(
|
||||
hiddenimports=hiddenimports,
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
runtime_hooks=[str(_REPO_DIR / 'packaging' / 'pyi_rth_crt_path.py')],
|
||||
excludes=excludes,
|
||||
noarchive=False,
|
||||
optimize=0,
|
||||
)
|
||||
|
||||
# 去掉 Analysis 自动收集到的重复 MSVC 运行库(比仅过滤手动 binaries 更关键)
|
||||
a.binaries = _dedupe_msvc_runtime_in_analysis_binaries(list(a.binaries))
|
||||
|
||||
pyz = PYZ(a.pure)
|
||||
|
||||
exe = EXE(
|
||||
|
||||
Reference in New Issue
Block a user