中文 ▾
NSFW Video Generator

用于成人视频管道的无审查 API

Python 免费 LLM:本地模型与托管 API

Python 免费 LLM 分为两类:你在自己机器上运行的开放权重模型,以及按几分钱计费的托管接口。本指南对比了两者,并提供了托管方案的可用代码。

更新于

本地机器连接到托管服务器集群的等距插图,对比本地和托管 LLM

要点

  1. 本地开放权重模型每个 token 成本为零,但需要内存、设置时间和维护。
  2. 托管 API 兼容 OpenAI:安装 openai 包,设置 base URL,使用模型 ID uncensored。
  3. 流式输出、函数调用和 JSON 模式均可通过标准的 chat completions 调用实现。
  4. 试用 API 密钥提供 $0.50 的额度,有效期 7 天,支持 2 个并发请求和每分钟 60 个请求。

将免费 LLM 引入 Python 脚本的两种方式

当人们搜索 Python 免费 LLM 时,通常指两种情况。第一种是你下载并自行运行的开放权重模型,使用 Ollama、llama.cpp 或 Hugging Face transformers 库等工具。第二种是托管接口,其成本极低或提供足够的试用额度,使其在原型开发中感觉免费。两者均合理,适用于不同场景。

本地运行意味着无需按 token 计费,数据也不会离开你的机器。这也意味着你需要为所选模型配备足够的 RAM 或 GPU 显存,需要等待下载,且能装进笔记本电脑的小型模型回答效果不如大型模型。托管 API 消除了硬件需求,但试用额度用完后需按 token 付费。本页诚实地介绍两者,然后展示本站托管选项的 Python 代码,该接口兼容 OpenAI,可与标准 openai 包配合使用。

本地模型与托管 API 对比

问题自行运行托管预付 API
每个 token 的成本无,但需支付硬件和电力费用每 1M 输入 token $0.15,每 1M 输出 token $0.50
设置时间安装运行时,下载权重,调整设置安装一个包,粘贴密钥
上下文长度受你的内存限制100,000 token,包含提示词和补全
并发取决于你的机器处理能力完整密钥支持 8 个并发请求,试用密钥支持 2 个
拒绝响应取决于你选择的权重针对合法的成人使用进行无内容拒绝调优
离线使用是否

如果你有性能强大的 GPU 且工作涉及隐私或离线,本地方案是很好的选择,你可以停止阅读。如果你想要更大的模型而无需拥有硬件,或希望脚本在笔记本、服务器和 CI 运行器上表现一致,托管方案更简单。许多项目同时使用两者:开发时使用小型本地模型,生产时使用托管模型,只需更改一个 base URL 即可切换。

五分钟内设置托管接口

你需要先获取密钥。使用 Google 或电子邮件和密码注册,然后在 API 密钥页面 一键领取 $0.50 试用额度。试用有效期 7 天,每人限领一次,无需付款。然后安装 SDK 并将密钥保留在源代码之外。

pip install openai
export NOTRACK_API_KEY="sk-your-key-here"

客户端需要从标准 OpenAI 设置中进行两项更改:base URL 和密钥。模型 ID 为 uncensored,仅提供一种模型。

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.nsfwvideogenerator.cc/v1",
    api_key=os.environ["NOTRACK_API_KEY"],
)

resp = client.chat.completions.create(
    model="uncensored",
    messages=[
        {"role": "system", "content": "You are a concise writing assistant."},
        {"role": "user", "content": "Give me three title ideas for a noir short story."},
    ],
    temperature=0.8,
)

print(resp.choices[0].message.content)
print(resp.usage)

认证使用标准的 Authorization: Bearer 头,SDK 会自动为你添加。有两种方法:POST /v1/chat/completions 和 GET /v1/models。你可以通过 client.models.list() 确认连接,该调用返回可用的模型 ID。完整参数列表见 文档页面。

流式响应

对于用户交互的内容,使用流式输出。设置 stream=True 并在服务器发送事件到达时遍历数据块。流结束时报告使用情况,因此你仍可记录 token 数量。

stream = client.chat.completions.create(
    model="uncensored",
    messages=[{"role": "user", "content": "Write a four-line poem about rain on a tin roof."}],
    stream=True,
)

for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    usage = getattr(chunk, "usage", None)
    if usage:
        print("\n", usage)

一个细节容易让人忽略:流式请求会占用其并发槽位,直到流结束。对于有 2 个槽位的试用密钥,两个打开的流意味着第三次调用会收到带有代码 concurrency 的 429 错误。务必消费或关闭流。

工具调用和 JSON 模式

该接口支持 tools、tool_choice、流式 tool_calls 以及以 role: "tool" 形式返回的结果。这里有一个包含一个函数的完整往返示例。

import json

tools = [{
    "type": "function",
    "function": {
        "name": "word_count",
        "description": "Count the words in a piece of text.",
        "parameters": {
            "type": "object",
            "properties": {"text": {"type": "string"}},
            "required": ["text"],
        },
    },
}]

messages = [{"role": "user", "content": "How many words are in: the quick brown fox jumps"}]
first = client.chat.completions.create(
    model="uncensored", messages=messages, tools=tools, tool_choice="auto"
)
msg = first.choices[0].message

if msg.tool_calls:
    messages.append(msg)
    for call in msg.tool_calls:
        args = json.loads(call.function.arguments)
        result = len(args["text"].split())
        messages.append({
            "role": "tool",
            "tool_call_id": call.id,
            "content": str(result),
        })
    final = client.chat.completions.create(model="uncensored", messages=messages, tools=tools)
    print(final.choices[0].message.content)

务必防御性地解析 arguments;模型将其作为 JSON 字符串返回,且任何模型偶尔都会生成格式错误的字符串。对于不使用工具的结构化输出,请使用 JSON 模式。

resp = client.chat.completions.create(
    model="uncensored",
    messages=[
        {"role": "system", "content": "Reply with a JSON object with keys title and tags (list of strings)."},
        {"role": "user", "content": "Describe a lighthouse keeper's diary."},
    ],
    response_format={"type": "json_object"},
    temperature=0.2,
)
data = json.loads(resp.choices[0].message.content)
print(data["title"], data["tags"])

提及 JSON 并在提示词中命名键,同时保持低 temperature。在生产代码中,将 json.loads 包裹在 try 块中。

速率限制、错误和重试

完整密钥允许 8 个并发请求和每分钟 300 个请求。试用密钥允许 2 个和 60 个。超过限制时,你会收到 HTTP 429 错误,代码为 rate_limited(每分钟过多)或 concurrency(同时过多)。在临时过载时,API 还会返回 429,并带有 Retry-After: 5 头。SDK 会自动重试某些错误;对于扇出脚本,使用小型显式包装器更清晰。

import time
from concurrent.futures import ThreadPoolExecutor
from openai import RateLimitError

def ask(prompt, tries=4):
    for attempt in range(tries):
        try:
            r = client.chat.completions.create(
                model="uncensored",
                messages=[{"role": "user", "content": prompt}],
                max_tokens=300,
            )
            return r.choices[0].message.content
        except RateLimitError:
            time.sleep(5 * (attempt + 1))
    raise RuntimeError("still rate limited")

prompts = [f"Summarize idea number {i} in one sentence." for i in range(20)]
with ThreadPoolExecutor(max_workers=2) as pool:   # 8 on a full key
    results = list(pool.map(ask, prompts))

将 max_workers 匹配到你的密钥的并发限制,可在大多数 429 错误发生前防止它们。每个响应还包含 X-Request-Id、X-Balance-USD 和两个速率限制头,你可以在需要调试或支持时通过 client.chat.completions.with_raw_response.create(...) 读取它们。

如何选择本地模型与托管 API

抛开意识形态,回答关于项目的四个问题。

  1. 数据必须保留在你的机器上吗? 如果合同或习惯要求如此,请在本地运行。托管的提示词在此不用于训练,但它们确实会通过网络传输。
  2. 你有多少内存? 模型大小决定质量。没有专用 GPU 的笔记本电脑会将你限制在小模型上,并且答案会显示出这一点。托管模型为你提供具有 100,000 token 上下文窗口的大模型,这在本地很难匹配。
  3. 你将发送多少请求? 每周几百个请求在任何情况下都微不足道。每月数十万请求会使托管账单变成具体金额,如果本地服务器闲置,本地部署就会显得有吸引力。计算一下:100,000 个请求,每个请求 1,000 个输入 token 和 500 个输出 token,费用为 100,000 x $0.0004 = $40。
  4. 你需要以特定方式处理拒绝吗? 许多开放权重模型自带内置的拒绝行为,其他模型则经过调整以消除它。这里的托管模型经过调整,以便在合法成人使用时无需内容拒绝即可回答,因此你不需要寻找正确的权重。

如果你的答案指向两者,请先从托管开始一周。试用免费,你将了解提示词的需求,然后再购买硬件或下载另一个多 GB 文件。

Python 脚本中的常见错误

人们遇到的大多数问题都是小问题且可修复。

  • 错误的 Base URL。 它必须以 /v1 结尾。缺少后缀会导致 404,而不是有用的消息。如果有疑问,请打印 client.base_url。
  • 密钥在代码中。 如上所述从环境变量中读取它,并将你的 .env 文件添加到 .gitignore。
  • 错误的模型名称。 唯一的模型 ID 是 uncensored。其他提供者的名称将不起作用,因此在移植代码时请更改它们。
  • 无界循环。 永不结束的调用工具循环是一个昂贵的错误。将其限制在,例如,五轮。
  • 忽略上下文预算。 提示词和完成共享 100,000 个 token。如果你永远附加每一轮,你最终会达到限制。修剪或总结旧消息。
  • 假设 JSON 总是有效的。 即使在 JSON 模式下,在使用之前也要检查你需要的键。

当服务器端出现异常时,在联系 支持 时引用响应中的 X-Request-Id 值。这能让运营人员找到你的具体调用。

托管选项在 Python 工作中的成本

典型脚本调用,包含 1,000 个输入和 500 个输出 token,成本为 $0.00015 加上 $0.00025,即 $0.0004。$0.50 的试用额度大约可以覆盖 1,250 次调用。$20 的充值(最低额度)可以覆盖 50,000 次。额度永不过期,失败或被拒绝的请求不收费,且提示词不用于训练。充值最高可达 $500,从 $50 起有奖金,支付方式为加密货币,TRC20 上的 USDT 或 Base 上的 USDC。详见 定价页面。

仅限文本:无图像、音频、视频、嵌入或微调。唯一的硬性规则是不涉及未成年人的色情内容。对于需要更少拒绝的文本生成的 Python 项目,这就是全部功能。

问答

我需要哪个 Python 包?

官方 openai 包。将 base_url 设置为 https://api.nsfwvideogenerator.cc/v1,,将密钥作为 api_key 传入,并使用模型 ID uncensored。

我可以使用 LangChain 或其他框架吗?

任何允许设置 OpenAI 兼容 Base URL 和 API 密钥的客户端都应该可以工作,因为 API 遵循 chat completions 格式。将其指向 Base URL 并使用 uncensored 作为模型名称。

免费的本地模型与托管模型一样好吗?

这取决于模型和你的硬件。能装在笔记本电脑上的模型通常比大型托管模型更小、更弱,但它们每个 token 的成本为零,并且可以离线工作。

我如何在 Python 中避免 429 错误?

将工作线程数保持在并发限制以内(试用密钥为 2,完整密钥为 8),并在收到 rate_limited、concurrency 或 Retry-After: 5 响应后稍作休眠再重试。

只差一张表单,即可获得密钥

创建账户,复制密钥,更改基础 URL。这就是全部设置。