Python API¶
本页介绍只获取候选工具、可选的云端 embedding/混合检索,以及通用大模型调用。均可直接在 Python 中使用,无需安装或启动 MCP,也无需安装 Agent 可选依赖。工具检索默认使用本地关键词匹配,不需要 API key。
安装 DNAKit 核心包即可:
如需接入支持 MCP 的客户端,请参阅 MCP。
自然语言驱动的 run_agent()、Python 补充执行、工具生成与优化、本地结果缓存及知识库检索(RAG)见 Agent 页面,其中提供开关、参数、示例与执行限制。
1) 只获取候选工具,不执行任务¶
其他程序只想知道“可以使用哪些工具”时,直接调用 registry.search(),无需运行 run_agent():
from dnakit.tools import default_tool_registry
registry = default_tool_registry()
tools = registry.search("download human hg38 reference genome", limit=3)
print([tool.to_summary() for tool in tools])
返回按相关性排序的 AgentToolSpec 元组;to_summary() 提供工具名称、功能描述、分类等信息。这里仅查询本地工具目录,不调用聊天模型、不下载 hg38,也不执行候选工具。关键词模式建议使用英文功能词或函数名称,limit 默认为 20,可设置为 1–100。
需要查看完整参数 Schema 时,单独调用:
工具执行是另一个步骤,由调用方决定是否使用 registry.execute()。单独运行 search() 或 describe() 不会触发它。
2) 关键词、云端 embedding 与混合检索¶
六种模式共用 registry.search(),返回格式相同,默认始终是 keyword。即使配置了 embedding 服务,省略 mode 也不会联网。
mode |
检索方式 | 是否调用 embedding API |
|---|---|---|
keyword(默认) |
匹配工具名称、功能短说明、中英文分类 | 否 |
semantic |
将查询和上述工具描述转成向量,按余弦相似度排序 | 是 |
hybrid |
合并关键词排名和语义排名 | 是 |
bm25 |
本地 Okapi BM25 词项检索 | 否 |
bm25_hybrid |
BM25 与语义排名的等权 RRF 融合 | 是 |
rerank |
BM25+Dense 召回固定候选池,再通过独立重排 API 排序 | 是,另调用重排 API |
混合检索使用等权倒数排名融合(RRF,k=60),完整函数名或短函数名的精确匹配优先。分类 category 和 include_python_only 过滤在检索前生效。空白查询用于列出工具,或分类过滤后没有候选时,不请求 embedding API。向量模式返回最相近的候选,不保证候选一定能完成需求;执行前仍需查看 Schema。
配置独立的云端 embedding 服务¶
支持 OpenAI-compatible POST /embeddings 文本向量接口;不需要安装 OpenAI SDK、PyTorch、向量数据库或本地 embedding 模型。可接入提供该兼容接口的服务,例如阿里云百炼文本向量 API。私有协议不自动适配。
先在终端或 PyCharm 运行配置中填写以下环境变量,将占位值替换为自己账户的实际配置:
export DNAKIT_EMBEDDING_BASE_URL="https://your-embedding-service.example/v1"
export DNAKIT_EMBEDDING_MODEL="your-text-embedding-model"
export DNAKIT_EMBEDDING_API_KEY="your-embedding-api-key"
BASE_URL 填 API 前缀,DNAKit 自动追加一次 /embeddings,也接受完整的该接口地址。选择支持中英文语义检索的文本 embedding 模型。这里的配置与 LLMConfig、DEEPSEEK_API_KEY 相互独立,不会自动使用聊天模型或聊天密钥。
import os
from dnakit.tools import AgentToolRegistry, EmbeddingConfig
registry = AgentToolRegistry(embedding_config=EmbeddingConfig(
model=os.environ["DNAKIT_EMBEDDING_MODEL"],
base_url=os.environ["DNAKIT_EMBEDDING_BASE_URL"],
))
tools = registry.search("下载人类 hg38 参考基因组", mode="semantic", limit=3)
print([tool.to_summary() for tool in tools])
仅获取混合检索候选:
tools = registry.search("下载人类 hg38 参考基因组", mode="hybrid", limit=3)
print([tool.to_summary() for tool in tools])
回到默认关键词检索只需省略 mode,仍然不执行任务:
缓存与请求参数¶
首次语义/混合检索先请求查询向量,再分批生成尚未缓存的工具向量。后续相同工具描述可复用本地缓存,每次搜索仍请求查询向量。缓存根据接口地址、模型、指定维度和工具描述区分;修改工具名称、短说明或分类后,重启进程会为变化的描述重新生成向量。服务商在同一个模型 ID 下更新权重时,应手动清理对应缓存,避免混用新旧向量。
EmbeddingConfig 参数 |
默认值与用途 |
|---|---|
model、base_url |
必填;文本 embedding 模型和 API 地址 |
api_key |
不填写时读取 api_key_env,不会读取聊天密钥 |
api_key_env |
DNAKIT_EMBEDDING_API_KEY;可改为服务商的环境变量名 |
cache_dir |
$XDG_CACHE_HOME/dnakit/tool_embeddings,未设置时使用 ~/.cache/dnakit/tool_embeddings;None 表示仅内存缓存 |
batch_size |
10;按服务商限制调整每批工具描述条数 |
dimensions |
None,使用模型默认维度;仅在服务商支持时指定 |
timeout_seconds |
60;单次 HTTP 请求超时 |
max_request_bytes |
1_000_000;单批请求字节上限 |
max_response_bytes |
16_000_000;单批响应字节上限 |
云端只接收搜索文本和工具的名称、短说明、分类;这些接口不会读取输入路径指向的 DNA 文件。向量与相似度排序保存在/运行于调用 registry 的机器上。磁盘缓存不保存 API key 或查询原文。构造配置、创建 registry 和默认关键词检索均不创建缓存、不请求云端。明确选择语义/混合模式后需要相应配置;缺少密钥、网络错误、超限或非法向量会明确报错,不会静默切回关键词模式,也不会自动重试付费请求。
将这个 registry 用于 run_agent() 的示例见 Agent:配置工具检索。
MCP 也使用相同检索实现,参阅 MCP 的只获取候选与云端检索配置。
BM25、BM25+Dense 与检索后重排¶
bm25 不需要模型、API key 或新增依赖,可以直接运行:
from dnakit.tools import AgentToolRegistry, BM25Config
registry = AgentToolRegistry(bm25_config=BM25Config(k1=1.2, b=0.75))
tools = registry.search("download human reference genome", mode="bm25", limit=10)
print([tool.name for tool in tools])
BM25 使用正值 IDF log(1 + (N - df + 0.5) / (df + 0.5));默认 k1=1.2、b=0.75。统计量在过滤后的候选目录内计算,仅返回得分大于零的工具,同分按完整工具名排序。文本来自工具名、检索说明(默认短说明)和中英文类别,与语义检索使用相同字段。英文转小写,下划线/连字符标识符同时保留整体和分词;中文文档使用单字及相邻双字,多个连续汉字的查询使用相邻双字。没有自动翻译、词干化或停用词删除。中文分词不会把中文描述翻译成工具的英文说明。
bm25_hybrid 复用 EmbeddingConfig,以等权 RRF(k=60)融合完整 BM25 正分排名和完整语义排名,最后截取 limit。它不使用原 hybrid 的工具名称精确匹配优先规则。
rerank 先运行 bm25_hybrid,再将前 candidate_limit 个候选发送到重排 API。使用 Cohere Rerank 风格协议:POST /rerank,请求包含 model、query、字符串数组 documents、top_n;响应包含 results,每项具有 index 和数值 relevance_score。其他协议需要另行适配,不能直接把聊天或 embedding 接口地址当作重排地址。
export DNAKIT_RERANK_BASE_URL="https://your-reranker-service.example/v2"
export DNAKIT_RERANK_MODEL="your-reranker-model"
export DNAKIT_RERANK_API_KEY="your-reranker-api-key"
配置好本节前面的 embedding 环境变量后:
import os
from dnakit.tools import AgentToolRegistry, BM25Config, EmbeddingConfig, RerankerConfig
registry = AgentToolRegistry(
bm25_config=BM25Config(k1=1.2, b=0.75),
embedding_config=EmbeddingConfig(
model=os.environ["DNAKIT_EMBEDDING_MODEL"],
base_url=os.environ["DNAKIT_EMBEDDING_BASE_URL"],
),
reranker_config=RerankerConfig(
model=os.environ["DNAKIT_RERANK_MODEL"],
base_url=os.environ["DNAKIT_RERANK_BASE_URL"],
candidate_limit=50,
),
)
for mode in ("bm25", "bm25_hybrid", "rerank"):
tools = registry.search("下载人类 hg38 参考基因组", mode=mode, limit=10)
print(mode, [tool.name for tool in tools])
RerankerConfig 的 model、base_url 必填;地址可为 API 前缀或完整 /rerank 地址。默认独立读取 DNAKIT_RERANK_API_KEY,可用 api_key_env 或隐藏于 repr 的 api_key 覆盖,不借用聊天或 embedding 密钥。candidate_limit 默认 50,允许 1–1000;limit 仍为 1–100,且不能超过候选池上限。可设置 timeout_seconds=60、max_request_bytes=1_000_000、max_response_bytes=2_000_000。
重排每次对整个固定候选池评分,再截取输出;相同分数保留召回顺序,不随 Top-1/5/10 改变候选池。所有索引、结果数量及有限数值均被核对,缺失或重复结果报错。缺少配置、密钥、网络失败或超限均明确报错,不自动降级或重试。重排不执行候选工具,也不持久化查询、重排分数或密钥;其 embedding 缓存仍按前述规则保存。run_agent(..., registry=registry, search_mode="rerank", search_limit=10) 使用同一实现;工具目录刷新会保留这些配置。知识库 RAG 的模式仍单独配置。
3) 通用大模型调用¶
dnakit.llm 可插入任意 Python 处理流程:自定义提示词 + 当前步骤的数据 → 大模型输出 → 继续本地代码。它不局限于 DNA 或训练文件结构分析,也不需要使用 DNAKit CLI。
公开入口为 LLMConfig、LLMResult、同步函数 call_llm() 和异步函数 acall_llm()。仅依赖 Python 标准库和 DNAKit 核心,不需要安装 OpenAI SDK、PyTorch 或训练扩展。首版使用 OpenAI-compatible Chat Completions 协议;不自动适配其他厂商的私有协议。
支持的服务商¶
不是只能使用 DeepSeek。provider 预设支持下面六家服务商,并保留 custom 自定义兼容接口;同步和异步调用使用同一套配置。模型名称必须由用户填写,不会自动选用收费模型。
| 服务商 | provider |
默认 API base URL | 默认密钥环境变量 |
|---|---|---|---|
| DeepSeek | deepseek |
https://api.deepseek.com |
DEEPSEEK_API_KEY |
| Google Gemini | gemini |
https://generativelanguage.googleapis.com/v1beta/openai |
GEMINI_API_KEY |
| 千问 / 阿里云百炼 | qwen |
https://dashscope.aliyuncs.com/compatible-mode/v1 |
DASHSCOPE_API_KEY |
| Kimi / Moonshot | kimi |
https://api.moonshot.cn/v1 |
MOONSHOT_API_KEY |
| OpenRouter | openrouter |
https://openrouter.ai/api/v1 |
OPENROUTER_API_KEY |
| OpenAI | openai |
https://api.openai.com/v1 |
OPENAI_API_KEY |
| 自定义兼容接口 | custom |
必须显式填写base_url |
DNAKIT_LLM_API_KEY |
from dnakit.llm import LLMConfig, available_llm_providers, call_llm
print([provider.name for provider in available_llm_providers()]) # 仅本地查询
config = LLMConfig(
provider="gemini", # 可换为 qwen、kimi、openrouter、openai、deepseek
model="填写你账户支持的实际模型名",
)
result = call_llm("用中文总结这段内容。", input_data="Your input text", config=config)
print(result.text)
available_llm_providers() 返回 LLMProvider 预设对象;get_llm_provider(name) 解析单个预设。支持 google / google-gemini、dashscope / alibaba、moonshot 和 openai-compatible 别名。错误的 provider 名称会在请求前报错,不会回退至 DeepSeek。
兼容与地域注意事项:
- Gemini 使用 Google 官方的 OpenAI 兼容入口和 Gemini API key,不是原生
generateContentURL,也不包含 Vertex AI 的服务账号认证。 - Qwen 预设为北京旧域名,官方仍保留支持。可用
base_url指定账户所属地域/业务空间地址,例如https://<实际WorkspaceId>.cn-beijing.maas.aliyuncs.com/compatible-mode/v1或新加坡的https://<实际WorkspaceId>.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1。密钥与地域必须匹配。 - Kimi 国际账户可覆盖为
base_url="https://api.moonshot.ai/v1",并使用对应平台密钥。 - OpenRouter 的
model使用其目录中的完整模型 ID;选择服务商不等于所有模型都支持 JSON、思考模式或相同参数。 - 显式填写的
base_url、api_key_env和api_key优先于预设。为兼容已有代码,不填写provider时仍使用 DeepSeek 地址及DNAKIT_LLM_API_KEY,不会悄悄改读其他环境变量。
模型扩展参数¶
extra_body 将有限、可序列化的 JSON 字段合并到 HTTP 请求体顶层,可传服务商的思考参数等。它不能覆盖 model、messages、stream、token 限额、输出格式或认证字段,也不能开启尚未支持的工具/多模态请求。参数是否有效仍由具体模型决定;默认不注入模型专属参数。
config = LLMConfig(
provider="qwen",
model="填写支持关闭思考的实际模型名",
extra_body={"enable_thinking": False},
)
对于要求关闭思考才能使用非流式或 JSON 输出的 Qwen 模型,可按模型文档显式配置上例。OpenAI/Kimi 的部分模型可传 extra_body={"reasoning_effort": "low"};Gemini 的对应 Google 扩展字段需要保留 HTTP 层嵌套,例如 extra_body={"extra_body": {"google": {"thinking_config": {"thinking_level": "low"}}}}。这些只是特定参数形式的例子,不保证适用于同一服务商的所有模型。
文本输入与输出¶
import os
from dnakit.llm import LLMConfig, call_llm
config = LLMConfig(
provider="deepseek", # 可切换为 gemini、qwen、kimi、openrouter 或 openai
model=os.environ["DNAKIT_LLM_MODEL"], # 使用你账户支持的实际模型名
api_key_env="DNAKIT_LLM_API_KEY", # 也支持 api_key=os.environ["...照你的变量名..."]
max_output_tokens=1024,
timeout_seconds=60,
)
result = call_llm(
"请将下面这段文字翻译成中文,只返回译文。",
input_data="The sample passed the quality check.",
config=config,
)
translated_text = result.text
print(translated_text)
print(dict(result.usage)) # 服务商返回的 token 用量,不是费用估算
在 PyCharm 的运行配置中设置两个环境变量即可;无需把密钥写进代码。base_url 是 API 地址,不是 platform.deepseek.com/usage 之类的账户页面。模型名称按服务商当前可用列表配置,DNAKit 不替用户选择或切换模型。
直接指定本地文件路径¶
call_llm() 和 acall_llm() 均支持 file_path,可直接读取并处理一个本地文本文件,无需手动 read_text():
from dnakit.llm import LLMConfig, call_llm
result = call_llm(
"用中文概括文件内容,只根据原文回答。",
file_path="/mnt/d/Pycharm_workspace/DNA/DNAKit/LICENSE",
config=LLMConfig(
provider="gemini", # 也可使用其他已支持的服务商
model="填写实际模型名",
api_key_env="GEMINI_API_KEY",
),
)
print(result.text)
文件路径支持字符串或 Path、绝对路径或相对于当前工作目录的路径,包含空格也可使用;Python 字符串中的下划线不需要加反斜杠转义。Windows 原生 Python 应使用 Windows 路径,例如 r"D:\Pycharm_workspace\DNA\DNAKit\LICENSE";/mnt/d/... 是 WSL/Linux 路径。
指定 file_path 表示允许发送该文件的完整文本内容。 请求只附带文件名,不自动附带绝对目录;不会读取邻近文件、扫描目录、递归读取文件中的链接、执行代码或自动分批请求。input_data 与 file_path 不能同时使用。原先 input_data="/path/to/file" 的行为保持不变:它仍只是一个字符串,不会触发读取。
可以先完全在本地预览:
默认 file_encoding="utf-8-sig" 支持 UTF-8 及 UTF-8 BOM;其他编码须显式指定,例如 file_encoding="gb18030" 或 "utf-16"。read_llm_file() 对应参数名为 encoding。
默认 max_file_bytes=64000 限制原文件字节数,read_llm_file() 对应参数名为 max_bytes。完整请求还受 LLMConfig.max_request_bytes 限制,后者包括提示词、文件名、JSON 转义和其他请求字段;提高文件上限不等于提高请求上限。超限时在请求前报错,不会偷偷截断、抽样或拆成多次付费调用。
支持无后缀 LICENSE、TXT、Markdown、CSV/TSV、JSON/JSONL、YAML、XML、Python 等可解码文本;表格与代码按原文发送,不执行或自动清洗。PDF、Word/Excel 二进制文档、图片、压缩包等不能直接处理,需先自行提取文本再传入 input_data。空文件、目录、设备文件、错误编码和超限文件会明确报错。完整示例为 others/examples/custom_llm_file.py。
JSON 输入与结构化输出¶
rows = [
{"id": "a", "note": "quality check passed"},
{"id": "b", "note": "measurement needs repeating"},
]
result = call_llm(
'将 note 翻译为中文。返回 JSON 对象 {"items": [{"id": "原 ID", "note_zh": "译文"}]}。',
input_data=rows,
output_format="json",
system_prompt="你是实验记录翻译助手。保留原始 ID,不补充未提供的实验结果。",
config=config,
)
output = result.data # 普通 dict;文本模式下为 None
if output is None or not isinstance(output.get("items"), list):
raise ValueError("输出缺少预期的 items 列表")
# 在这里继续验证记录 ID、字段类型等,再交给下一步 Python 代码。
JSON 模式请求 response_format={"type": "json_object"} 并校验返回语法、非有限数值、重复键和顶层对象类型;不保证业务字段符合预期,也不保证模型判断正确。需要数组时,将其放在对象字段内,例如 {"items": [...]}。所选模型需要支持 JSON mode;服务商拒绝请求或返回非法 JSON 时会明确报错,DNAKit 不会静默切换输出模式或模型。
LLMResult 提供 text、data、model、response_id、finish_reason、usage 和 to_dict()。data 每次返回独立的普通字典,修改它不会改变原结果。结果不保留请求提示词或原始输入,但模型输出本身仍可能包含敏感内容。
任意 Python 步骤与异步程序¶
你可以把上一步产生的字符串、有限数值、布尔值、列表、元组或字符串键字典传入 input_data。None 表示不额外附加数据,只使用提示词。DataFrame、NumPy 数组、自定义对象需要由调用方先明确转换;例如只共享表格样本时使用 df.head(5).to_dict(orient="records"),并检查缺失值和非有限数值。
from dnakit.llm import acall_llm
async def summarize_step(current_result, config):
result = await acall_llm(
"用两句话概括结果,不推断未提供的信息。",
input_data=current_result,
config=config,
)
return result.text
acall_llm() 在线程中进行 HTTP 调用,不阻塞 asyncio 事件循环。取消 await 不代表已提交的请求被取消,服务商仍可能完成并计费。首次连接、每次调用均无自动重试、无隐式会话历史;循环或并发调用的次数由你的 Python 代码控制。