Python 编程最佳本地 LLM:本地还是托管 API?
没有单一的赢家,因为最佳选择取决于你的 GPU、你的任务以及模型拒绝回答的频率。以下是如何做出决定,以及在本地硬件不足时如何测试托管选项。

要点
- 在你的实际任务上评估编码模型:Python 版本、库、仓库大小以及它处理测试的方式。
- GPU 内存设定了本地模型的上限。在 4 位量化下,权重每个参数大约需要半字节,加上上下文的空间。
- 本网站是一个托管 API,而非本地运行时。它拥有 100,000 token 的上下文窗口,每 1M token 费用为 $0.15 和 $0.50。
- 小型测试套件和试用密钥比任何排行榜都能告诉你更多。
从你的约束条件开始,而不是模型名称
Python 编程的最佳本地 LLM 这个问题没有固定答案,因为模型更新很快,而你的机器才是真正的限制。在比较名称之前,写下四件事:
- GPU 内存。这决定了你能运行哪些规模的模型。
- 上下文需求。编辑一个函数与在一个整个包上进行推理是不同的。
- 隐私规则。有些代码不能离开你的机器,这是留在本地的正当理由。
- 拒绝容忍度。安全工具、爬虫、逆向工程和模糊测试器可能会触发重度过滤模型的拒绝。
如果严格离线运行是硬性要求,你需要自己运行一个模型。如果不是,托管 API 就消除了硬件问题。该网站属于第二类:它是一个托管的、与 OpenAI 兼容的 API,而不是本地运行时,值得与你的本地环境一起测试。
你需要多少 GPU 内存
权重的粗略规则:参数数量乘以每个参数的字节数。16 位精度下每个参数 2 字节;8 位下 1 字节;4 位下约 0.5 字节。
| 模型大小 | 16 位 | 8 位 | 4 位 |
|---|---|---|---|
| 7B | 14 GB | 7 GB | 3.5 GB |
| 14B | 28 GB | 14 GB | 7 GB |
| 32B | 64 GB | 32 GB | 16 GB |
这些数字仅指权重。你还需要上下文缓存的内存,它会随提示词增长,以及运行时的内存。留出几 GB 的余量,如果你计划粘贴大文件,则需要更多。更重的量化可以节省内存,但可能会损失一些准确性,这对于代码很重要,因为一个错误的字符就会导致程序崩溃。
如何公平地比较编码模型
公共排行榜衡量的是别人的任务。更好的方法需要一小时,并使用你自己的代码。
- 收集 15 到 20 个真实任务:一个带有失败测试的 bug、一个根据文档字符串编写的函数、一个重构任务、一个添加类型提示的请求。
- 使用相同的提示词、相同的温度(对于代码,0.2 是一个合理的起点)以及在支持的模型上使用相同的种子运行每个模型。
- 通过运行测试来评分,而不是阅读答案。它是否导入了真实的模块?它是否通过了测试?
- 单独记录拒绝情况。一个在代码上好 5% 但拒绝你的端口扫描器任务的模型,对你来说更差。
- 记录每个任务的时间以及托管模型每个任务的成本。
将测试框架保存在文件中,以便在新模型出现时可以重新运行。这种复用比任何单次结果都更有价值。
在相同任务上测试托管选项
由于 API 与 OpenAI 兼容,你的测试框架只需要不同的 base URL。此脚本请求一个函数,提取第一个 Python 代码块并将其针对测试运行。模型 ID 为uncensored。
import re
import subprocess
import tempfile
from openai import OpenAI
client = OpenAI(base_url="https://api.uncensoredlocalllm.com/v1", api_key="YOUR_API_KEY")
TASK = "Write a Python function parse_size(text) that converts '10KB' or '2 MB' to bytes."
TEST = "assert parse_size('10KB') == 10240\nassert parse_size('2 MB') == 2 * 1024 * 1024\nprint('ok')"
r = client.chat.completions.create(
model="uncensored",
temperature=0.2,
seed=7,
messages=[
{"role": "system", "content": "You write correct Python 3. Reply with one fenced code block and no commentary."},
{"role": "user", "content": TASK},
],
)
text = r.choices[0].message.content
m = re.search(r"```(?:python)?\n(.*?)```", text, re.S)
code = m.group(1) if m else text
with tempfile.NamedTemporaryFile("w", suffix=".py", delete=False) as f:
f.write(code + "\n" + TEST)
out = subprocess.run(["python3", f.name], capture_output=True, text=True, timeout=20)
print(out.stdout.strip() or out.stderr.strip())
将相同任务列表针对你的本地模型运行并比较通过率。代码会运行生成的输出,因此对于超出玩具示例的内容,请使用一次性目录或容器。
托管模型在哪些场景下能帮到 Python 开发者
托管接口并非在所有情况下都更优,但以下几类任务非常适合它:
- 大上下文。 上下文窗口为 100,000 token,包含提示词和输出。这足以容纳一个较大的模块、其测试代码以及堆栈跟踪信息,全部在一个请求中完成。
- 函数调用。 你可以定义诸如
run_tests或read_file之类的工具,让模型在循环中调用它们,并将结果作为role: "tool"消息返回。 - JSON 模式。 使用
response_format: {"type":"json_object"}你可以获得结构化的代码审查结果,例如带有行号的问题列表。 - 安全任务拒绝更少。 该模型经过调整,可在合法成人用途下无内容审查地回答,包括对你拥有或获授权测试的系统进行安全测试。
权衡很明显:你的代码会离开你的机器,且你需要网络连接。提示词不会用于训练,但如果你的策略禁止将代码发送给任何第三方,请留在本地运行。
让模型通过函数调用运行你的测试
函数调用将一次性回答转变为循环:模型要求运行测试,看到失败并修复代码。定义一个工具并自行处理调用。
import json
import subprocess
from openai import OpenAI
client = OpenAI(base_url="https://api.uncensoredlocalllm.com/v1", api_key="YOUR_API_KEY")
tools = [{
"type": "function",
"function": {
"name": "run_tests",
"description": "Run pytest in the project and return the output",
"parameters": {"type": "object", "properties": {}, "required": []},
},
}]
messages = [
{"role": "system", "content": "You fix Python bugs. Call run_tests to check your work."},
{"role": "user", "content": "The tests in this project fail. Run them and tell me the first error."},
]
for _ in range(5):
r = client.chat.completions.create(model="uncensored", messages=messages, tools=tools, temperature=0.2)
msg = r.choices[0].message
messages.append(msg)
if not msg.tool_calls:
print(msg.content)
break
for call in msg.tool_calls:
out = subprocess.run(["pytest", "-x", "-q"], capture_output=True, text=True)
messages.append({"role": "tool", "tool_call_id": call.id, "content": (out.stdout + out.stderr)[-4000:]})
循环限制在五轮以内,以防模型陷入无限循环。保持工具输出简短,因为你返回的所有内容都会在下一轮作为输入计费。将其截断为最后 4,000 个字符可使每轮成本更低。
编码工作的成本
编码提示词通常输入量大:你粘贴代码,得到较短的回答。以一个包含 6,000 个输入 token 和 1,500 个输出 token 的重构请求为例,输入价格为每 1M token $0.15,输出价格为每 1M token $0.50:
- 输入:6,000 / 1,000,000 x $0.15 = $0.0009
- 输出:1,500 / 1,000,000 x $0.50 = $0.00075
- 总计:每次请求 $0.00165
一千次此类请求成本为 $1.65。$0.50 的试用额度大约可支持 303 次请求,足以多次运行包含 20 个任务的基准测试。在大量使用时,本地 GPU 每次请求的成本可能更低,但它有前期投入成本,且在你未使用时无法缩减为零。定价页面 有完整的表格。
代码生成的实用设置
- Temperature 0.1 到 0.3。 较低的值可减少虚构的 API 和随机的风格变化。
- 固定 seed 当你比较提示词时,以便差异仅来自提示词而非采样。
- 在系统消息中声明 Python 版本和库:"Python 3.11, standard library only" 可消除大量猜测。
- 要求附带测试代码。 能自行编写测试的模型在运行测试时,往往能发现自身的边界错误。
- 发送失败的堆栈跟踪,而不是对其的描述。
要尝试,请在 API 密钥页面 领取试用,然后遵循 快速入门。对于聊天式使用,请参阅 无审查 LLM 聊天指南。该服务适用于合法成人用途,且不会生成涉及未成年人的色情内容。
编码模型的常见误区
- 虚构的导入和函数名。 运行代码。模型可能会描述一个不存在的库方法,因此测试是唯一的判断标准。
- 过时的语法。 如果你需要现代功能(如结构模式匹配),请在提示词中指明 Python 版本。
- 上下文过多。 更大的窗口并不意味着你应该粘贴所有内容。发送关键文件以及错误信息。
- 信任生成的安全码。 人工审查任何涉及身份验证、加密或输入解析的内容。
- 盲目运行输出。 生成的代码可能会删除文件或发起网络调用。请使用沙箱。
更多指南
问答
哪个本地 LLM 最适合 Python 代码?
这取决于你的 GPU 内存和任务,因此请在你自己的代码上测试两三个适合你硬件规模的模型,并通过运行测试来评分。排行榜仅作为起点。
这个网站是本地 LLM 吗?
不是。它是一个托管的、OpenAI 兼容的 API,模型 ID 为 uncensored。如果你可以将代码发送到远程服务,它适合你。
运行 14B 模型需要多少 GPU 内存?
仅权重部分:16-bit 约需 28 GB,8-bit 约需 14 GB,4-bit 约需 7 GB,此外还需要额外的上下文缓存空间。
我可以从现有的 Python 工具中使用它吗?
可以。一旦你将 Base URL 设置为 https://api.uncensoredlocalllm.com/v1 并使用你的密钥,任何 OpenAI SDK 或客户端均可工作。
我如何免费测试?
注册后在 API 密钥页面领取 $0.50 试用额度。有效期为 7 天,无需填写支付信息,每人限领一次。