增加exe打包配置
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
# G3SB Backman Windows Service Installation Script
|
||||
# Run as Administrator
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$Action = "install"
|
||||
)
|
||||
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
if (-not $isAdmin) {
|
||||
Write-Host "ERROR: Administrator privileges required" -ForegroundColor Red
|
||||
Write-Host "Please right-click and select 'Run as administrator'" -ForegroundColor Yellow
|
||||
Start-Sleep -Seconds 5
|
||||
exit 1
|
||||
}
|
||||
|
||||
$serviceName = "Backman_Text2sql"
|
||||
$serviceDisplayName = "Backman Text2SQL Service"
|
||||
$serviceDescription = "Backman Text2SQL AI Backend Service"
|
||||
|
||||
$scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
# 单文件模式:exe 在 deploy 同级目录
|
||||
$exePath = Join-Path $scriptPath "Backman_Text2SQL_Server.exe"
|
||||
|
||||
if (-not (Test-Path $exePath)) {
|
||||
Write-Host "ERROR: Backman_Text2SQL_Server.exe not found" -ForegroundColor Red
|
||||
Write-Host "Path: $exePath" -ForegroundColor Yellow
|
||||
Write-Host "Please run 'pyinstaller --clean main.spec' in project root first" -ForegroundColor Yellow
|
||||
Start-Sleep -Seconds 5
|
||||
exit 1
|
||||
}
|
||||
|
||||
$NSSM_URL = "https://nssm.cc/release/nssm-2.24.zip"
|
||||
$nssmPath = Join-Path $scriptPath "nssm.exe"
|
||||
|
||||
function Get-NSSM {
|
||||
if (-not (Test-Path $nssmPath)) {
|
||||
Write-Host "Downloading NSSM..." -ForegroundColor Cyan
|
||||
$zipPath = Join-Path $env:TEMP "nssm.zip"
|
||||
try {
|
||||
Invoke-WebRequest -Uri $NSSM_URL -OutFile $zipPath -UseBasicParsing
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
[System.IO.Compression.ZipFile]::ExtractToDirectory($zipPath, $env:TEMP)
|
||||
$nssmSource = Get-ChildItem -Path $env:TEMP -Recurse -Filter "nssm.exe" | Where-Object { $_.FullName -like "*win64*" } | Select-Object -First 1
|
||||
if ($nssmSource) {
|
||||
Copy-Item $nssmSource.FullName -Destination $nssmPath -Force
|
||||
Write-Host "NSSM downloaded to: $nssmPath" -ForegroundColor Green
|
||||
} else {
|
||||
throw "nssm.exe not found"
|
||||
}
|
||||
Remove-Item $zipPath -Force
|
||||
Remove-Item (Join-Path $env:TEMP "nssm-2.24") -Recurse -Force
|
||||
}
|
||||
catch {
|
||||
Write-Host "Failed to download NSSM: $_" -ForegroundColor Red
|
||||
Write-Host "Manual: Visit https://nssm.cc/download and place nssm.exe in this directory" -ForegroundColor Yellow
|
||||
Start-Sleep -Seconds 5
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Write-Host "NSSM exists: $nssmPath" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
|
||||
function Install-Service {
|
||||
Write-Host "`n=================================" -ForegroundColor Cyan
|
||||
Write-Host "Installing G3SB Backman Service" -ForegroundColor Cyan
|
||||
Write-Host "=================================`n" -ForegroundColor Cyan
|
||||
|
||||
Get-NSSM
|
||||
$workDir = $scriptPath
|
||||
|
||||
Write-Host "Creating service: $serviceName" -ForegroundColor Cyan
|
||||
& $nssmPath install $serviceName "$exePath"
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
& $nssmPath set $serviceName DisplayName $serviceDisplayName
|
||||
& $nssmPath set $serviceName Description $serviceDescription
|
||||
& $nssmPath set $serviceName Start SERVICE_AUTO_START
|
||||
& $nssmPath set $serviceName AppDirectory $workDir
|
||||
|
||||
$logDir = Join-Path $workDir "logs"
|
||||
if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null }
|
||||
$stdoutLog = Join-Path $logDir "service_stdout.log"
|
||||
$stderrLog = Join-Path $logDir "service_stderr.log"
|
||||
& $nssmPath set $serviceName AppStdout $stdoutLog
|
||||
& $nssmPath set $serviceName AppStderr $stderrLog
|
||||
& $nssmPath set $serviceName AppRestartDelay 1000
|
||||
& $nssmPath set $serviceName AppExit Default Restart
|
||||
|
||||
Write-Host "\n[OK] Service installed successfully!" -ForegroundColor Green
|
||||
Write-Host " Service Name: $serviceName" -ForegroundColor White
|
||||
Write-Host " Display Name: $serviceDisplayName" -ForegroundColor White
|
||||
Write-Host " Executable: $exePath" -ForegroundColor White
|
||||
|
||||
$response = Read-Host "`nStart service now? (Y/n)"
|
||||
if ([string]::IsNullOrWhiteSpace($response) -or $response -match '^[Yy]$') {
|
||||
Start-ServiceAction
|
||||
}
|
||||
|
||||
Write-Host "`nTips:" -ForegroundColor Yellow
|
||||
Write-Host " Status: .\install_service.ps1 status" -ForegroundColor White
|
||||
Write-Host " Stop: .\install_service.ps1 stop" -ForegroundColor White
|
||||
Write-Host " Start: .\install_service.ps1 start" -ForegroundColor White
|
||||
Write-Host " Uninstall: .\install_service.ps1 uninstall" -ForegroundColor White
|
||||
} else {
|
||||
Write-Host "`n[FAIL] Service installation failed!" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
function Uninstall-Service {
|
||||
Write-Host "`n=================================" -ForegroundColor Cyan
|
||||
Write-Host "Uninstalling G3SB Backman Service" -ForegroundColor Cyan
|
||||
Write-Host "=================================`n" -ForegroundColor Cyan
|
||||
|
||||
Stop-ServiceAction
|
||||
Get-NSSM
|
||||
|
||||
$confirm = Read-Host "Confirm uninstall? (y/N)"
|
||||
if ($confirm -notmatch '^[Yy]$') {
|
||||
Write-Host "Cancelled" -ForegroundColor Yellow
|
||||
return
|
||||
}
|
||||
|
||||
& $nssmPath remove $serviceName confirm
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "`n[OK] Service uninstalled!" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "`n[FAIL] Uninstall failed!" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
function Start-ServiceAction {
|
||||
Write-Host "`nStarting service $serviceName ..." -ForegroundColor Cyan
|
||||
try {
|
||||
Start-Service -Name $serviceName -ErrorAction Stop
|
||||
Write-Host "[OK] Service started" -ForegroundColor Green
|
||||
Start-Sleep -Seconds 3
|
||||
$status = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
|
||||
if ($status.Status -eq 'Running') {
|
||||
Write-Host "[OK] Service running" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[WARN] Service status: $($status.Status)" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Host "[FAIL] Failed to start: $_" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
function Stop-ServiceAction {
|
||||
Write-Host "`nStopping service $serviceName ..." -ForegroundColor Cyan
|
||||
try {
|
||||
Stop-Service -Name $serviceName -Force -ErrorAction Stop
|
||||
Write-Host "[OK] Service stopped" -ForegroundColor Green
|
||||
}
|
||||
catch {
|
||||
Write-Host "[WARN] Service not running or failed to stop: $_" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ServiceStatus {
|
||||
Write-Host "`n=================================" -ForegroundColor Cyan
|
||||
Write-Host "Service Status" -ForegroundColor Cyan
|
||||
Write-Host "=================================`n" -ForegroundColor Cyan
|
||||
|
||||
try {
|
||||
$service = Get-Service -Name $serviceName -ErrorAction Stop
|
||||
Write-Host "Service Name: $($service.Name)" -ForegroundColor White
|
||||
Write-Host "Display Name: $($service.DisplayName)" -ForegroundColor White
|
||||
Write-Host "Status: $($service.Status)" -ForegroundColor $(if ($service.Status -eq 'Running') { 'Green' } else { 'Yellow' })
|
||||
Write-Host "Start Type: $($service.StartType)" -ForegroundColor White
|
||||
|
||||
if ($service.Status -eq 'Running') {
|
||||
Write-Host "`n[OK] Service is running" -ForegroundColor Green
|
||||
Write-Host "URL: http://localhost:8041" -ForegroundColor Cyan
|
||||
} else {
|
||||
Write-Host "`n[WARN] Service is not running" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Host "[FAIL] Service not installed" -ForegroundColor Red
|
||||
Write-Host "Install: .\install_service.ps1 install" -ForegroundColor Yellow
|
||||
}
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
Write-Host "`nG3SB Backman Service Manager" -ForegroundColor Cyan
|
||||
Write-Host "============================`n" -ForegroundColor Cyan
|
||||
|
||||
switch ($Action.ToLower()) {
|
||||
"install" { Install-Service }
|
||||
"uninstall" { Uninstall-Service }
|
||||
"start" { Start-ServiceAction }
|
||||
"stop" { Stop-ServiceAction }
|
||||
"status" { Get-ServiceStatus }
|
||||
"restart" { Stop-ServiceAction; Start-Sleep -Seconds 2; Start-ServiceAction }
|
||||
default {
|
||||
Write-Host "Usage: .\install_service.ps1 [action]" -ForegroundColor Yellow
|
||||
Write-Host "Actions: install, uninstall, start, stop, restart, status" -ForegroundColor White
|
||||
}
|
||||
}
|
||||
Write-Host ""
|
||||
@@ -0,0 +1,21 @@
|
||||
以**管理员身份**打开 PowerShell,然后执行:
|
||||
|
||||
```powershell
|
||||
# 安装服务
|
||||
powershell.exe -ExecutionPolicy Bypass -File .\install_service.ps1 install
|
||||
|
||||
# 查看服务状态
|
||||
powershell.exe -ExecutionPolicy Bypass -File .\install_service.ps1 status
|
||||
|
||||
# 启动服务
|
||||
powershell.exe -ExecutionPolicy Bypass -File .\install_service.ps1 start
|
||||
|
||||
# 停止服务
|
||||
powershell.exe -ExecutionPolicy Bypass -File .\install_service.ps1 stop
|
||||
|
||||
# 重启服务
|
||||
powershell.exe -ExecutionPolicy Bypass -File .\install_service.ps1 restart
|
||||
|
||||
# 卸载服务
|
||||
powershell.exe -ExecutionPolicy Bypass -File .\install_service.ps1 uninstall
|
||||
```
|
||||
@@ -0,0 +1,152 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from PyInstaller.utils.hooks import collect_data_files, collect_submodules
|
||||
|
||||
# 获取项目根目录(spec 文件所在目录)
|
||||
import sys
|
||||
_REPO_DIR = Path(os.getcwd()).resolve()
|
||||
|
||||
# 根目录执行:pyinstaller --clean main.spec
|
||||
# 收集配置文件夹和数据文件
|
||||
datas = [
|
||||
# 所有数据文件都不打包,从外部读取
|
||||
# ('.env', '.'),
|
||||
# ('data/schemas', 'data/schemas'),
|
||||
# ('data/embeddings', 'data/embeddings'),
|
||||
# ('data/experiences', 'data/experiences'),
|
||||
]
|
||||
|
||||
# 收集所有需要的隐藏导入
|
||||
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.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 自动收集所有子模块
|
||||
|
||||
# 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',
|
||||
] + 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=[],
|
||||
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, # 单文件模式:将数据文件打包进 exe
|
||||
[],
|
||||
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,
|
||||
)
|
||||
Reference in New Issue
Block a user