PAYATHON 2026

使用 Groq API 的 Python coding agent 为何触发 OpenAI 401 错误

排障赵师傅

结论

这次 401 报错来自 OpenAI embeddings,与 Groq API key 无关。ChatGroq 只负责对话模型调用;CrewAI 启用 memory=True 后,还会启动独立的向量记忆流程。当前调用链中的 Embedchain/ChromaDB 默认使用 OpenAI embedding function,因此请求进入了 openai.resources.embeddings,并读取环境中无效的 OPENAI_API_KEY=fake 调用 OpenAI,最终返回 401。

可以根据是否需要向量记忆选择处理方式:

  1. 不需要向量记忆时,关闭 CrewAI memory。
  2. 需要向量记忆时,为 Crew 明确配置 embedding provider,例如本地 Hugging Face 模型或其他受支持的嵌入服务。

重新生成 Groq key 不会解决这个错误,因为失败的是 embeddings 请求,Groq 的聊天补全请求并未报错。

为什么配置了 ChatGroq 还会调用 OpenAI

启用记忆后,agent 通常有两条独立的调用链:

任务执行
  └─ ChatGroq
      └─ Groq chat completion API

记忆检索
  └─ CrewAI contextual memory
      └─ Embedchain
          └─ ChromaDB
              └─ embedding function
                  └─ OpenAI embeddings API

下面这段代码:

llm = ChatGroq(...)

只指定了用于生成文本的 LLM,没有指定 CrewAI 使用哪个 embedding model。

异常堆栈也显示,请求经过了以下调用链:

contextual_memory.build_context_for_task
short_term_memory.search
rag_storage.search
embedchain.search
chromadb.Collection.query
_embedding_function
openai.resources.embeddings

错误发生在短期记忆的相似度检索阶段,此时还没有进入 ChatGroq 的文本生成流程。

Groq 聊天模型与 embedding model 属于两类服务。把 ChatGroq 传给 Agent 或 Task,不会让 CrewAI 自动改用 Groq 生成向量。

方案一:关闭 memory

如果流程只是让一个 agent 生成代码,再由另一个 agent 执行和检查,通常用不到向量数据库。顺序任务会把前一个任务的输出传给后一个任务。

可以先关闭所有 memory 配置,检查主流程能否正常运行:

coderAgent = Agent(
    role="Senior Software engineer and developer",
    goal="Write production grade bug free code on this user prompt: {topic}",
    backstory="You are an experienced Python developer.",
    llm=llm,
    tools=[duckduckgo_search_tool],
    memory=False,
    verbose=True,
    max_iter=10,
    max_rpm=10,
    allow_delegation=True,
)

DebuggerAgent = Agent(
    role="Code Debugger and bug solving agent",
    goal="Run and debug the code produced by the coding agent.",
    backstory="You debug Python code using an interpreter.",
    llm=llm,
    tools=[duckduckgo_search_tool, python_repl_tool],
    memory=False,
    verbose=True,
    max_iter=10,
    max_rpm=10,
    allow_delegation=True,
)

crew = Crew(
    agents=[coderAgent, DebuggerAgent],
    tasks=[coding_task, debug_task],
    process=Process.sequential,
    memory=False,
    cache=True,
    max_rpm=25,
)

需要特别确认 Crew 上的 memory 已关闭:

crew = Crew(
    ...
    memory=False,
)

cache=True 与向量记忆是两项不同的功能,可以继续保留。不同 CrewAI 版本处理 Agent(memory=...) 的方式可能不同,排查时最好同时关闭 Agent 和 Crew 上的 memory。

如果修改后程序能够运行,基本可以确认问题出在默认的 embedding 配置上。

方案二:显式配置非 OpenAI embeddings

需要语义记忆时,可以在 Crew 上指定 embedding provider。以下配置使用本地 Hugging Face sentence-transformers 模型:

crew = Crew(
    agents=[coderAgent, DebuggerAgent],
    tasks=[coding_task, debug_task],
    process=Process.sequential,
    memory=True,
    cache=True,
    max_rpm=25,
    embedder={
        "provider": "huggingface",
        "config": {
            "model": "sentence-transformers/all-MiniLM-L6-v2"
        },
    },
)

本地模型通常还需要安装相应依赖:

python -m pip install sentence-transformers

embedder 的字段结构取决于 CrewAI 和 Embedchain 的版本。有些版本使用 model_name,有些还要求安装对应 provider 的额外依赖。可以先查看当前环境中的版本:

python -m pip show crewai embedchain chromadb langchain-groq
python -m pip check

确认版本后,再按照对应版本的 CrewAI memory 接口调整 provider 和 config。CrewAI 的 memory 实现和配置方式有过变化,其他版本的参数不一定能直接使用。

Ollama 等本地 embedding 服务也可以作为 provider,但需要先确认当前 CrewAI 版本是否支持,以及配置中要求使用 base_url、url 还是其他字段。

如果继续使用 OpenAI embeddings

生成模型可以继续使用 Groq,记忆模块则使用 OpenAI embeddings。两项服务需要各自的凭据:

import os

os.environ["GROQ_API_KEY"] = "your-groq-api-key"
os.environ["OPENAI_API_KEY"] = "your-openai-api-key"

同时明确指定 OpenAI embedding model:

crew = Crew(
    agents=[coderAgent, DebuggerAgent],
    tasks=[coding_task, debug_task],
    process=Process.sequential,
    memory=True,
    embedder={
        "provider": "openai",
        "config": {
            "model": "text-embedding-3-small"
        },
    },
)

Groq key 不能用于调用 OpenAI。错误信息:

Incorrect API key provided: fake

表示 OpenAI 客户端读取到的 key 是 fake。这个值可能来自系统环境变量、.env 文件、IDE 启动配置或示例配置。

排查时只需检查变量是否存在,不要将完整 key 写入日志:

import os

print("GROQ_API_KEY configured:", bool(os.getenv("GROQ_API_KEY")))
print("OPENAI_API_KEY configured:", bool(os.getenv("OPENAI_API_KEY")))

如果不使用 OpenAI embeddings,不要用假的 OPENAI_API_KEY 绕过初始化。应关闭 memory,或明确选择其他 embedding provider。

更换 embedding model 后要处理旧向量数据

如果 Chroma collection 已经存在,更换 embedding provider 后可能出现向量维度不一致。例如,旧模型生成的是 1536 维向量,新模型可能生成 384 维向量。

遇到这种情况,应先备份需要保留的数据,再重新创建对应的 CrewAI/Chroma memory collection。存储位置由 CrewAI 版本和 storage 配置决定。确认路径之前,不要直接删除整个项目目录。

建议的排查顺序

  1. 关闭 Crew(memory=False) 和 Agent 上的所有 memory 配置。
  2. 确认 ChatGroq 能够独立完成一次调用。
  3. 检查 .env、系统环境变量或 IDE 是否注入了 OPENAI_API_KEY。
  4. 查看 crewai、embedchain 和 chromadb 的实际版本。
  5. 确定需要 memory 后,再添加明确的 embedder 配置。
  6. 更换 embedding model 后,重新创建向量集合。

llama3-70b-8192 能否使用,取决于 Groq 当前提供的模型列表。如果之后出现 Groq 的 model-not-found 错误,需要改用账户中可用的模型。该问题与本次 OpenAI 401 的调用链无关。

使用 LangGraph 实现时的对应思路

LangGraph 可以用带条件边的状态图表示“生成代码、执行代码、根据结果决定是否重试”的流程。状态持久化通常由 checkpointer 完成,默认不需要向量 embeddings。

迁移时可以划分为以下节点:

coder
  ↓
execute_python
  ↓
是否执行成功?
  ├─ 是 → END
  └─ 否 → debugger → coder

可在 LangGraph 官方资料中查找以下关键词:

  • Tool calling
  • Conditional edges
  • Persistence/checkpointer
  • Human-in-the-loop
  • ChatGroq 与 LangChain tools 集成

LangGraph 和 LangChain 的 agent API 更新较快,示例代码应以已安装版本对应的官方文档为准。无论使用 CrewAI 还是 LangGraph,只要加入基于语义搜索的长期记忆,就需要单独选择并配置 embedding model。

还需注意,PythonREPL 可以执行模型生成的任意 Python 代码。用于真实用户或生产环境时,应将其放入权限受限的容器或沙箱,并限制文件系统、网络、执行时间和可用资源。

备注:内容仅供参考。