1. 为什么 LiteLLM Proxy 的启动总在 Python 环境上翻车LiteLLM Proxy 是一个用 Python 写的本地模型网关它能把你手上一堆不同厂商的模型统一成 OpenAI 兼容接口对外只暴露一个/v1/chat/completions。适合谁适合本地要跑多个模型、又不想在每个客户端里重复填不同 Base URL 和 Key 的人。但真正卡住新手的往往不是配置本身而是启动那一刻litellm: command not found、ModuleNotFoundError、明明import得到却起不来服务。这些几乎全是 Python 环境没治理好。我见过太多项目把依赖装在系统 Python 里今天装个litellm明天装个fastapi版本互相打架最后连pip list都不敢看。LiteLLM Proxy 本身依赖不少litellm、fastapi、uvicorn、httpx、pydantic一串如果和系统里其他项目共用解释器升级一个包就可能把另一个项目搞崩。所以正确姿势是每个项目一个隔离虚拟环境依赖版本锁死启动命令走项目自己的解释器。这篇就围绕my-litellm-service这个项目结构来讲用uv创建隔离环境、锁定依赖再把 TaoToken 作为统一 Key/API 通道接进 LiteLLM 的config.yaml。TaoToken 官网是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 它的 API 入口是 https://taotoken.net/api 兼容 OpenAI 格式所以接进 LiteLLM 只需要在litellm_params里写api_base和api_key。下面从环境初始化一路走到/v1/models和一次 chat 请求验证命令都能直接复制。先明确一个容易混的点LiteLLM Proxy 是第三方包安装后提供的命令行入口不是你项目里的app/main.py。所以启动它用的是litellm --config config.yaml --port 4000而不是python main.py。项目里未来可能还有一个 FastAPI 业务服务那个才用uvicorn app.main:app --port 8000。两个服务职责不同启动方式也不同别混着用。2. 用 uv 初始化隔离环境并锁定依赖版本uv是这两年我用得最顺的 Python 环境与依赖管理工具它把虚拟环境创建、依赖解析、锁文件生成三件事合成一条命令。相比python -m venv加pip install的组合uv解析快、锁文件uv.lock可复现团队里每个人uv sync出来的环境基本一致。项目根目录假设是/home/gateman/projects/github/my-litellm-service结构里有app/、config.yaml、pyproject.toml、.env、.env.example、.venv/。第一步进项目目录并初始化。如果还没有pyproject.toml用uv init生成已经有的话直接同步依赖cd /home/gateman/projects/github/my-litellm-service uv init --python 3.12 uv venv --python 3.12uv venv会在项目下创建.venv/并绑定 Python 3.12。接着把运行依赖写进pyproject.toml这里给出和项目一致的依赖清单注意版本区间用加锁大版本避免某天自动升到不兼容的 2.x[project] name my-litellm-service version 0.1.0 requires-python 3.12,3.13 dependencies [ aiomysql0.2.0,1.0.0, fastapi0.115.0,1.0.0, httpx0.27.0,1.0.0, litellm1.74.0,2.0.0, pydantic-settings2.6.0,3.0.0, redis[hiredis]5.2.0,7.0.0, uvicorn[standard]0.32.0,1.0.0, ] [dependency-groups] dev [ pytest8.3.0,9.0.0, pytest-asyncio0.24.0,2.0.0, pyyaml6.0.0,7.0.0, ruff0.8.0,1.0.0, ]写完执行同步uv sync会读pyproject.toml、解析依赖、生成或更新uv.lock并把所有包装进.venvuv sync --dev--dev表示连[dependency-groups]里的开发依赖一起装。这里有个坑要提醒[dependency-groups]是 uv 的写法对应命令是uv sync --dev而pip install -e .[dev]用的是[project.optional-dependencies]的 extras 语法。两者概念都是“装开发依赖”但配置位置不同别把pip install -e .[dev]套到用[dependency-groups]的项目上会报找不到 extra。装完后确认litellm入口在哪uv run which litellm uv run litellm --versionuv run会自动使用项目.venv不需要手动source .venv/bin/activate也不会误用系统 Python。这一步过了说明环境隔离和依赖锁定都到位了。如果你更习惯传统方式也可以source .venv/bin/activate后用which python、which pip、which litellm确认三者都指向.venv/bin/而不是/usr/bin。3. 可复制的 config.yaml 与 .env 接入 TaoToken环境好了接下来是配置。LiteLLM 的模型路由写在config.yaml的model_list里每条包含对外暴露的model_name和底层litellm_params。接 TaoToken 的关键是model用openai/前缀因为 TaoToken 兼容 OpenAI 协议api_base指向 https://taotoken.net/api api_key从环境变量读避免明文进 Git。先写.env敏感信息都放这里.env.example只留占位# .env LITELLM_MASTER_KEYsk-local-master-please-change LITELLM_PORT4000 TAOTOKEN_API_KEYsk-your-taotoken-key注意LITELLM_MASTER_KEY是 LiteLLM 自己对外校验用的本地主 Key客户端调 LiteLLM 时带它TAOTOKEN_API_KEY才是真正发给 TaoToken 的上游 Key两者别搞混。然后写config.yamlmodel_list: - model_name: taotoken-gpt-4o-mini litellm_params: model: openai/gpt-4o-mini api_base: https://taotoken.net/api api_key: os.environ/TAOTOKEN_API_KEY - model_name: taotoken-claude litellm_params: model: openai/claude-3-5-sonnet api_base: https://taotoken.net/api api_key: os.environ/TAOTOKEN_API_KEY litellm_settings: drop_params: true general_settings: master_key: os.environ/LITELLM_MASTER_KEY这里model_name是对外别名客户端请求时填它litellm_params.model里的openai/前缀告诉 LiteLLM 走 OpenAI 兼容协议真正的模型名跟在斜杠后面。api_base统一指向 TaoToken 的 API 入口api_key用os.environ/语法从环境变量注入这样配置文件可以安全提交。drop_params: true让 LiteLLM 自动丢弃上游不支持的参数减少 400 报错。启动前把.env导出到当前 shellLiteLLM 才能读到这些变量cd /home/gateman/projects/github/my-litellm-service set -a source .env set a uv run litellm --config config.yaml --port $LITELLM_PORTset -a让后续source的变量自动导出set a关掉。如果你从其他目录启动配置路径要用绝对路径或者先切回项目根目录。启动日志里看到Uvicorn running on http://0.0.0.0:4000就说明起来了。这一步的 Base URL、Key、Model ID 三件套对应关系是客户端 Base URL 填http://127.0.0.1:4000Key 填LITELLM_MASTER_KEYModel ID 填taotoken-gpt-4o-mini这类别名。4. 验证 /v1/models 与一次 chat 请求服务起来后别急着发真实请求先做两个不花钱的检查。第一个是健康检查curl http://127.0.0.1:4000/health返回{status:healthy}之类就正常。第二个是模型列表验证配置有没有被正确加载curl http://127.0.0.1:4000/v1/models \ -H Authorization: Bearer $LITELLM_MASTER_KEY这个请求只读本地配置不会打到上游所以不产生模型调用费用。返回的data数组里应该能看到taotoken-gpt-4o-mini和taotoken-claude两个别名。如果这里报 401多半是LITELLM_MASTER_KEY没导出或和请求头不一致如果列表为空检查config.yaml路径和model_list缩进。确认无误后发一次真实 chat 请求这一步会走 TaoToken 到上游模型curl http://127.0.0.1:4000/v1/chat/completions \ -H Authorization: Bearer $LITELLM_MASTER_KEY \ -H Content-Type: application/json \ -d { model: taotoken-gpt-4o-mini, messages: [ { role: user, content: Reply with exactly: OK } ], max_tokens: 128 }注意model字段填的是对外别名taotoken-gpt-4o-mini不是openai/gpt-4o-mini。后者只写在litellm_params.model里。返回结构里应该有choices[0].message.content、model和usage三个关键字段。如果content是null且finish_reason是length说明max_tokens太小输出预算被内部 thinking 吃掉了把max_tokens调到 512 以上再试。用 Python 客户端验证也一样openaiSDK 把base_url指向本地代理即可from openai import OpenAI client OpenAI( base_urlhttp://127.0.0.1:4000, api_keysk-local-master-please-change, ) resp client.chat.completions.create( modeltaotoken-gpt-4o-mini, messages[{role: user, content: Reply with exactly: OK}], max_tokens128, ) print(resp.choices[0].message.content) print(resp.model, resp.usage)跑通这段说明从客户端到 LiteLLM 再到 TaoToken 的整条链路是通的。之后你要换模型只改config.yaml里的别名和底层模型名客户端代码一行不用动这就是本地代理的价值。5. 本篇常见报错排查401、command not found 与 choices 为空排障这块我按真实遇到的报错来对。第一个高频是litellm: command not found。原因通常是虚拟环境没激活或者litellm没装进当前环境。先确认which python python -m pip show litellm如果which python指向/usr/bin/python说明你在用系统解释器。改用uv run litellm --version或直接.venv/bin/litellm --config config.yaml --port 4000。第二种情况是代码能import但服务起不来比如from app.core.config import Settings成功litellm却报ModuleNotFoundError。这是因为 Python 把当前目录加进了模块搜索路径能找到你的源码不代表第三方依赖装好了。用uv sync补齐依赖即可。第二个是 401。分两种客户端调 LiteLLM 报 401是LITELLM_MASTER_KEY不匹配检查.env是否source过、请求头Bearer后面有没有多余空格。LiteLLM 调 TaoToken 报 401是TAOTOKEN_API_KEY无效或没导出确认config.yaml里写的是os.environ/TAOTOKEN_API_KEY且启动前执行了set -a; source .env; set a。如果报local proxy failed或连接超时检查api_base是不是写成了https://taotoken.net/api末尾不要多加/v1LiteLLM 会自己拼路径。第三个是reading choices相关报错通常是上游返回结构不符合预期或者max_tokens太小导致choices为空。先看完整响应体确认finish_reason。如果是length加大输出额度如果是上游 429 或 5xxLiteLLM 会透传错误码这时候要退避重试。还有一种OAuth类报错一般出现在用某些需要 OAuth 的 provider 时TaoToken 走的是 API Key 模式不会触发如果你混用了别的 provider 配置检查那条litellm_params是不是写错了前缀。第四个是测试长时间没结果。常见原因是进程没继承代理变量、代理地址不可达、或者没设客户端超时。终端跑测试前先set -a; source .env; set aIDE 的 pytest runner 不一定自动加载.env要么在 IDE 里显式配环境文件要么直接用终端跑。给请求加个timeout参数避免代理不可达时无限等待。6. 把 TaoToken 接进本地代理后的长期用法环境治理和接入都跑通后日常使用其实很轻。本地开发我推荐固定用uv run litellm --config config.yaml --port $LITELLM_PORT它自动用项目.venv依赖由uv.lock锁定换台机器uv sync就能复现。脚本化或交给服务管理器时用绝对路径.venv/bin/litellm --config config.yaml --port 4000不依赖 shell 激活状态。需要长期跑编码任务或 Agent 的话可以了解下 TaoToken 的 Coding Plan它更适合持续性的模型调用场景只是想验证某个模型效果用模型对话页面直接试更快要管理 Key 就去控制台。这几个入口分别是模型对话 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API Keys 管理 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。最后几个实用习惯.env永远不进 Git.env.example只留占位符uv.lock要提交保证团队环境一致每次改完config.yaml先打/v1/models确认别名加载再发真实请求真实 API 调用和真实 pytest 都显式执行控制费用。把这些固定下来LiteLLM Proxy 的启动就不再是玄学而是一条可复现的命令。