Files
Cyrene_v2/scripts/embed.bat
AskaEth cc566354fa
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
chore(scripts): embedding 服务改回只绑 127.0.0.1(0.0.0.0 实测无益且有暴露面)
主人 2026-10-07 最终口径:改回 127.0.0.1。

一个来回的结论登记进脚本注释,免得以后有人再试一遍:
- 0.0.0.0 是 IPv4 通配、不覆盖 IPv6(实测 netstat 只有
  TCP 0.0.0.0:11434 LISTENING,http://[::1]:11434 仍失败)
  ⇒ 它修不了「客户端把 localhost 解析成 ::1 而卡住」那个故障
- llama-server 没有鉴权 ⇒ 绑 0.0.0.0 等于向整个局域网暴露本机 embedding 算力
- EMBED_HOST 保留为可配置项(默认 127.0.0.1),将来真需要对外再打开
2026-10-07 16:16:07 +08:00

146 lines
5.6 KiB
Batchfile

@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem ============================================================
rem Cyrene v2 local embedding server (llama.cpp) - Windows
rem
rem Usage:
rem scripts\embed.bat start (default)
rem scripts\embed.bat start start llama-server on :11434
rem scripts\embed.bat stop stop llama-server
rem scripts\embed.bat status show status
rem
rem Serves an OpenAI-compatible embeddings endpoint:
rem POST http://127.0.0.1:<port>/v1/embeddings
rem backed by Qwen3-Embedding-0.6B Q8_0 (dim 1024, CPU) - the model
rem .env EMBEDDING_API_URL / EMBEDDING_MODEL are expected to point at.
rem Cyrene only takes the real semantic path when this is up; otherwise it
rem logs "vector index unavailable, falling back to in-memory semantic".
rem
rem The vector index itself lives in PostgreSQL + pgvector (DB_PG_URL):
rem docker compose -f docker-compose.dev.yml up -d pg
rem
rem Overridable via environment:
rem LLAMA_DIR (default %USERPROFILE%\apps\llama.cpp)
rem EMBED_MODEL (default %USERPROFILE%\.models\Qwen3-Embedding-0.6B-Q8_0.gguf)
rem EMBED_PORT (default 11434)
rem Logs: %USERPROFILE%\llama.log (+ llama.stdout.log)
rem
rem ASCII-only + CRLF on purpose (cmd parsing is codepage/line-ending
rem sensitive); Windows tools are called by absolute System32 path so an
rem MSYS/MinGW PATH (Git Bash) cannot shadow them.
rem ============================================================
set "SYS=%SystemRoot%\System32"
if not defined LLAMA_DIR set "LLAMA_DIR=%USERPROFILE%\apps\llama.cpp"
if not defined EMBED_MODEL set "EMBED_MODEL=%USERPROFILE%\.models\Qwen3-Embedding-0.6B-Q8_0.gguf"
if not defined EMBED_PORT set "EMBED_PORT=11434"
rem EMBED_HOST: which interface llama-server binds to. Default 127.0.0.1
rem (loopback only). History, so nobody repeats the experiment:
rem 2026-10-07 the owner briefly asked for 0.0.0.0; it was measured and then
rem reverted, because (a) 0.0.0.0 is an IPv4 wildcard and does NOT cover
rem IPv6 -- with --host 0.0.0.0, netstat showed only "TCP 0.0.0.0:11434
rem LISTENING" (no IPv6 entry) and http://[::1]:11434 still failed, so it
rem did NOT fix the client-side hang it was meant to fix; and (b)
rem llama-server has NO auth, so 0.0.0.0 exposes this machine's embedding
rem compute to every device on the LAN.
rem Clients must dial 127.0.0.1 (see internal/runtime/embedding).
if not defined EMBED_HOST set "EMBED_HOST=127.0.0.1"
set "SERVER=%LLAMA_DIR%\llama-server.exe"
set "LOG_FILE=%USERPROFILE%\llama.log"
set "STDOUT_FILE=%USERPROFILE%\llama.stdout.log"
set "HEALTH_URL=http://127.0.0.1:%EMBED_PORT%/health"
set "ACTION=%~1"
if "%ACTION%"=="" set "ACTION=start"
if /i "%ACTION%"=="start" goto :do_start
if /i "%ACTION%"=="stop" goto :do_stop
if /i "%ACTION%"=="status" goto :do_status
echo Usage: scripts\embed.bat [start^|stop^|status] (no arg = start)
exit /b 1
:do_start
if not exist "%SYS%\curl.exe" (
echo [ERROR] %SYS%\curl.exe not found - the readiness check needs it.
exit /b 1
)
call :is_running
if defined RUNNING_PID (
echo embedding server is already running ^(PID !RUNNING_PID!^) on port %EMBED_PORT%.
exit /b 0
)
if not exist "%SERVER%" (
echo [ERROR] llama-server.exe not found: %SERVER%
echo download the llama.cpp bin-win-cpu-x64 zip and extract it there.
exit /b 1
)
if not exist "%EMBED_MODEL%" (
echo [ERROR] embedding model not found: %EMBED_MODEL%
echo fetch Qwen3-Embedding-0.6B-Q8_0.gguf from ModelScope.
exit /b 1
)
echo Starting llama-server -^> %EMBED_MODEL% ^(port %EMBED_PORT%^)
powershell -NoProfile -Command "Start-Process -FilePath '%SERVER%' -ArgumentList '-m','%EMBED_MODEL%','--embeddings','--host','%EMBED_HOST%','--port','%EMBED_PORT%','-c','4096','-b','2048','-ub','2048','-t','8' -WorkingDirectory '%LLAMA_DIR%' -RedirectStandardOutput '%STDOUT_FILE%' -RedirectStandardError '%LOG_FILE%' -WindowStyle Hidden"
set /a TRIES=0
:start_wait
set /a TRIES+=1
call :healthy
if not errorlevel 1 (
echo Ready: http://127.0.0.1:%EMBED_PORT%/v1/embeddings ^(log: %LOG_FILE%^)
exit /b 0
)
if !TRIES! GEQ 30 (
echo [ERROR] not ready after ~60s - check %LOG_FILE%
exit /b 1
)
"%SYS%\ping.exe" -n 2 127.0.0.1 >nul
goto :start_wait
:do_stop
call :is_running
if not defined RUNNING_PID (
echo embedding server is not running.
exit /b 0
)
echo Stopping PID !RUNNING_PID! ...
"%SYS%\taskkill.exe" /PID !RUNNING_PID! /T /F >nul 2>&1
"%SYS%\ping.exe" -n 2 127.0.0.1 >nul
call :is_running
if not defined RUNNING_PID (
echo Stopped.
exit /b 0
)
echo [WARN] still listening on %EMBED_PORT%.
exit /b 1
:do_status
call :is_running
call :healthy
if not errorlevel 1 (
echo embedding: running ^(PID !RUNNING_PID!^) . port %EMBED_PORT% . health ok
exit /b 0
)
if defined RUNNING_PID (
echo embedding: process alive ^(PID !RUNNING_PID!^) but health not ready ^(%HEALTH_URL%^)
exit /b 1
)
echo embedding: not running
exit /b 1
rem healthy: errorlevel 0 = HTTP 2xx
:healthy
"%SYS%\curl.exe" -s -f --max-time 3 -o NUL "%HEALTH_URL%" >nul 2>&1
exit /b %errorlevel%
rem is_running -> RUNNING_PID (detected from the listening port)
:is_running
set "RUNNING_PID="
set "NS_FILE=%TEMP%\embed-netstat-%RANDOM%.txt"
"%SYS%\netstat.exe" -ano -p tcp > "%NS_FILE%" 2>nul
for /f "tokens=2,5" %%A in ('%SYS%\findstr.exe /C:"LISTENING" "%NS_FILE%"') do (
if not defined RUNNING_PID (
echo %%A| "%SYS%\findstr.exe" /E /C:":%EMBED_PORT%" >nul && set "RUNNING_PID=%%B"
)
)
del "%NS_FILE%" >nul 2>&1
exit /b 0