LlamaIndex 接入统一 API:OpenAILike 类

最后更新: 2026-07-16

LlamaIndex 自带一个专门类:OpenAILike。api_base 填 https://api.kkaiapi.com/v1,is_chat_model 显式设为 True,查询引擎和 Agent 背后的模型就能是目录里任意 ID,索引的 Embedding 那一侧完全不受影响。

先说结论:OpenAILike 加 is_chat_model=True

LlamaIndex 的 OpenAI 类会拿模型名去校验 OpenAI 官方目录,认不出的 ID 直接拒绝。框架给这个场景准备的答案是 OpenAILike,一个在独立包 llama-index-llms-openai-like 里的类,跳过校验、说同样的协议:api_base 填 https://api.kkaiapi.com/v1,传 Key 和任意目录模型 ID,再把 is_chat_model 显式设为 True,请求才会走 /chat/completions。 这最后一个参数是承重的。OpenAILike 没法知道一个陌生 ID 是不是聊天模型,不设这个参数时它会把模型当成老式的 completions 模型,发到网关不为这个用途提供服务的端点。显式设它,是能跑通和一个看起来像路由问题的 404 之间的区别。

import os
from llama_index.llms.openai_like import OpenAILike

llm = OpenAILike(
    model="claude-sonnet-4-6",           # 目录里任意 ID
    api_base="https://api.kkaiapi.com/v1",
    api_key=os.environ["KKAIAPI_KEY"],
    is_chat_model=True,                   # 必须显式设置:聊天而非补全
    is_function_calling_model=True,       # 打开 Agent / 工具调用路径
    context_window=200000,
)

print(llm.complete("用一句话概括检索增强生成。"))

LLM 在 LlamaIndex 管线里的位置

LlamaIndex(GitHub 上的 run-llama,约 5.1 万星标)是一个数据框架:文档先被切块、Embedding 化建进索引,查询按向量相似度检索出相关片段,LLM 到这一步才登场,基于检索到的上下文合成答案。Agent 再叠加第二层 LLM 职责,决定该调用哪个工具或查询引擎。 这个分工决定了路由的边界。检索跑在 Embedding 模型上;合成和 Agent 决策跑在 LLM 上。OpenAILike 把第二部分工作挪到网关,Embedding 模型以及索引里已经建好的每一个向量都留在原地不动。换 Embedding 是重新建索引;换合成用的模型只是改一个构造参数。 可以全局接线,通过 Settings.llm,之后创建的每个查询引擎和 Agent 都继承它;也可以按组件单独接线,给混用多个模型的管线用。model 字段是原样传下去的字符串,所以合成步骤可以是一个 Claude ID,而前置的"先总结再入库"步骤跑一个快速的 DeepSeek ID,两者共用一个端点和 Key。

完整配置:RAG 查询引擎与 TS 变体

下面这个 RAG 写法把网关模型设成全局,Embedding 配置完全不碰。context_window 值得留意:LlamaIndex 按这个数字规划每次合成调用要塞进多少检索文本,OpenAILike 对陌生模型默认给的值偏保守。声明模型真实的窗口大小,意味着更少的 refine 轮次去重复处理同一批节点,这既是质量也是成本。 TypeScript 这边,LlamaIndex.TS 通过它的 OpenAI 类接到同一个端点,这个类直接接受 baseURL、apiKey、model 三个参数。TS 包里没有单独的 OpenAILike 类,baseURL 覆盖就是官方文档给出的路径。

import os
from llama_index.core import Settings, VectorStoreIndex, SimpleDirectoryReader
from llama_index.llms.openai_like import OpenAILike

Settings.llm = OpenAILike(
    model="claude-sonnet-4-6",
    api_base="https://api.kkaiapi.com/v1",
    api_key=os.environ["KKAIAPI_KEY"],
    is_chat_model=True,
    is_function_calling_model=True,
    context_window=200000,
)
# Settings.embed_model 不动:索引和向量保持有效

docs = SimpleDirectoryReader("./reports").load_data()
index = VectorStoreIndex.from_documents(docs)

engine = index.as_query_engine(similarity_top_k=5)
print(engine.query("这个季度的利润率变化主要由什么驱动?"))

选合成模型

RAG 让模型对比变得格外严谨:固定住索引和一批查询,只换合成模型的 ID,把答案和来源逐条比对。经一个端点,每个候选都是一行代码的改动,按 Key 的用量视图给评测集的每一轮跑分定价。

  • 合成质量就是答案质量:模型读检索到的片段、写出回答,最该优化的是对来源的忠实度。claude-sonnet-4-6 是可靠的中间档,gpt-5.5 是有力的第二意见
  • 高频查询场景(内部搜索框、批量文档问答),多数调用走合成步骤,claude-haiku-4-5-20251001 在问题偏常规的时候能把单次查询成本压平
  • Agent 场景(把查询引擎当工具、多步推理)需要 is_function_calling_model=True 加一个工具调用可靠的 ID,这是强模型能真正回本的地方
  • 检索上下文长、top-k 大或分块大的场景,适合 gemini-3.1-pro-preview 配合如实声明的 context_window,用更少的 refine 轮次换一次更大的调用

主力模型价格

价格按 kkaiapi 中文区实时价格计算,单位 ¥/1M tokens(输入/输出)。

实时价格以 /pricing 为准
模型模型 IDkkaiapi 价格(输入/输出)适合场景
Claude Sonnet 4.6claude-sonnet-4-6¥3 / ¥15合成默认档
Claude Haiku 4.5claude-haiku-4-5-20251001¥1 / ¥5高频常规问答
GPT-5.5gpt-5.5¥4 / ¥25合成第二意见
Gemini 3.1 Pro Previewgemini-3.1-pro-preview¥7 / ¥42长上下文、高 top-k
DeepSeek V4 Flashdeepseek-v4-flash¥0.9 / ¥1.8预处理与总结步骤

翻车点与版本锁定

漏设 is_chat_model。默认会把陌生 ID 当成老式补全模型,发到 /chat/completions 之外的端点,结果是一个看起来像路由错误、实际是配置漏了一个布尔值的报错。这是 OpenAILike 上最典型的坑,值得排在所有排查项之前。 用普通 OpenAI 类接非 OpenAI 的 ID。这个类会校验模型名,认不出的 ID 在任何请求发出之前就报错。如果看到一个"未知模型"错误、而且没有任何网络请求发出去,说明用错了类,该换成 OpenAILike。 context_window 留在默认值。合成阶段的规划按这个数字打包检索到的文本,一个 20 万窗口的模型如果留着保守的默认值,意味着更多、更碎的合成调用和更多轮 refine;声明真实窗口能让响应合成更好也更省。 0.10 版本之后的包结构。LlamaIndex 拆分成了带命名空间的独立包,OpenAILike 活在 llama-index-llms-openai-like 里,从 llama_index.llms.openai_like 导入。老代码里从单体 llama_index 包直接导入,是拆分之前的写法。依赖清单里锁定具体的集成包,而不只是 llama-index-core。 不设函数调用标志,Agent 路径会静默降级。is_function_calling_model=False 会让 Agent 走 fallback 的提示词方案而不是原生工具调用,能跑但明显不够可靠。对上面表里这类支持工具调用的 ID,显式设成 True。 Embedding 是单独一次迁移。Settings.embed_model 和 LLM 相互独立,挪动合成不会让向量失效;kkaiapi 目前不提供 Embedding 模型,如果打算连 Embedding 一起换,那是重新对整个语料库做 Embedding 的决定,和换 LLM 分开考虑。

谁会把 LlamaIndex 接到一个网关上

  • 想在已有索引上获得 Claude 级别合成质量、又不想动 Embedding 侧或重新建索引的 RAG 开发者
  • 跑量级文档问答的团队,一个快速合成 ID 能改变每次查询的单位经济,按 Key 用量让每千次查询的成本一目了然
  • 按固定索引和查询集评测合成模型的工程师,每个候选只是一行构造参数
  • 构建 Agent 的开发者,把查询引擎当工具用,需要可靠的函数调用,整条管线共用一个计费面
  • 拿不到某家厂商计费权限的开发者,充值即用不需要海外卡

验证接入与排查首次查询

接线之前先列出网关的模型;model 参数必须和提供的某个 ID 精确匹配,版本后缀也算。 首次查询的失败很有规律。报错形状像路由问题(404 类),说明 is_chat_model 没设。一个在本地就报出来、没有任何请求发出去的"未知模型"错误,说明用的是普通 OpenAI 类而不是 OpenAILike。对网关报 401,是 Key 不对,或者环境变量回退到了和构造参数不一致的值,打印实际生效的两个值。模型不存在的报错是 ID 拼错了。 查询能跑起来之后,kkaiapi 控制台会显示每次请求的模型、token 数和花费。对 RAG 来说该盯着看的是每次查询的 token 数:检索到的上下文主导了输入 token,所以 top-k 和分块大小的调整,和模型选择一样会直接体现在用量视图里。

curl -s https://api.kkaiapi.com/v1/models \
  -H "Authorization: Bearer $KKAIAPI_KEY" | head -50

常见问题

为什么要用 OpenAILike 而不是普通的 OpenAI 类?

普通类会拿模型名去校验 OpenAI 官方目录,Claude、DeepSeek 这类 ID 都会被拒绝。OpenAILike 说同样的协议但跳过校验,正好是多厂商端点需要的行为。

忘记设 is_chat_model=True 会怎样?

OpenAILike 会把模型当成老式补全模型,发到 /chat/completions 之外的路径,对着一个聊天网关就是一个 404 形状的报错。每个 OpenAILike 实例都要显式设这个参数。

用这个方案需要重新对索引做 Embedding 吗?

不需要。检索跑在 Embedding 模型上,这套配置不碰它;只有合成和 Agent 调用挪到网关,已有向量保持有效。换 Embedding 模型是另一次迁移,那才需要重新处理整个语料库。

LlamaIndex 的 Agent 和工具调用能这样接吗?

能,给一个支持工具调用的 ID 设 is_function_calling_model=True,Agent 就会用原生函数调用经网关跑。这个参数留 False 会让 Agent 悄悄降级到不够可靠的提示词 fallback。

TypeScript 版有 OpenAILike 吗?

没有单独的类;LlamaIndex.TS 通过它的 OpenAI 类接自定义端点,这个类接受 baseURL 加 apiKey 和 model。把网关地址填进 baseURL,model 填字符串 ID 即可。

应该锁定哪些包版本?

显式锁定 llama-index-llms-openai-like 和 llama-index-core。v0.10 拆分之后,各个集成活在带命名空间的独立包里,只锁一个元包会让实际依赖的类版本处于漂移状态。