网站设计平台 动易,国外网站建设设计欣赏,哪里可以上传自己的php网站,用python做网页#x1f680; 实现Windows本地大模型翻译服务 - 基于OllamaFlask的划词翻译实践 #x1f6e0;️ 步骤概要1️⃣ python 环境准备2️⃣ Ollama 安装3️⃣ 一个 Flask 服务4️⃣ Windows 服务化封装5️⃣ 测试本地接口6️⃣ 配置划词翻译自定义翻译源7️⃣ 效果展示8️⃣ debug… 实现Windows本地大模型翻译服务 - 基于OllamaFlask的划词翻译实践 ️ 步骤概要1️⃣ python 环境准备2️⃣ Ollama 安装3️⃣ 一个 Flask 服务4️⃣ Windows 服务化封装5️⃣ 测试本地接口6️⃣ 配置划词翻译自定义翻译源7️⃣ 效果展示8️⃣ debug 历程 技术亮点 ️ 步骤概要
参考 API 文档
Ollama API划词翻译自定义翻译源
1️⃣ python 环境准备
# 虚拟环境
conda create -n ollama_trans
conda activate ollama_trans
pip install flask flask-cors pywin32 requests waitress
# 请确保完成 pywin32_postinstall.py 的安装步骤。:
python path\to\your\envs\ollama_trans\Scripts\pywin32_postinstall.py -install2️⃣ Ollama 安装
安装 Ollama 最好提前设置安装路径和模型下载路径否则它都一股脑干到 C 盘。可以参考前一篇博客 《本地投喂deepseek》
设置模型保存路径新增环境变量 OLLAMA_MODELS值为目标地址似乎要 重启电脑生效指定安装目录OllamaSetup.exe /DIR“D:\some\location”ollama默认在 11434 端口提供 REST API比如通过 curl 发送请求到 /api/generate 来生成文本
curl http://localhost:11434/api/generate -d {\model\: \deepseek-r1:14b\, \prompt\: \Why is the sky blue?\, \stream\: false}我们的目的就是用 flask 写一个服务器适配 Ollama 和划词翻译的 API
3️⃣ 一个 Flask 服务 遇事不决问 DS # translation_service.py
import re
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
from flask import Flask, request, jsonify
from flask_cors import CORS
from waitress import serve
import requests
import logging
import sys
import osapp Flask(__name__)
CORS(app)# 获取当前脚本所在的目录
current_directory os.path.dirname(os.path.abspath(__file__))
# 定义日志文件名
log_file_path os.path.join(current_directory, flask_svc.log)
# 配置日志记录器
logging.basicConfig(levellogging.INFO,format%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s,datefmt%a, %d %b %Y %H:%M:%S,filenamelog_file_path,filemodea # 使用 a 表示追加模式w 表示覆盖模式
)
logger logging.getLogger(__name__)# 选择ollama的模型
MODEL_NAME {qwen: qwen2.5:7b-instruct-q8_0,llama: llama3.2:3b,deepseek: deepseek-r1:14b # 其实 deepseek-r1 擅长推理并不适合翻译有点慢
}# 语言映射
LANGUAGE_MAP {中文(简体): 中文,英语: 英文,日语: 日文
}def clean_response(text):清除think标签内容# 过滤DeepSeek思考过程的正则表达式THINK_PATTERN re.compile(rthink.*?/think, re.DOTALL)return THINK_PATTERN.sub(, text).strip()def build_prompt(text, source, target):source_lang LANGUAGE_MAP.get(source, source)target_lang LANGUAGE_MAP.get(target, target)return f作为专业翻译官请将以下{source_lang}内容精准翻译为{target_lang}仅输出译文\n{text}app.route(/translate, methods[POST])
def translate():try:data request.jsonlogger.info(f收到请求: {data})# 提取必要参数model_name data[name].lower()text data[text]dest_langs data[destination]source_lang data.get(source) or autoif source_lang dest_langs[0] and len(dest_langs) 1:target_lang dest_langs[1]else:target_lang dest_langs[0]response requests.post(http://localhost:11434/api/generate,json{model: MODEL_NAME.get(model_name, model_name),prompt: build_prompt(text, source_lang, target_lang),stream: False,options: {temperature: 0.3}})# 处理翻译结果raw_response response.json()[response]translated_text clean_response(raw_response)return jsonify({text: text,from: source_lang,to: target_lang,result: [translated_text]})except Exception as e:logger.error(f翻译失败: {str(e)})return jsonify({error: str(e)}), 500class TranslationService(win32serviceutil.ServiceFramework):_svc_name_ LocalOllamaTranslationService # 服务名称唯一_svc_display_name_ Ollama本地翻译服务_svc_description_ 为划词翻译提供基于Ollama中运行的大模型的本地翻译服务 # 服务描述logger.info(fsvc_name: {_svc_name_}, model_name: {MODEL_NAME})def __init__(self, args):win32serviceutil.ServiceFramework.__init__(self, args)self.hWaitStop win32event.CreateEvent(None, 0, 0, None)socket.setdefaulttimeout(60)def SvcStop(self):self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)logger.info(Stopping Ollama Translation Service...)win32event.SetEvent(self.hWaitStop)servicemanager.LogInfoMsg(服务正在停止...)logger.info(Service stopped successfully.)def SvcDoRun(self):logger.info(Starting Ollama Translation Service...)try:self.main()logger.info(Service started successfully.)except Exception as e:logger.error(fFailed to start service: {str(e)})self.ReportServiceStatus(win32service.SERVICE_STOPPED)def main(self):serve(app, host127.0.0.1, port5000)if __name__ __main__:if len(sys.argv) 1:servicemanager.Initialize()servicemanager.PrepareToHostSingle(TranslationService)servicemanager.StartServiceCtrlDispatcher()else:win32serviceutil.HandleCommandLine(TranslationService)4️⃣ Windows 服务化封装
以下脚本都需要以管理员身份运行
启动服务脚本 install_service.bat
:: install_service.bat
echo off
# 这里的 python 解释器要填虚拟环境那个否则找不到包
set PYTHON_PATHpath\to\your\envs\ollama_trans\python.exe
set SCRIPT_PATH%~dp0translation_service.py%PYTHON_PATH% %SCRIPT_PATH% --startupauto install
# 这里的服务名称 LocalOllamaTranslationService 要跟上面程序里面的一致是唯一的
net start LocalOllamaTranslationService关闭服务脚本 uninstall_service.bat
:: uninstall_service.bat
echo off
net stop LocalOllamaTranslationService
set PYTHON_PATHpath\to\your\envs\ollama_trans\python.exe
set SCRIPT_PATH%~dp0translation_service.py%PYTHON_PATH% %SCRIPT_PATH% remove最终的文件结构
├── translation_service.py # 主服务程序
├── install_service.bat # 服务安装脚本
├── uninstall_service.bat # 服务卸载脚本
└── flask_svc.log # python 日志5️⃣ 测试本地接口
现在我们请求的是 flask 服务的端口我这里指定了模型名称是 qwenollama 中也下载了 qwen2.5:7b-instruct-q8_0
curl -X POST http://localhost:5000/translate -H Content-Type: application/json -d {\name\: \qwen\,\text\: \人工智能的发展前景\, \destination\: [\中文(简体)\, \英语\], \source\: \中文(简体)\}返回
{from:\u4e2d\u6587(\u7b80\u4f53),result:[The Prospects for the Development of Artificial Intelligence],text:\u4eba\u5de5\u667a\u80fd\u7684\u53d1\u5c55\u524d\u666f,to:\u82f1\u8bed}6️⃣ 配置划词翻译自定义翻译源
插件设置
自定义翻译源 接口地址http://localhost:5000/translate 翻译源名称qwen然后回车 测试
根据上面的程序逻辑翻译源名称最好跟 ollama 下载的模型名称一致
7️⃣ 效果展示 8️⃣ debug 历程
日志的重要性 一开始 deepseek 生成的 py 程序都没写日志启动服务一直失败报错pywintypes.error: (1063, StartServiceCtrlDispatcher, 服务进程无法连接到服务控制器上。)然后又那这些报错去问它给了一堆方案都没解决问题 写了 logger 才发现问题所在
Sat, 15 Feb 2025 21:19:16 wasyncore.py[line:449] INFO Serving on http://127.0.0.1:5001
Sat, 15 Feb 2025 21:22:47 app.py[line:875] ERROR Exception on /translate [POST]
Traceback (most recent call last):File D:\dev\miniconda\miniconda3\envs\flask\Lib\site-packages\flask\app.py, line 1511, in wsgi_appresponse self.full_dispatch_request()File D:\dev\miniconda\miniconda3\envs\flask\Lib\site-packages\flask\app.py, line 919, in full_dispatch_requestrv self.handle_user_exception(e)File D:\dev\miniconda\miniconda3\envs\flask\Lib\site-packages\flask_cors\extension.py, line 165, in wrapped_functionreturn cors_after_request(app.make_response(f(*args, **kwargs)))~^^^^^^^^^^^^^^^^^File D:\dev\miniconda\miniconda3\envs\flask\Lib\site-packages\flask\app.py, line 917, in full_dispatch_requestrv self.dispatch_request()File D:\dev\miniconda\miniconda3\envs\flask\Lib\site-packages\flask\app.py, line 902, in dispatch_requestreturn self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
TypeError: TranslationService.translate() missing 1 required positional argument: self服务启停 cmd 中的双引号是需要用反斜杠 \ 转义的在 powershell 中不需要debug 过程中需要起了又删掉 LocalOllamaTranslationService 服务sc queryex LocalOllamaTranslationService 得到 PIDtaskkill /f /pid PID 强行停止sc delete LocalOllamaTranslationService 删掉这个服务 ID 后才能再启动程序否则会报错服务已存在或者以管理员身份打开 cmd 或者 VS Code执行python translation_service.py stop 停止服务python translation_service.py remove 删除服务python translation_service.py install 安装服务python translation_service.py start 启动服务 技术亮点 完全离线: 从模型推理到翻译服务全程本地运行 隐私保护: 敏感文本无需离开本地设备 低延迟: 省去网络传输耗时平均响应500ms 可扩展架构: 轻松切换不同大语言模型