使用 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。
可以根据是否需要向量记忆选择处理方式:
- 不需要向量记忆时,关闭 CrewAI memory。
- 需要向量记忆时,为 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 配置决定。确认路径之前,不要直接删除整个项目目录。
建议的排查顺序
- 关闭
Crew(memory=False)和 Agent 上的所有 memory 配置。 - 确认 ChatGroq 能够独立完成一次调用。
- 检查
.env、系统环境变量或 IDE 是否注入了OPENAI_API_KEY。 - 查看
crewai、embedchain和chromadb的实际版本。 - 确定需要 memory 后,再添加明确的
embedder配置。 - 更换 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 代码。用于真实用户或生产环境时,应将其放入权限受限的容器或沙箱,并限制文件系统、网络、执行时间和可用资源。
备注:内容仅供参考。
