使用 Ollama 和 FastAPI 部署 Python AI 应用
一个在本地构建的 AI 项目,可能使用了像 Ollama 和 FastAPI 这样的库,最终需要部署到服务器上,以便更广泛地访问或实现可靠的 24/7 运行。本文档详细介绍了将这样一个基于 Python 的 AI 应用部署到 Linux 服务器上的常用流程。
这些步骤涵盖了连接到服务器、设置环境、管理 AI 模型、手动运行应用程序进行测试,以及使用 systemd 将其配置为可靠的后台服务运行。虽然这些步骤是基于部署使用 FastAPI 和 Ollama 的应用程序,但许多步骤展示了适用于各种 Python Web 应用程序的标准部署实践。
目录
-
案例研究:使用 Ollama 和 FastAPI 部署 Python AI 应用
- 目录
-
通过 SSH 连接到服务器
- 生成 SSH 密钥
- 连接
- 克隆项目代码库
-
环境配置
- 1. 安装
uv(可选但推荐) - 2. 安装 Python
-
3. 安装软件依赖
- 项目依赖
- 安装并运行 Ollama
-
4. 准备 AI 模型
- 上传/下载模型
- 使用 Ollama 构建模型
- 5. 设置环境变量
- 6. 手动运行项目 (测试)
- 1. 安装
-
使用
systemd作为服务部署- 创建服务文件
- 启用并启动服务
-
常见问题 (FAQ)
- 环境配置问题
- 运行时问题
- 结论
通过 SSH 连接到服务器
安全外壳协议 (SSH) 是安全连接和管理远程 Linux 服务器的标准方法。这一般是部署过程的第一步。
生成 SSH 密钥
如果本地计算机上还没有 SSH 密钥对,需要生成一个:一个私钥(安全地保存在本地)和一个公钥(与服务器共享)。
在本地计算机上使用 ssh-keygen 命令。一般遵循提示即可。常见的算法是 ED25519 (推荐) 或 RSA。
# 使用 ED25519 的示例
ssh-keygen -t ed25519 -C "your_email@example.com"
# 遵循提示保存密钥(默认位置一般即可)并可选地设置密码。
- 参考: GitHub 文档:生成新的 SSH 密钥
在 macOS 和 Linux 上,密钥一般存储在 ~/.ssh 目录中。使用 ls -al ~/.ssh 检查:
-
id_ed25519或id_rsa:私钥。切勿共享此文件。 -
id_ed25519.pub或id_rsa.pub:公钥。复制此文件的内容以提供给服务器管理员,或者如果有权限,自行添加。
服务器管理员(或自己)必须将公钥文件 (id_xxx.pub) 的内容添加到服务器上目标用户主目录下的 ~/.ssh/authorized_keys 文件中。
连接
一旦公钥在服务器上被授权,就可以使用私钥建立连接:
ssh -i /path/to/your/private_key your_server_username@your_server_hostname_or_ip -p <ssh_port_number>
替换占位符:
-
/path/to/your/private_key:私钥文件的路径(例如~/.ssh/id_ed25519)。 -
your_server_username:远程服务器上的用户名。 -
your_server_hostname_or_ip:服务器的 IP 地址或可解析的主机名。 -
<ssh_port_number>:服务器上配置的 SSH 端口号(默认为 22,但为了安全一般会更改)。
注意: 替换像 <ssh_port_number> 这样的占位符时,省略尖括号 (<>)。
首次连接到新服务器时,可能会看到一个主机真实性警告。这是正常的。输入 yes 继续。
The authenticity of host ... can t be established.
... key fingerprint is ...
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
克隆项目代码库
成功建立 SSH 连接后,使用 Git 将项目代码获取到服务器上:
git clone your_repository_link
# 示例: git clone git@github.com:your_username/your_project.git
# 或: git clone https://github.com/your_username/your_project.git
将 your_repository_link 替换为 Git 代码库的实际 SSH 或 HTTPS URL。进入克隆的目录:cd your_project_directory_name。
环境配置
在服务器上设置必要的软件和环境。
1. 安装 uv (可选但推荐)
uv 是一个用 Rust 编写的超级快速的 Python 包安装器和解析器。与标准的 pip 相比,使用它可以显著加快依赖项的安装速度。它是可选的,但推荐使用。
# 使用 pip 安装 uv (确保 pip 可用)
pip install uv
# 或者,遵循官方说明:https://github.com/astral-sh/uv#installation
验证安装:
uv --version
# 预期输出类似于:uv x.y.z
2. 安装 Python
确保安装了兼容的 Python 版本(例如 3.8-3.11,检查项目的需求)。
如果安装了 uv,可以用它来安装 Python:
# 将 3.x.y 替换为目标版本 (例如 3.10.13)
uv python install 3.x.y
# 遵循任何关于 PATH 更新的提示。
或者,使用系统的包管理器(在 Linux 服务器上很常见):
# Debian/Ubuntu 示例
sudo apt update
sudo apt install python3 python3-pip python3-venv
# CentOS/RHEL 示例
sudo yum update
sudo yum install python3 python3-pip
确认 Python 安装:
python3 --version
# 或有时只是 python --version ,取决于 PATH 设置
- 参考: 使用 uv 安装 Python
3. 安装软件依赖
项目依赖
项目应该有一个 requirements.txt 文件,列出了 Python 依赖项。导航到项目目录并安装它们。
使用 uv (如果已安装,推荐):
cd /path/to/your/project
uv pip install -r requirements.txt
或者,使用 pip (一般在虚拟环境中):
cd /path/to/your/project
# 最佳实践:第一创建并激活虚拟环境
# python3 -m venv venv
# source venv/bin/activate
pip install -r requirements.txt
# 或 pip3 install -r requirements.txt
注意: 将 /path/to/your/project 替换为克隆的代码库的实际绝对路径。
安装并运行 Ollama
Ollama 允许在本地运行大型语言模型。使用官方脚本在 Linux 服务器上安装它:
curl -fsSL https://ollama.com/install.sh | sh
为了初步测试,可以在后台手动启动 Ollama 服务器:
ollama serve & # & 符号使其仅在当前会话的后台运行。
注意: 对于生产环境,Ollama 应设置为 systemd 服务(安装脚本一般会自动执行此操作,请使用 systemctl status ollama 检查)。运行 ollama serve & 主要用于临时测试。
验证 Ollama 是否正在运行且可访问(此命令与正在运行的服务器通信):
ollama list
# 应该显示一个空列表或任何已经拉取/创建的模型。
# 如果命令挂起或出错,则表明服务器未正确运行。
- 参考: Ollama Linux 安装指南
4. 准备 AI 模型
将所需的 AI 模型文件放在服务器上。选择一个合适的位置,例如项目内的 models/ 子目录或中央的 /opt/ai-models/ 目录。
上传/下载模型
-
从 Hugging Face: 使用
huggingface-cli(通过pip install huggingface_hub安装):huggingface-cli download repo_id path/to/model.gguf --local-dir /path/on/server/models --local-dir-use-symlinks False # 替换 repo_id, 模型文件名, 和 /path/on/server/models -
从本地机器: 使用
scp(Secure Copy) 从开发机器上传模型。替换占位符。# 上传单个模型文件 scp /path/on/local/model.gguf your_server_username@your_server_hostname_or_ip:/path/on/server/models/ # 上传一个 Ollama Modelfile scp /path/on/local/Modelfile your_server_username@your_server_hostname_or_ip:/path/on/server/models/ # 递归上传整个目录 scp -r /path/on/local/model_directory your_server_username@your_server_hostname_or_ip:/path/on/server/models/ -
GGUF 合并: 如果模型被分割(例如
model-part-1.gguf,model-part-2.gguf),可能需要llama.cpp工具来合并它们。克隆llama.cpp,构建它,并使用llama-gguf-split:# 假设 llama.cpp 工具已构建并在 PATH 中 # llama-gguf-split --merge input_part_*.gguf output_merged.gguf
使用 Ollama 构建模型
要将本地模型文件(如 .gguf)与 Ollama 集成或定义自定义模型参数,请使用 Modelfile。在服务器上,与基础模型文件 (.gguf) 一样的目录中创建这个文本文件(例如 MyModelModelfile)。
Modelfile 内容示例:
# 使用 FROM 指向同一目录中的模型文件的相对路径
FROM ./local_model_filename.gguf
# (可选) 定义提示模板
TEMPLATE """[INST] {{ .Prompt }} [/INST]"""
# (可选) 设置参数
PARAMETER temperature 0.7
PARAMETER top_k 40
# 根据需要添加其他参数 (停止序列等)
使用选定的名称构建模型并将其注册到 Ollama:
# 确保 Ollama 服务器正在运行
# 导航到包含 Modelfile 和 .gguf 文件的目录
cd /path/on/server/models/
# 创建模型 - 使用一个描述性的名称
ollama create your_custom_model_name -f MyModelModelfile
验证模型是否可用:ollama list。
5. 设置环境变量
应用程序一般需要配置,如 API 密钥或数据库 URL,最好通过环境变量来管理。一种常见的方法是在项目的根目录中使用 .env 文件。切勿将 .env 文件提交到 Git。 将 .env 添加到.gitignore 文件中。
在项目根目录 (/path/to/your/project/.env) 创建一个名为 .env 的文件,内容类似这样(替换占位符值):
# 示例 .env 文件内容
# 框架密钥 (生成一个强随机密钥)
SECRET_KEY=your_strong_random_secret_key
# 外部服务的 API 密钥
EXTERNAL_API_KEY=your_external_api_key_value
# 如果应用需要显式连接 Ollama 的配置
OLLAMA_HOST=http://127.0.0.1:11434
# 其他配置变量
DATABASE_URL=your_database_connection_string
Python 应用程序代码需要加载这些变量,一般使用像 python-dotenv (pip install python-dotenv) 这样的库。
6. 手动运行项目 (测试)
在设置服务之前,从终端手动运行应用程序,以确保它能正确启动和运行。
-
确保 Ollama 正在运行: 使用
ollama list或systemctl status ollama(如果作为服务安装) 来验证。 -
激活环境 (如果使用 venv):
source /path/to/your/project/venv/bin/activate -
启动应用程序: 导航到项目根目录。使用像
uvicorn这样的 ASGI 服务器来运行 FastAPI。替换占位符。cd /path/to/your/project # 使用 uvicorn 的示例命令 # 假设 FastAPI 应用实例在 main.py 中名为 app # 使用应用配置监听的端口 uvicorn main:app --host 0.0.0.0 --port <your_app_port> --reload-
--host 0.0.0.0:使应用可以从网络上的其他机器访问(确保防火墙规则允许<your_app_port>端口的流量)。 -
--port <your_app_port>:应用程序将监听的端口(例如 8000)。 -
--reload:仅用于测试。 在代码更改时启用自动重新加载。对于生产部署,请移除此标志。
-
-
测试:
-
API 端点: 使用
curl、Postman 或 Insomnia 等工具发送请求(例如curl http://your_server_hostname_or_ip:<your_app_port>/api/some_endpoint)。 -
Web UI: 通过浏览器访问
http://your_server_hostname_or_ip:<your_app_port>上的任何 Web 界面。 - 日志: 检查终端输出以查找错误。
-
API 端点: 使用
使用 systemd 作为服务部署
在终端中手动运行应用程序不适合生产环境。systemd 是标准的 Linux 服务管理器,用于:
- 在服务器启动时自动启动应用程序。
- 在应用程序崩溃时自动重启。
- 将应用程序作为后台进程进行管理,并进行适当的日志记录。
创建服务文件
使用具有 sudo 权限的文本编辑器创建一个服务定义文件。使用描述性的名称(例如 your-app-name.service)。
sudo nano /etc/systemd/system/your-app-name.service
将以下模板粘贴到文件中。请仔细阅读注释并替换所有占位符。
[Unit]
Description=My Python AI Application Service # 服务的描述性名称
After=network.target
# 如果应用严格要求 Ollama 第一运行 (并且 Ollama 是一个 systemd 服务), 撤销注释:
# Wants=ollama.service
# After=network.target ollama.service
[Service]
# !!! 安全最佳实践:切勿以 ROOT 用户身份运行 !!!
# 为应用程序创建一个专用的非 root 用户。
# 将 your_app_user 替换为实际的用户名。确保此用户具有
# 读取项目文件和写入必要目录 (例如日志、上传文件) 的权限。
User=your_app_user
# Group=your_app_group # 一般与用户一样,如果需要则撤销注释
# 将工作目录设置为项目的根目录绝对路径
WorkingDirectory=/path/to/your/project # !!! 务必替换此绝对路径 !!!
# 启动应用程序的命令。使用可执行文件 (uvicorn, gunicorn 等) 的绝对路径。
# 查找路径: which uvicorn (以 your_app_user 身份, 可能在激活 venv 后)
# 或者可能是类似: /path/to/your/project/venv/bin/uvicorn 或 /home/your_app_user/.local/bin/uvicorn
# 调整 main:app , host, port, 和其他参数。移除 --reload!
ExecStart=/path/to/executable/uvicorn main:app --host 0.0.0.0 --port <your_app_port> --forwarded-allow-ips= * # !!! 务必替换路径, 应用, 端口并检查参数 !!!
# 重启策略
Restart=always
RestartSec=5 # 重启前等待 5 秒
# 日志记录: 将 stdout/stderr 重定向到 systemd journal
StandardOutput=journal
StandardError=journal
# 可选: 从 .env 文件加载环境变量
# 确保路径是绝对路径。权限必须允许 your_app_user 读取它。
# EnvironmentFile=/path/to/your/project/.env # !!! 务必替换此绝对路径 !!!
# 注意: 此处的变量可能会覆盖系统范围或用户特定的环境设置。
[Install]
WantedBy=multi-user.target # 在正常系统启动期间启动服务
需要验证的关键占位符和设置:
-
Description:一个清晰的名称。 -
User/Group:必须更改为一个专用的非 root 用户 (your_app_user)。确保此用户的文件/目录权限正确。 -
WorkingDirectory:项目根目录的绝对路径。 -
ExecStart:-
uvicorn(或其他 WSGI/ASGI 服务器)可执行文件的绝对路径。如果使用虚拟环境,一般在venv/bin/内。 -
main:app必须与 Python 文件和 FastAPI/Flask 应用实例匹配。 -
<your_app_port>、--host和其他参数必须适合生产环境。移除--reload。 - 如果位于反向代理(如 Nginx 或 Apache)之后,可能需要
--forwarded-allow-ips= *。根据安全需要进行调整。
-
- (可选)
EnvironmentFile:如果使用,指向.env文件的绝对路径。
保存文件并退出编辑器(在 nano 中按 Ctrl+X,然后按 Y,然后按 Enter)。
启用并启动服务
使用 systemctl 管理新服务:
-
重新加载
systemd配置: 使其知道新文件。sudo systemctl daemon-reload -
启用服务: 使其在启动时自动运行。使用创建的一样文件名。
sudo systemctl enable your-app-name.service -
启动服务: 立即运行它。
sudo systemctl start your-app-name.service -
检查状态: 验证它是否正在运行。
sudo systemctl status your-app-name.service查找
active (running)。如果显示failed或不是 active,请检查日志。 -
查看日志: 查看应用程序输出并排查错误。
sudo journalctl -u your-app-name.service -f-
-u your-app-name.service:过滤特定服务的日志。 -
-f:实时跟踪日志(类似tail -f)。按Ctrl+C停止跟踪。 - 要查看较早的日志,移除
-f:sudo journalctl -u your-app-name.service --since "1 hour ago"
-
AI 应用程序目前应该作为托管的后台服务运行了。
常见问题 (FAQ)
设置或运行时遇到的常见问题。
环境配置问题
-
SSH 连接/输入缓慢:
- 缘由: 网络延迟高。
-
解决方案: 使用
-C标志启用 SSH 压缩:ssh -C your_server_username@your_server_hostname_or_ip ...
运行时问题
-
缺少环境变量: 出现类似
KeyError: SECRET_KEY或ValueError: Required setting X not found的错误。- 缘由: 应用程序需要的环境变量在其运行上下文中未定义。
-
解决方案: 确保所需变量已设置,可以通过以下方式之一:
- 在
.env文件中,并且应用程序使用python-dotenv加载它。 - 或者在
systemd服务文件中使用Environment="VAR_NAME=value"指令(对于许多变量不太常见)或EnvironmentFile=指令指向.env文件。验证systemd服务用户是否有权限读取EnvironmentFile。更改后重新加载 (daemon-reload) 并重启服务。
- 在
-
Ollama 运行时错误:
Error: llama runner process has terminated: exit status X.- 缘由: 多种多样。可能是 Ollama 的 bug、模型所需的 RAM/VRAM 不足、模型文件损坏或不兼容。
-
解决方案:
- 检查 Ollama 的日志:
journalctl -u ollama.service(如果作为 systemd 服务运行)。 - 在 Ollama GitHub Issues 中搜索具体的错误消息或退出状态码。
- 确保服务器满足模型的资源需求。
- 尝试不同的(可能更小的)模型来隔离问题。
- 思考尝试不同的 Ollama 版本(降级或升级),检查兼容性说明。
- 检查 Ollama 的日志:
-
Ollama 响应缓慢/无响应/推理时间长:
-
缘由 1: 网络代理干扰。
解决方案 1: 如果手动运行 Ollama 或配置其环境,尝试撤销设置代理变量:unset http_proxy https_proxy NO_PROXY。对于systemd服务,可能需要在系统范围或服务环境设置中配置/禁用代理。 - 缘由 2: 硬件资源不足 (CPU, RAM, VRAM 如果使用 GPU)。
-
解决方案 2: 验证模型需求与服务器规格。监控资源使用情况 (
htop,nvidia-smi如果有 GPU)。如果需要,使用更小的模型或升级硬件。
-
缘由 1: 网络代理干扰。
-
ollama serve失败:端口已被占用: 出现类似listen tcp 127.0.0.1:11434: bind: address already in use的错误。- 缘由: 另一个进程(很可能是另一个 Ollama 实例或配置错误的应用程序)正在使用端口 11434。
-
解决方案: 停止冲突的进程。
- 如果 Ollama 是一个服务:
sudo systemctl stop ollama。 - 手动查找并终止:
sudo lsof -i :11434 # 查找使用该端口的 PID sudo kill <PID> # 将 <PID> 替换为找到的进程 ID # 或者更强制地 (谨慎使用): # sudo pkill ollama # sudo killall ollama- 停止冲突后,再次尝试启动服务/Ollama。
- 如果 Ollama 是一个服务:
结论
部署 Python AI 应用涉及仔细的环境配置、依赖管理、模型处理和健壮的进程管理。像 uv (提高速度)、Ollama (本地模型服务)、FastAPI (提供 API) 和 systemd (可靠的服务操作) 这样的工具提供了坚实的基础。请记住,通过使用非 root 用户并通过环境变量适当地管理密钥来优先思考安全性。通过遵循这些步骤并根据具体项目需求进行调整,可以成功部署应用程序以实现持续运行。



