mineru_local_daemon.sh 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. #!/bin/bash
  2. # filepath: ocr_platform/ocr_tools/daemons/mineru_local_daemon.sh
  3. # 对应: MinerU2.5-Pro 本地 llama-server 服务(macOS),使用 GGUF 格式模型
  4. # 适用于 Mac M4 Pro 48G,使用 Metal GPU 加速
  5. # 模型下载地址: https://huggingface.co/mradermacher/MinerU2.5-Pro-2604-1.2B-GGUF
  6. #
  7. # 首次下载方式(自动下载 Q8_0 量化版本):
  8. # llama-server -hf mradermacher/MinerU2.5-Pro-2604-1.2B-GGUF:Q8_0
  9. # 模型会缓存到 ~/Library/Caches/llama.cpp/,也可手动移至 ~/models/mineru_vl/
  10. # curl -X POST http://localhost:8103/v1/chat/completions -d @payload.json
  11. # ----!!!!! 目前提供的gguf 不是官方发布的最终版本,无法解析表格结构 ----!!!!!
  12. LOGDIR="$HOME/workspace/logs"
  13. mkdir -p $LOGDIR
  14. PIDFILE="$LOGDIR/mineru_llamaserver.pid"
  15. LOGFILE="$LOGDIR/mineru_llamaserver.log"
  16. # 配置参数
  17. CONDA_ENV="mineru"
  18. PORT="8103"
  19. HOST="0.0.0.0"
  20. # 本地 GGUF 模型路径(llama-server -hf 下载后的实际路径)
  21. HF_CACHE="$HOME/models/MinerU2.5-Pro-2604-1.2B-GGUF"
  22. # MODEL_PATH="$HF_CACHE/MinerU2.5-Pro-2604-1.2B-F16.gguf"
  23. MODEL_PATH="$HF_CACHE/MinerU2.5-Pro-2604-1.2B-Q8_0.gguf"
  24. MMPROJ_PATH="$HF_CACHE/MinerU2.5-Pro-2604-1.2B-F16-mmproj.gguf"
  25. # 模型别名(对外暴露的模型 ID,对应 yaml 中的 model 字段)
  26. MODEL_NAME="MinerU2.5-Pro-2604-1.2B"
  27. # llama-server 执行文件
  28. LLAMA_SERVER_EXECUTABLE="/Users/zhch158/workspace/repository.git/llama.cpp/build/bin/llama-server"
  29. # llama-server 参数
  30. # 注意:MinerU2.5-Pro n_ctx_train=8192,设置 8192 即可
  31. CONTEXT_SIZE="8192" # 上下文长度(对齐模型 n_ctx_train=8192)
  32. GPU_LAYERS="99" # Metal GPU 层数(99 表示全部)
  33. THREADS="8" # CPU 线程数(M4 Pro 建议值)
  34. BATCH_SIZE="512" # 批处理大小
  35. UBATCH_SIZE="128" # 微批处理大小
  36. # conda 环境激活
  37. if [ -f "$HOME/anaconda3/etc/profile.d/conda.sh" ]; then
  38. source "$HOME/anaconda3/etc/profile.d/conda.sh"
  39. conda activate $CONDA_ENV
  40. elif [ -f "$HOME/miniconda3/etc/profile.d/conda.sh" ]; then
  41. source "$HOME/miniconda3/etc/profile.d/conda.sh"
  42. conda activate $CONDA_ENV
  43. elif [ -f "/opt/miniconda3/etc/profile.d/conda.sh" ]; then
  44. source /opt/miniconda3/etc/profile.d/conda.sh
  45. conda activate $CONDA_ENV
  46. else
  47. echo "Warning: conda initialization file not found, trying direct path"
  48. export PATH="/opt/miniconda3/envs/$CONDA_ENV/bin:$PATH"
  49. fi
  50. start() {
  51. if [ -f $PIDFILE ] && kill -0 $(cat $PIDFILE) 2>/dev/null; then
  52. echo "MinerU2.5-Pro llama-server 已在运行"
  53. return 1
  54. fi
  55. echo "启动 MinerU2.5-Pro llama-server 守护进程..."
  56. echo "Host: $HOST, Port: $PORT"
  57. echo "主模型: $MODEL_PATH"
  58. echo "多模态投影器: $MMPROJ_PATH"
  59. echo "上下文长度: $CONTEXT_SIZE"
  60. echo "GPU 层数: $GPU_LAYERS (Metal)"
  61. echo "线程数: $THREADS"
  62. # 检查模型文件是否存在
  63. if [ ! -f "$MODEL_PATH" ]; then
  64. echo "❌ 主模型文件不存在: $MODEL_PATH"
  65. echo "请确认模型已下载到 llama.cpp 缓存目录"
  66. return 1
  67. fi
  68. if [ ! -f "$MMPROJ_PATH" ]; then
  69. echo "❌ 多模态投影器文件不存在: $MMPROJ_PATH"
  70. echo "请确认 mmproj 文件已下载"
  71. return 1
  72. fi
  73. # 检查 llama-server 执行文件(本机编译版本)
  74. if [ ! -x "$LLAMA_SERVER_EXECUTABLE" ]; then
  75. echo "❌ llama-server 执行文件不存在或不可执行: $LLAMA_SERVER_EXECUTABLE"
  76. echo "请确认已在本机编译 llama.cpp(cmake --build build)"
  77. return 1
  78. fi
  79. echo "🔧 使用 llama-server: $LLAMA_SERVER_EXECUTABLE"
  80. echo "🔧 llama.cpp 版本: $("$LLAMA_SERVER_EXECUTABLE" --version 2>&1 | head -1 || echo 'Unknown')"
  81. echo "💻 系统信息:"
  82. echo " 架构: $(uname -m)"
  83. echo " 系统: $(uname -s)"
  84. echo " 内存: $(sysctl -n hw.memsize | awk '{printf "%.1f GB", $1/1024/1024/1024}')"
  85. # 启动 llama-server
  86. # 注意:MinerU2.5-Pro GGUF 内嵌推荐采样参数(top_k=1, top_p=0.001, temp=0.01),
  87. # llama-server 会自动应用,此处只设 --temp 0 确保确定性解码
  88. nohup "$LLAMA_SERVER_EXECUTABLE" \
  89. -m "$MODEL_PATH" \
  90. --mmproj "$MMPROJ_PATH" \
  91. --alias $MODEL_NAME \
  92. --host $HOST \
  93. --port $PORT \
  94. --media-path $HOME/workspace \
  95. -c $CONTEXT_SIZE \
  96. -ngl $GPU_LAYERS \
  97. -t $THREADS \
  98. -b $BATCH_SIZE \
  99. -ub $UBATCH_SIZE \
  100. --temp 0 \
  101. > $LOGFILE 2>&1 &
  102. echo $! > $PIDFILE
  103. echo "✅ MinerU2.5-Pro llama-server 已启动,PID: $(cat $PIDFILE)"
  104. echo "📋 日志文件: $LOGFILE"
  105. echo "🌐 服务 URL: http://$HOST:$PORT"
  106. echo "📖 OpenAI 兼容 API: http://localhost:$PORT/v1 (chat/completions, models)"
  107. echo ""
  108. echo "等待服务启动..."
  109. sleep 5
  110. status
  111. }
  112. stop() {
  113. if [ ! -f $PIDFILE ]; then
  114. echo "MinerU2.5-Pro llama-server 未在运行"
  115. return 1
  116. fi
  117. PID=$(cat $PIDFILE)
  118. echo "停止 MinerU2.5-Pro llama-server (PID: $PID)..."
  119. kill $PID
  120. for i in {1..30}; do
  121. if ! kill -0 $PID 2>/dev/null; then
  122. break
  123. fi
  124. echo "等待进程停止... ($i/30)"
  125. sleep 1
  126. done
  127. if kill -0 $PID 2>/dev/null; then
  128. echo "强制终止进程..."
  129. kill -9 $PID
  130. fi
  131. rm -f $PIDFILE
  132. echo "✅ MinerU2.5-Pro llama-server 已停止"
  133. }
  134. status() {
  135. if [ -f $PIDFILE ] && kill -0 $(cat $PIDFILE) 2>/dev/null; then
  136. PID=$(cat $PIDFILE)
  137. echo "✅ MinerU2.5-Pro llama-server 正在运行 (PID: $PID)"
  138. echo "🌐 服务 URL: http://$HOST:$PORT"
  139. echo "📋 日志文件: $LOGFILE"
  140. # 检查端口监听状态
  141. if lsof -nP -iTCP:$PORT -sTCP:LISTEN >/dev/null 2>&1; then
  142. echo "🔗 端口 $PORT 正在监听"
  143. else
  144. echo "⚠️ 端口 $PORT 未在监听(服务可能正在启动)"
  145. fi
  146. # 检查 API 响应
  147. if command -v curl >/dev/null 2>&1; then
  148. if curl -s --connect-timeout 2 http://127.0.0.1:$PORT/v1/models > /dev/null 2>&1; then
  149. echo "🎯 API 响应正常"
  150. else
  151. echo "⚠️ API 无响应(服务可能正在启动)"
  152. fi
  153. fi
  154. # 显示进程内存使用
  155. if command -v ps >/dev/null 2>&1; then
  156. MEM=$(ps -o rss= -p $PID 2>/dev/null | awk '{printf "%.2f GB", $1/1024/1024}')
  157. if [ -n "$MEM" ]; then
  158. echo "💾 内存使用: $MEM"
  159. fi
  160. fi
  161. if [ -f $LOGFILE ]; then
  162. echo "📄 最近日志(最后 3 行):"
  163. tail -3 $LOGFILE | sed 's/^/ /'
  164. fi
  165. else
  166. echo "❌ MinerU2.5-Pro llama-server 未在运行"
  167. if [ -f $PIDFILE ]; then
  168. echo "删除过期的 PID 文件..."
  169. rm -f $PIDFILE
  170. fi
  171. fi
  172. }
  173. logs() {
  174. if [ -f $LOGFILE ]; then
  175. echo "📄 MinerU2.5-Pro llama-server 日志:"
  176. echo "====================="
  177. tail -f $LOGFILE
  178. else
  179. echo "❌ 日志文件不存在: $LOGFILE"
  180. fi
  181. }
  182. config() {
  183. echo "📋 当前配置:"
  184. echo " Conda 环境: $CONDA_ENV"
  185. echo " Host: $HOST"
  186. echo " Port: $PORT"
  187. echo " 模型别名: $MODEL_NAME"
  188. echo " 主模型路径: $MODEL_PATH"
  189. echo " 多模态投影器: $MMPROJ_PATH"
  190. echo " 上下文长度: $CONTEXT_SIZE"
  191. echo " GPU 层数: $GPU_LAYERS"
  192. echo " 线程数: $THREADS"
  193. echo " 批处理大小: $BATCH_SIZE"
  194. echo " 微批处理大小: $UBATCH_SIZE"
  195. echo " PID 文件: $PIDFILE"
  196. echo " 日志文件: $LOGFILE"
  197. echo ""
  198. echo "📦 模型文件检查:"
  199. if [ -f "$MODEL_PATH" ]; then
  200. SIZE=$(du -h "$MODEL_PATH" | cut -f1)
  201. echo " ✅ 主模型存在 ($SIZE)"
  202. else
  203. echo " ❌ 主模型不存在: $MODEL_PATH"
  204. fi
  205. if [ -f "$MMPROJ_PATH" ]; then
  206. SIZE=$(du -h "$MMPROJ_PATH" | cut -f1)
  207. echo " ✅ 多模态投影器存在 ($SIZE)"
  208. else
  209. echo " ❌ 多模态投影器不存在: $MMPROJ_PATH"
  210. fi
  211. echo ""
  212. echo "🔧 环境检查:"
  213. echo " llama-server: $LLAMA_SERVER_EXECUTABLE"
  214. if [ -x "$LLAMA_SERVER_EXECUTABLE" ]; then
  215. LLAMA_VERSION=$("$LLAMA_SERVER_EXECUTABLE" --version 2>&1 | head -1 || echo 'Unknown')
  216. echo " 版本: $LLAMA_VERSION"
  217. else
  218. echo " ⚠️ 执行文件不存在或不可执行"
  219. fi
  220. echo " Conda: $(which conda 2>/dev/null || echo '未找到')"
  221. echo " 当前 Python: $(which python 2>/dev/null || echo '未找到')"
  222. echo ""
  223. echo "💻 系统信息:"
  224. echo " 架构: $(uname -m)"
  225. echo " 系统版本: $(sw_vers -productVersion 2>/dev/null || echo 'Unknown')"
  226. echo " 总内存: $(sysctl -n hw.memsize 2>/dev/null | awk '{printf "%.1f GB", $1/1024/1024/1024}' || echo 'Unknown')"
  227. echo " CPU 核心: $(sysctl -n hw.ncpu 2>/dev/null || echo 'Unknown')"
  228. }
  229. test_api() {
  230. echo "🧪 测试 MinerU2.5-Pro llama-server API..."
  231. if [ ! -f $PIDFILE ] || ! kill -0 $(cat $PIDFILE) 2>/dev/null; then
  232. echo "❌ MinerU2.5-Pro llama-server 服务未在运行"
  233. return 1
  234. fi
  235. if ! command -v curl >/dev/null 2>&1; then
  236. echo "❌ curl 命令未找到"
  237. return 1
  238. fi
  239. echo "📡 测试 /v1/models 端点..."
  240. response=$(curl -s --connect-timeout 10 http://127.0.0.1:$PORT/v1/models)
  241. if [ $? -eq 0 ]; then
  242. echo "✅ Models 端点可访问"
  243. echo "$response" | python -m json.tool 2>/dev/null || echo "$response"
  244. else
  245. echo "❌ Models 端点不可访问"
  246. fi
  247. echo ""
  248. echo "📡 测试 /health 端点..."
  249. health=$(curl -s --connect-timeout 5 http://127.0.0.1:$PORT/health)
  250. if [ $? -eq 0 ]; then
  251. echo "✅ Health 端点: $health"
  252. else
  253. echo "⚠️ Health 端点不可访问"
  254. fi
  255. }
  256. test_client() {
  257. echo "🧪 测试 MinerU2.5-Pro 与 llama-server 集成..."
  258. if [ ! -f $PIDFILE ] || ! kill -0 $(cat $PIDFILE) 2>/dev/null; then
  259. echo "❌ MinerU2.5-Pro llama-server 服务未在运行,请先启动: $0 start"
  260. return 1
  261. fi
  262. CONFIG_FILE="/Users/zhch158/workspace/repository.git/ocr_platform/ocr_tools/universal_doc_parser/config/bank_statement_mineru_vl_local.yaml"
  263. echo "📄 配置文件: $CONFIG_FILE"
  264. echo ""
  265. echo "确保配置文件中 vl_recognition.server_url 指向: http://localhost:$PORT"
  266. echo ""
  267. echo "测试命令示例:"
  268. echo " cd /Users/zhch158/workspace/repository.git/ocr_platform/ocr_tools/universal_doc_parser"
  269. echo " conda activate mineru"
  270. echo " python main_v2.py -i /path/to/test.pdf -c $CONFIG_FILE -o /tmp/test_output -s bank_statement --pages 1 --streaming"
  271. echo ""
  272. echo "或者使用 curl 直接测试 API:"
  273. echo " curl -X POST http://localhost:$PORT/v1/chat/completions \\"
  274. echo " -H 'Content-Type: application/json' \\"
  275. echo " -d '{"
  276. echo " \"model\": \"$MODEL_NAME\","
  277. echo " \"messages\": ["
  278. echo " {"
  279. echo " \"role\": \"user\","
  280. echo " \"content\": ["
  281. echo " {\"type\": \"text\", \"text\": \"Table Recognition:\"},"
  282. echo " {\"type\": \"image_url\", \"image_url\": {\"url\": \"file:///path/to/image.png\"}}"
  283. echo " ]"
  284. echo " }"
  285. echo " ],"
  286. echo " \"max_tokens\": 8192"
  287. echo " }'"
  288. }
  289. usage() {
  290. echo "MinerU2.5-Pro llama-server 服务守护进程(macOS)"
  291. echo "==========================================="
  292. echo "用法: $0 {start|stop|restart|status|logs|config|test|test-client}"
  293. echo ""
  294. echo "命令:"
  295. echo " start - 启动 MinerU2.5-Pro llama-server 服务"
  296. echo " stop - 停止 MinerU2.5-Pro llama-server 服务"
  297. echo " restart - 重启 MinerU2.5-Pro llama-server 服务"
  298. echo " status - 显示服务状态和资源使用"
  299. echo " logs - 显示服务日志(跟踪模式)"
  300. echo " config - 显示当前配置"
  301. echo " test - 测试 /v1/models API 端点"
  302. echo " test-client - 显示如何测试与配置文件集成"
  303. echo ""
  304. echo "配置(编辑脚本修改):"
  305. echo " Host: $HOST"
  306. echo " Port: $PORT"
  307. echo " 主模型: $MODEL_PATH"
  308. echo " 多模态投影器: $MMPROJ_PATH"
  309. echo " 上下文长度: $CONTEXT_SIZE"
  310. echo " GPU 层数: $GPU_LAYERS (Metal)"
  311. echo ""
  312. echo "示例:"
  313. echo " ./mineru_local_daemon.sh start"
  314. echo " ./mineru_local_daemon.sh status"
  315. echo " ./mineru_local_daemon.sh logs"
  316. echo " ./mineru_local_daemon.sh test"
  317. echo ""
  318. echo "前置要求:"
  319. echo " 1. 本机编译 llama.cpp,执行文件: $LLAMA_SERVER_EXECUTABLE"
  320. echo " 2. 模型文件位于: $HF_CACHE"
  321. echo " 3. conda 环境 mineru 已配置"
  322. }
  323. case "$1" in
  324. start)
  325. start
  326. ;;
  327. stop)
  328. stop
  329. ;;
  330. restart)
  331. stop
  332. sleep 3
  333. start
  334. ;;
  335. status)
  336. status
  337. ;;
  338. logs)
  339. logs
  340. ;;
  341. config)
  342. config
  343. ;;
  344. test)
  345. test_api
  346. ;;
  347. test-client)
  348. test_client
  349. ;;
  350. *)
  351. usage
  352. exit 1
  353. ;;
  354. esac