Skip to main content

为什么世界还缺少一个 llm_requests

如果你是一名LLM开发者,你可能遇到过这样的困扰:明明在软件开发领域自己有了一个想法之后可以借助各种开发工具快速搭建一个模型来验证自己的想法或者向别人展示。但是到了LLM开发领域却有许多的脏活需要处理。依据API文档慢慢实现模型请求的代码?好在后来有了API网关解决了这个问题。想快速构建一个应用?似乎LangChain可以解决这个问题,但繁杂的文档却要求你先花一段学习如何使用它。而当你想实现一些特殊需求时,其高度封装的API成为了另一个阻碍。

如果你是一名LLM研究者,你可能遇到过这样的困扰:自己的方法需要在大量的模型上对比大量的方法,可能不同的方法上还要去考虑不同的推理配置对结果的影响,如解码超参数、是否开启推理等。而且pass@k等指标的计算还要求多次重复实验。大模型推理很贵,你希望能够缓存模型的输出结果,以减少实验的消耗。前者需要能够方便地在全局设置LLM请求的一些参数,后者需要一个工具来管理模型的输出结果。

——在LangChain之下、LLM网关之上,LLM开发领域似乎还缺少一个类似requests的工具,它仅仅封装模型请求的脏活累活,而把其他一些内容暴露给使用者,使开发者能够在其之上便捷地构建下游应用。

于是便有了llm_requests。它通过以请求体为中心的设计,把模型(Model)、推理平台(Infrastructure)、推理设置(policy)和推理参数(Params)作为一等公民,让使用者能够在不同的对象间自由组合、快速配置。

QuikStart

在模型请求前,应在.config/llmrequest/{infra-name}.json中配置请求网址和key:

{
    "api_key": "none",
    "base_url": "http://127.0.0.1:8080/"
}

单次请求

from llm_requests import LLMRequester
from llm_requests.infras.llamacpp import gemma4_e2b

requester = LLMRequester()
print(requester.request(gemma4_e2b, "介绍一下你自己。"))

批次请求

批次请求用于并行进行多次请求,并行度取决于平台支持的上限。此外,为了防止重复请求,该方式可以接收一个缓存文件。 当缓存文件中包含当次请求的输入和参数时直接调用缓存的结果。

from llm_requests import LLMRequester
from llm_requests.infras.llamacpp import gemma4_e2b

requester = LLMRequester()
print(requester.request_batch(gemma4_e2b, "介绍一下你自己。", batch_size=10, cachefile=".test.json"))

我们把模型的输出结果封装在了LLMRequestResult类中,它包含一次推理涉及的所有信息:

model: Model(name='gemma4-e2b', infra_name='llama.cpp', released_date='2026-04-02', support_reasoning=True, inference_params=InferenceParams(enable_reason=True, max_tokens=20000, reasoning_effort=1))
contexts: [{'role': 'user', 'content': [{'type': 'text', 'text': '介绍一下你自己。'}]}]
output: 您好!很高兴向您介绍我自己。 ...
input_length: 20
output_length: 627
reasoning_output: Thinking Process:  ...
reasoning_length: 0
inference_time: 11.822667500004172
is_ooc: False
is_stop_by_length: False
appendix: {}
response_msgs: ChatCompletionMessage(...)
tool_calls: None

自定义模型

我们在每个推理设施中封装了一些常用的模型。除此之外,我们还提供自定义模型:

from llm_requests import LLMRequester, Model, InferenceParams

inference_param = InferenceParams(enable_think=True, max_tokens=5)
model = Model(name="gemma4-e2b", infra_name="llama.cpp", released_date="2026-04-02",
              support_reasoning=True, inference_params=inference_param)
requester = LLMRequester()
print(requester.request(gemma4_e2b, "介绍一下你自己。"))

Callback

Callback功能用于对模型的输出结果进行后处理。结果会放在LLMRequestResult.appendix中。在实验中,callback经常用于对模型的输出结果打分。在开发中,可以通过此功能追踪LLM的用量信息或对模型的输出内容添加审查。

from llm_requests import LLMRequester, register_callback, LLMRequestResult
from llm_requests.infras.llamacpp import gemma4_e2b
from llm_requests.utils import extract_code_block
from forging_utils.code_runner import execute_code, LANG_TYPE

@register_callback("code")
def run_code(r: LLMRequestResult) -> dict:
    code = extract_code_block(r.output)
    result = execute_code(code, LANG_TYPE.Python)
    return {"code": result.stdout}


requester = LLMRequester(callbacks=[run_code])
print(requester.request(gemma4_e2b, "请你编写一个Python代码输出三三乘法表。").appendix["code"])
--------------------------------
2026-09-11 21:05:21.390 | INFO     | forging_utils.code_runner:_init_client:435 - SingletonCodeRunner client initialized
2026-09-11 21:05:22.961 | INFO     | forging_utils.code_runner:try_to_launch:210 - podman run -d --name bench-web-1789131921 --workdir /home/ubuntu/code_runner -P --memory="2g" --memory-swap="2g" --cpus="1" --pids-limit=10000 localhost/bench:1.3.2 /home/ubuntu/env_code_runner/bin/python3 -m gunicorn --workers=1 --threads=4 --bind=0.0.0.0:8000 --timeout 120 server:app
2026-09-11 21:05:22.962 | INFO     | forging_utils.code_runner:try_to_launch:211 - 783d1e
2026-09-11 21:05:24.189 | INFO     | forging_utils.code_runner:start_server:164 - [783d1e]start at http://192.168.239.131:34763/
1 * 1 = 1
1 * 2 = 2; 2 * 2 = 4
1 * 3 = 3; 2 * 3 = 6; 3 * 3 = 9
2026-09-11 21:05:26.476 | INFO     | forging_utils.code_runner:terminal:263 - [783d1e] terminal, has del it
2026-09-11 21:05:26.476 | INFO     | forging_utils.code_runner:_shutdown_client:444 - CodeRunner client shutdown

全局开关

全局开关用于设置一些不方便通过参数设置的内容,如requester已经被框架封装在最里面时。以下代码常用于确保模型请求时读取缓存文件,而不是去发起新的请求。所有可配置的开关可参考llm_requests.policy。

from llm_requests import LLMRequester
from llm_requests.infras.llamacpp import gemma4_e2b
from llm_requests.policy import change_policy

requester = LLMRequester()
with change_policy(requests_allow_real=False):
    print(requester.request(gemma4_e2b, "请你介绍一下你自己。。").output)
--------------
...
    raise dtypes.NotAllowedRequestError()
llm_requests.dtypes.NotAllowedRequestError

工具调用

我们的框架支持简单地配置工具,你可以使用log_tool_calls开关来观察模型调用工具的情况。

from llm_requests import LLMRequester
from llm_requests.infras.llamacpp import gemma4_e2b
from llm_requests.dtypes import ToolParams
from llm_requests.policy import change_policy
from llm_requests.tools import print_to, ask

requester = LLMRequester()
tool_params = ToolParams(tools=[print_to, ask])
with change_policy(log_tool_calls=True):
    requester.request(gemma4_e2b, "请你用工具和我聊三句话。", tool_params=tool_params)

添加推理平台

我们把推理平台抽象为Infrastructure类,只需要实现相应平台的接口即可接入新的平台。具体内容可以参考llm_requests.infras下的文件。

利用内容块管理模型输入

我们使用内容块封装不同类型(文本、图片、音频和视频)的输入,以屏蔽平台间的web请求协议的差异。目前我们支持文字、图片、音频、视频四种输入类型。

对于流式输入类型(如音频、视频),我们支持对内容块进行切片:

from llm_requests import LLMRequester, dtypes
from llm_requests.infras.llamacpp import gemma4_e2b

requester = LLMRequester()
block = dtypes.VidioContentBlock.from_bilibili(your_url)

print(requester.request_content(gemma4_e2b, contents=[
    dtypes.SystemContentBlock(), dtypes.TextContentBlock("这个视频里的男人说了什么?"),
    block.slice(1, 30),
    ]).output)

对于视频类型,我们支持获取其音频内容块:

dtypes.VidioContentBlock.from_bilibili(your_url).to_audio()。

Metadata

Release files for llm-requests 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for llm-requests 1.0.0
File Size Uploaded
llm_requests-1.0.0.tar.gz 27.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for llm-requests 1.0.0
File Interpreter ABI Platform
llm_requests-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 58.9 kB

Release files / llm_requests-1.0.0.tar.gz

Download URL llm_requests-1.0.0.tar.gz
Size 27.7 kB
Tags Source
SHA-256 checksum
How to use checksums
05e6ef613d13736e80e10dbefb4b447d16d691a8fbc12c911a24c0c911ccb560
BLAKE2b-256 checksum
How to use checksums
aa4a281135c40d171c93c6b57f7cd029a6fa8aa95fa31309226dea894c6473c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.13

Release files / llm_requests-1.0.0-py3-none-any.whl

Download URL llm_requests-1.0.0-py3-none-any.whl
Size 31.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7f1a1eb708910e41392998a9c8cdb28689dd2c4b10c4ddec9ec3938607b28baa
BLAKE2b-256 checksum
How to use checksums
35e89126129c9f1ebc48e33653273e6719915d5098d0da20d9aeb8e99880296c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.13

Release history Release notifications | RSS feed

1.0.1

2 release files

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page