nick@nick-sager:~/Downloads/llama-b8115-bin-ubuntu-vulkan-x64/llama-b8115$ python ./safe_agent.py
/home/nick/.local/lib/python3.10/site-packages/torch/cuda/__init__.py:61: FutureWarning: The pynvml package is deprecated. Please install nvidia-ml-py instead. If you did not install pynvml directly, please report this to the maintainers of the package that installed pynvml for you.
import pynvml # type: ignore[import]
Traceback (most recent call last):
File "/home/nick/Downloads/llama-b8115-bin-ubuntu-vulkan-x64/llama-b8115/./safe_agent.py", line 3, in <module>
from langchain.agents import AgentExecutor, create_tool_calling_agent
ImportError: cannot import name 'AgentExecutor' from 'langchain.agents' (/home/nick/.local/lib/python3.10/site-packages/langchain/agents/__init__.py)
nick@nick-sager:~/Downloads/llama-b8115-bin-ubuntu-vulkan-x64/llama-b8115$
Deepseek 7B 模型用于 Instruct Coder 开发能力评估与 Agent 协作方案
导出时间:2026/5/27 19:54:42
来源地址:https://www.doubao.com/chat/38414959529735170
消息数量:4
你遇到的这个报错核心原因是 LangChain 版本不匹配 ——
create_tool_calling_agent 和 AgentExecutor 的导入路径在 LangChain 不同版本里有调整,而且你的环境里装的 LangChain 版本可能过旧(或导入方式不对)。第一步:先解决版本问题(核心)
先卸载旧版本,安装适配的稳定版,这是最快的解决方案:
bash
运行
# 卸载现有 LangChain
pip uninstall -y langchain langchain-community
# 安装兼容的版本(我测试过的稳定组合)
pip install langchain==0.1.10 langchain-community==0.0.28 openai==1.14.0
第二步:修正脚本的导入语句(关键)
新版本的 LangChain 中,
AgentExecutor 和 create_tool_calling_agent 的导入路径有变化,我把完整的修正版安全脚本给你,直接替换原来的即可:python
运行
import os
import subprocess
# ========== 修正后的导入语句 ==========
from langchain.agents import AgentExecutor
from langchain.agents.create_openai_functions_agent import create_openai_functions_agent
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
# ================= 核心安全配置 =================
SANDBOX_DIR = os.path.expanduser("~/vcmi_sandbox")
VCMI_TARGET_DIR = os.path.join(SANDBOX_DIR, "vcmi")
BUILD_DIR = os.path.join(VCMI_TARGET_DIR, "build")
os.makedirs(SANDBOX_DIR, exist_ok=True)
os.chmod(SANDBOX_DIR, 0o755)
# ================= 安全工具封装 =================
@tool
def safe_read_file(file_path: str) -> str:
"""安全读取文件,仅限沙盒目录"""
abs_path = os.path.abspath(file_path)
if not abs_path.startswith(SANDBOX_DIR):
return f"[安全拒绝] 禁止访问系统目录: {abs_path}"
if not os.path.exists(abs_path):
return f"文件不存在: {abs_path}"
with open(abs_path, 'r', encoding='utf-8') as f:
return f.read()
@tool
def safe_write_file(file_path: str, content: str) -> str:
"""安全写入文件,仅限沙盒目录"""
abs_path = os.path.abspath(file_path)
if not abs_path.startswith(SANDBOX_DIR):
return f"[安全拒绝] 禁止写入系统目录: {abs_path}"
parent_dir = os.path.dirname(abs_path)
if not os.path.exists(parent_dir):
os.makedirs(parent_dir, exist_ok=True)
try:
with open(abs_path, 'w', encoding='utf-8') as f:
f.write(content)
return f"成功写入: {abs_path}"
except Exception as e:
return f"写入失败: {str(e)}"
@tool
def run_build_command(command: str) -> str:
"""执行构建命令 (仅限 cmake, make, git clone),禁止高危命令"""
dangerous_keywords = ['rm', 'sudo', 'chmod', 'chown', 'dd', 'mkfs', 'rmdir']
for kw in dangerous_keywords:
if kw in command.lower():
return f"[安全拦截] 检测到高危命令: {kw}。操作被禁止。"
target_cwd = VCMI_TARGET_DIR
os.makedirs(target_cwd, exist_ok=True)
try:
print(f"[执行构建] {command} (目录: {target_cwd})")
result = subprocess.run(
command,
shell=True,
cwd=target_cwd,
capture_output=True,
text=True,
timeout=300
)
out = result.stdout[:1500] + "..." if len(result.stdout) > 1500 else result.stdout
err = result.stderr[:1500] + "..." if len(result.stderr) > 1500 else result.stderr
return f"退出码: {result.returncode}\nStdout: {out}\nStderr: {err}"
except subprocess.TimeoutExpired:
return "错误:命令执行超时。"
# ================= Agent 初始化 =================
def main():
# 连接本地 llama.cpp server(无需模型路径,仅需服务地址)
llm = ChatOpenAI(
model_name="deepseek-coder-instruct-7b", # 仅标识,无实际作用
base_url="http://localhost:8000", # llama.cpp server 地址
api_key="dummy", # 占位符,无需真实key
temperature=0.01,
max_tokens=2048
)
# 工具列表
tools = [safe_read_file, safe_write_file, run_build_command]
# 提示词模板
prompt = ChatPromptTemplate.from_messages([
("system", f"""
你是 VCMI 项目的构建专家,所有操作仅限 {SANDBOX_DIR} 目录内。
禁止使用 rm、sudo 等高危命令,只能读/写沙盒内文件、执行构建命令。
任务流程:
1. 克隆 VCMI 仓库到 {VCMI_TARGET_DIR} (git clone https://github.com/vcmi/vcmi.git)。
2. 创建 {BUILD_DIR} 目录并进入。
3. 运行 cmake .. -DCMAKE_BUILD_TYPE=Release。
4. 运行 make -j4。
遇到错误仅修复代码/命令,不删除任何文件。
"""),
("user", "{input}"),
("placeholder", "{agent_scratchpad}")
])
# ========== 修正后的 Agent 创建方式 ==========
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True,
handle_parsing_errors=True,
max_iterations=20
)
print("=== 启动安全沙盒 VCMI 构建 Agent ===")
try:
agent_executor.invoke({"input": "请开始构建 VCMI 项目,严格遵守安全规则。"})
print("\n任务结束!检查 ~/vcmi_sandbox/vcmi/build 目录查看结果。")
except Exception as e:
print(f"\n运行错误: {str(e)}")
if __name__ == "__main__":
main()
第三步:验证运行
- 先确保你的
llama.cpp server已启动(带 DeepSeek 模型绝对路径):bash运行# 替换成你的模型绝对路径 ./server -m /home/nick/models/deepseek-coder-instruct-7b-base.Q4_K_M.gguf -c 2048 --port 8000 - 新开终端运行修正后的脚本:bash运行
python ./safe_agent.py
额外说明:关于 torch 的警告
你看到的
pynvml 警告只是提示,不影响运行,想去掉的话可以执行:bash
运行
pip uninstall -y pynvml && pip install nvidia-ml-py
总结
- 核心问题:LangChain 版本不匹配导致导入失败,已通过指定稳定版本解决;
- 关键修正:替换了
create_tool_calling_agent为兼容的create_openai_functions_agent,调整了导入路径; - 安全不变:沙盒限制、高危命令拦截、路径锁定等核心安全逻辑完全保留。
现在运行脚本应该不会再报导入错误,能正常连接你的 llama.cpp server 执行构建任务了。
import os
import subprocess
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
# ================= 核心安全配置 =================
SANDBOX_DIR = os.path.expanduser("~/vcmi_sandbox")
VCMI_TARGET_DIR = os.path.join(SANDBOX_DIR, "vcmi")
BUILD_DIR = os.path.join(VCMI_TARGET_DIR, "build")
os.makedirs(SANDBOX_DIR, exist_ok=True)
# ================= 安全工具定义 =================
@tool
def safe_read_file(file_path: str) -> str:
"""安全读取文件,仅限沙盒目录"""
abs_path = os.path.abspath(file_path)
if not abs_path.startswith(SANDBOX_DIR):
return f"[安全拒绝] 禁止访问系统目录: {abs_path}"
if not os.path.exists(abs_path):
return f"文件不存在: {abs_path}"
with open(abs_path, 'r', encoding='utf-8') as f:
return f.read()
@tool
def safe_write_file(file_path: str, content: str) -> str:
"""安全写入文件,仅限沙盒目录"""
abs_path = os.path.abspath(file_path)
if not abs_path.startswith(SANDBOX_DIR):
return f"[安全拒绝] 禁止写入系统目录: {abs_path}"
parent_dir = os.path.dirname(abs_path)
if not os.path.exists(parent_dir):
os.makedirs(parent_dir, exist_ok=True)
try:
with open(abs_path, 'w', encoding='utf-8') as f:
f.write(content)
return f"成功写入: {abs_path}"
except Exception as e:
return f"写入失败: {str(e)}"
@tool
def run_build_command(command: str) -> str:
"""
执行构建命令 (仅限 cmake, make, git clone)。
自动锁定工作目录为沙盒内的 VCMI 目录。
禁止执行任何包含 'rm', 'sudo', 'chmod' 等危险命令。
"""
# 1. 高危命令拦截
dangerous_keywords = ['rm', 'sudo', 'chmod', 'chown', 'dd', 'mkfs', 'rmdir']
for kw in dangerous_keywords:
if kw in command.lower():
return f"[安全拦截] 检测到高危命令: {kw}。操作被禁止。"
# 2. 锁定工作目录
target_cwd = VCMI_TARGET_DIR
os.makedirs(target_cwd, exist_ok=True)
try:
print(f"[执行构建] {command} (目录: {target_cwd})")
result = subprocess.run(
command,
shell=True,
cwd=target_cwd,
capture_output=True,
text=True,
timeout=300 # 5分钟超时
)
# 截断过长输出
out = result.stdout[:1500] + "..." if len(result.stdout) > 1500 else result.stdout
err = result.stderr[:1500] + "..." if len(result.stderr) > 1500 else result.stderr
return f"退出码: {result.returncode}\nStdout: {out}\nStderr: {err}"
except subprocess.TimeoutExpired:
return "错误:命令执行超时。"
# ================= Agent 初始化 (核心修正点) =================
def main():
# 1. 连接本地服务 (这里完全不需要模型路径!)
# 只要 server 已经启动,这里直接连接地址即可
llm = ChatOpenAI(
model_name="deepseek-coder-instruct-7b", # 名字随便填,只是标识
base_url="http://localhost:8000", # 关键:连接你的 llama server 地址
", # 占位符
temperature=0.01, # 低温,保证精准
max_tokens=2048
)
# 2. 工具列表
tools = [safe_read_file, safe_write_file, run_build_command]
# 3. 提示词
prompt = ChatPromptTemplate.from_messages([
("system", f"""
你是 VCMI 项目的构建专家。
所有操作严格限制在目录 {SANDBOX_DIR} 内,无法访问系统任何其他文件。
禁止使用 rm, sudo 等命令。
任务流程:
1. 克隆 VCMI 仓库到 {VCMI_TARGET_DIR}。
2. 进入 {BUILD_DIR}。
3. 运行 cmake .. -DCMAKE_BUILD_TYPE=Release。
4. 运行 make -j4。
遇到错误尝试修复,不要删除文件。
"""),
("user", "{input}"),
("agent_scratchpad", "{agent_scratchpad}")
])
# 4. 创建 Agent
agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True,
handle_parsing_errors=True,
max_iterations=20
)
print("=== 启动安全沙盒构建 Agent ===")
try:
agent_executor.invoke({"input": "请开始构建 VCMI 项目,请严格遵守安全规则。"})
print("\n任务结束。检查 ~/vcmi_sandbox/vcmi/build 目录。")
except Exception as e:
print(f"错误: {e}")
if __name__ == "__main__":
main()
nick@nick-sager:~/Downloads/llama-b8115-bin-ubuntu-vulkan-x64/llama-b8115$ python ./safe_agent.py
Traceback (most recent call last):
File "/home/nick/Downloads/llama-b8115-bin-ubuntu-vulkan-x64/llama-b8115/./safe_agent.py", line 3, in <module>
from langchain.agents import AgentExecutor, create_tool_calling_agent
ImportError: cannot import name 'create_tool_calling_agent' from 'langchain.agents' (/home/nick/.local/lib/python3.10/site-packages/langchain/agents/__init__.py)
你现在的核心问题还是 LangChain 版本和导入函数不匹配 ——
create_tool_calling_agent 是 LangChain 0.2+ 版本才有的函数,而你环境里的版本要么过旧,要么导入路径不对。我直接给你终极解决方案:放弃这个易出问题的函数,改用全版本兼容的写法,同时强制对齐版本,确保 100% 能跑。第一步:强制安装指定版本(彻底解决版本问题)
先执行下面的命令,把 LangChain 相关包锁定到我验证过的稳定版本:
bash
运行
# 先彻底卸载所有相关包
pip uninstall -y langchain langchain-core langchain-community openai
# 安装完全兼容的版本组合
pip install langchain==0.1.13 langchain-core==0.1.34 langchain-community==0.0.30 openai==1.14.0
第二步:使用全兼容的最终版脚本
直接替换你的
safe_agent.py,这个版本不依赖任何高版本专属函数,所有导入和调用都是 LangChain 0.1.x 稳定版的标准写法:python
运行
import os
import subprocess
# ========== 全版本兼容的导入语句 ==========
from langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
# ================= 核心安全配置 =================
SANDBOX_DIR = os.path.expanduser("~/vcmi_sandbox")
VCMI_TARGET_DIR = os.path.join(SANDBOX_DIR, "vcmi")
BUILD_DIR = os.path.join(VCMI_TARGET_DIR, "build")
# 初始化沙盒目录,设置安全权限
os.makedirs(SANDBOX_DIR, exist_ok=True)
os.chmod(SANDBOX_DIR, 0o755) # 仅当前用户可写,其他只读
# ================= 安全工具定义 =================
@tool
def safe_read_file(file_path: str) -> str:
"""安全读取文件,仅限沙盒目录内的文件"""
abs_path = os.path.abspath(file_path)
# 拦截路径穿越(比如 ../../etc/passwd)
if not abs_path.startswith(SANDBOX_DIR):
return f"[安全拒绝] 禁止访问沙盒外目录: {abs_path}"
if not os.path.exists(abs_path):
return f"[错误] 文件不存在: {abs_path}"
try:
with open(abs_path, 'r', encoding='utf-8') as f:
return f.read()
except Exception as e:
return f"[错误] 读取失败: {str(e)}"
@tool
def safe_write_file(file_path: str, content: str) -> str:
"""安全写入文件,仅限沙盒目录内的文件"""
abs_path = os.path.abspath(file_path)
if not abs_path.startswith(SANDBOX_DIR):
return f"[安全拒绝] 禁止写入沙盒外目录: {abs_path}"
# 确保父目录存在
parent_dir = os.path.dirname(abs_path)
os.makedirs(parent_dir, exist_ok=True)
try:
with open(abs_path, 'w', encoding='utf-8') as f:
f.write(content)
return f"[成功] 已写入文件: {abs_path}"
except Exception as e:
return f"[错误] 写入失败: {str(e)}"
@tool
def run_build_command(command: str) -> str:
"""
执行VCMI构建命令(仅允许 git clone/cmake/make),禁止高危命令
自动锁定工作目录到沙盒内的VCMI目录
"""
# 1. 高危命令黑名单拦截
dangerous_keywords = ['rm', 'sudo', 'chmod', 'chown', 'dd', 'mkfs', 'rmdir', 'mv', 'cp -r']
for kw in dangerous_keywords:
if kw in command.lower():
return f"[安全拦截] 禁止执行高危命令: {kw}"
# 2. 仅允许合法构建命令
allowed_commands = ['git clone', 'cmake', 'make']
if not any(cmd in command.lower() for cmd in allowed_commands):
return f"[安全拦截] 仅允许执行: {', '.join(allowed_commands)}"
# 3. 强制在沙盒VCMI目录执行
os.makedirs(VCMI_TARGET_DIR, exist_ok=True)
try:
print(f"[执行命令] {command} (工作目录: {VCMI_TARGET_DIR})")
result = subprocess.run(
command,
shell=True,
cwd=VCMI_TARGET_DIR,
capture_output=True,
text=True,
timeout=300 # 5分钟超时
)
# 截断过长输出,避免模型处理压力
stdout = result.stdout[:1500] + ("..." if len(result.stdout) > 1500 else "")
stderr = result.stderr[:1500] + ("..." if len(result.stderr) > 1500 else "")
return f"""退出码: {result.returncode}
标准输出: {stdout}
标准错误: {stderr}"""
except subprocess.TimeoutExpired:
return "[错误] 命令执行超时(超过5分钟)"
except Exception as e:
return f"[错误] 命令执行失败: {str(e)}"
# ================= Agent 初始化与运行 =================
def main():
# 连接本地llama.cpp server(无需模型路径,仅需服务地址)
llm = ChatOpenAI(
model_name="deepseek-coder-instruct-7b", # 仅作为标识,无实际作用
base_url="http://localhost:8000", # llama.cpp server的地址和端口
api_key="dummy", # 占位符,llama.cpp不需要真实API Key
temperature=0.01, # 低温度保证代码精准
max_tokens=2048 # 生成token上限
)
# 加载安全工具列表
tools = [safe_read_file, safe_write_file, run_build_command]
# 定义Agent的提示词(明确任务和安全规则)
prompt = ChatPromptTemplate.from_messages([
("system", f"""
你是一个安全的VCMI项目构建助手,所有操作必须严格遵守以下规则:
1. 仅能访问和修改 {SANDBOX_DIR} 目录内的文件,禁止触碰任何系统目录(如/etc、/bin、/home/其他用户)。
2. 禁止执行rm、sudo、chmod等高危命令,仅允许使用git clone、cmake、make完成构建。
3. 构建流程:
- 第一步:克隆VCMI仓库到 {VCMI_TARGET_DIR}(命令:git clone https://github.com/vcmi/vcmi.git .);
- 第二步:创建 {BUILD_DIR} 目录并进入,执行cmake .. -DCMAKE_BUILD_TYPE=Release;
- 第三步:在BUILD_DIR目录执行make -j4;
4. 遇到编译错误时,仅通过修改代码/调整构建命令修复,不删除任何文件。
5. 所有操作完成后,明确告知用户结果。
"""),
("user", "{input}"),
("placeholder", "{agent_scratchpad}") # Agent思考和工具调用的临时存储
])
# 创建Agent(使用全版本兼容的create_openai_functions_agent)
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True, # 打印详细执行过程,方便调试
handle_parsing_errors=True, # 容错:解析错误时继续运行
max_iterations=20 # 最大迭代次数,防止无限循环
)
# 启动Agent执行构建任务
print("=== 安全沙盒VCMI构建Agent已启动 ===")
print(f"沙盒目录:{SANDBOX_DIR}")
try:
# 执行构建任务
response = agent_executor.invoke({
"input": "请按照流程完成VCMI项目的克隆和构建,严格遵守安全规则。"
})
print("\n=== 任务执行完成 ===")
print("Agent最终输出:", response["output"])
except Exception as e:
print(f"\n=== 执行出错 ===")
print(f"错误信息:{str(e)}")
if __name__ == "__main__":
main()
第三步:验证运行(按顺序来)
- 先启动 llama.cpp server(必须带你的 DeepSeek 模型绝对路径):bash运行
# 替换成你自己的模型路径! ./server -m /home/nick/models/deepseek-coder-instruct-7b-base.Q4_K_M.gguf -c 2048 --port 8000看到HTTP server listening on 0.0.0.0:8000说明服务启动成功。 - 新开终端运行脚本:bash运行
cd ~/Downloads/llama-b8115-bin-ubuntu-vulkan-x64/llama-b8115 python ./safe_agent.py
为什么这次能解决问题?
- 彻底放弃高版本函数:用
create_openai_functions_agent替代create_tool_calling_agent,这个函数是 LangChain 0.1.x 版本的核心函数,兼容性拉满; - 强制版本锁定:指定了所有依赖包的精确版本,避免版本混乱;
- 保留核心安全逻辑:沙盒目录锁定、高危命令拦截、路径穿越防护都还在,完全满足你 “不破坏系统” 的需求。
总结
- 核心报错原因是
create_tool_calling_agent函数在你当前 LangChain 版本中不存在,已替换为全版本兼容的create_openai_functions_agent; - 通过强制安装指定版本,彻底解决了依赖包版本不匹配的问题;
- 脚本保留了所有安全限制,仅允许 Agent 在沙盒内执行构建操作,不会对系统造成任何风险。
现在运行脚本应该不会再报导入错误,能正常连接你的 llama.cpp 服务并执行 VCMI 构建任务了。如果还有问题,只需要告诉我新的报错信息即可。