别再让AI当嘴炮了!用Python给你的AI Agent装上手脚,让它真正帮你干活
别再让 AI 当嘴炮了!用 Python 给你的 AI Agent 装上手脚,让它真正帮你干活
摘要:你有没有发现,大多数 AI 对话都像在跟一个博学但瘫痪的天才聊天?它什么都知道,但什么都不能做。本文教你用 Python + OpenAI Function Calling,从零搭建一个能读文件、写代码、执行命令、搜索网络的 AI Agent。三个版本,从青铜到王者,附完整可运行代码。让你的 AI 从"嘴炮型选手"进化成"动手型选手"。
前言:AI 的"嘴炮困境"
各位程序员兄弟姐妹们好,我是你们的老朋友。
今天聊一个扎心的话题:你花了那么多钱订阅的 AI,到底帮你干了什么?
写个邮件?查个 API?解释一段代码?
恭喜你,你正在用一台"装了火箭发动机的拖拉机"来送快递。AI 最强大的能力——自主行动——被你白白浪费了。
想想看:
- 你问 AI:“帮我看看这个文件有什么问题” → AI 说:“请把文件内容贴给我” → 你手动复制粘贴 → AI 分析完 → 你手动改
- 你问 AI:“帮我搜一下这个库的最新版本” → AI 说:“根据我的训练数据…” → 数据是半年前的 → 你被坑了
- 你问 AI:“帮我跑一下测试” → AI 说:“你可以在终端执行…” → 你手动复制命令 → 跑完把结果贴回来 → AI 再分析
这叫什么?这叫人工智障流程。AI 负责"智能",你负责"人工"。
真正的 AI Agent 应该是这样的:
你:帮我看看 src/ 目录下有哪些 Python 文件有 bug
AI:好的,我来扫描一下...
→ [自动读取目录]
→ [自动逐个分析文件]
→ [自动运行 lint]
→ [自动运行测试]
→ 给你一份完整的报告,包含 3 个 bug 和修复建议
看到区别了吗? 前者是"聊天机器人",后者才是"AI Agent"。
今天,我就手把手教你,怎么用 Python 给你的 AI 装上手脚,让它从"嘴炮型选手"进化成"动手型选手"。
第一章:Function Calling——AI 的"手"
什么是 Function Calling?
简单说:Function Calling 就是让 AI 学会"打电话叫外卖"。
以前,AI 只能自己"做饭"(基于训练数据生成回答)。现在,它可以"打电话"(调用你预定义的函数),让它去读文件、查数据库、调 API。
传统 AI: 用户 → AI → 回答(基于记忆)
Agent: 用户 → AI → 判断需要什么工具 → 调用工具 → 拿到结果 → 继续推理 → 回答
最小可行示例
先来一个最简单的例子,让你感受一下:
import openai
import json
client = openai.OpenAI()
# 定义一个工具:计算器
tools = [
{
"type": "function",
"function": {
"name": "calculator",
"description": "计算数学表达式",
"parameters": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "数学表达式,如 '2 + 3 * 4'"
}
},
"required": ["expression"]
}
}
}
]
def calculator(expression: str) -> str:
"""安全地计算数学表达式"""
allowed = set("0123456789+-*/.() ")
if not all(c in allowed for c in expression):
return "错误:表达式包含非法字符"
try:
return str(eval(expression)) # 生产环境请用 ast.literal_eval 或 numexpr
except Exception as e:
return f"计算错误:{e}"
# 对话
messages = [{"role": "user", "content": "帮我算一下 (15 + 27) * 3 - 18 等于多少"}]
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
tool_choice="auto"
)
msg = response.choices[0].message
if msg.tool_calls:
for tool_call in msg.tool_calls:
func_name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
result = calculator(args["expression"])
print(f"AI 调用了 {func_name}({args['expression']}) = {result}")
输出:
AI 调用了 calculator((15 + 27) * 3 - 18) = 108
就这么简单。 AI 自己判断了需要用计算器,自己构造了表达式,自己调用了函数。
你没有手动算,没有手动复制,AI 自己搞定了。
第二章:给 AI 装一整套工具——青铜版 Agent
有了 Function Calling 的基础,我们来搭一个真正有用的 Agent。
工具箱设计
一个好的 Agent 需要这些工具:
| 工具 | 功能 | 用途 |
|---|---|---|
read_file |
读取文件 | 让 AI 看代码、看日志 |
write_file |
写入文件 | 让 AI 创建/修改文件 |
list_files |
列出目录 | 让 AI 了解项目结构 |
run_command |
执行命令 | 让 AI 运行测试、安装依赖 |
search_web |
搜索网络 | 让 AI 查最新文档 |
python_repl |
执行 Python | 让 AI 验证想法 |
完整代码:青铜版 Agent
import openai
import json
import os
import subprocess
import glob
from datetime import datetime
client = openai.OpenAI()
# ==================== 工具定义 ====================
def read_file(filepath: str) -> str:
"""读取文件内容"""
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
if len(content) > 5000:
content = content[:5000] + f"\n... [文件过大,已截断,共 {len(content)} 字符]"
return content
except Exception as e:
return f"读取失败:{e}"
def write_file(filepath: str, content: str) -> str:
"""写入文件内容"""
try:
os.makedirs(os.path.dirname(filepath), exist_ok=True)
with open(filepath, 'w', encoding='utf-8') as f:
f.write(content)
return f"文件已写入:{filepath}({len(content)} 字符)"
except Exception as e:
return f"写入失败:{e}"
def list_files(directory: str = ".", pattern: str = "*") -> str:
"""列出目录下的文件"""
try:
path = os.path.join(directory, pattern)
files = glob.glob(path, recursive=True)
if not files:
return f"未找到匹配的文件:{path}"
result = []
for f in sorted(files)[:50]: # 最多显示 50 个
size = os.path.getsize(f) if os.path.isfile(f) else 0
type_icon = "📁" if os.path.isdir(f) else "📄"
result.append(f"{type_icon} {f} ({size} bytes)")
return "\n".join(result)
except Exception as e:
return f"列出失败:{e}"
def run_command(command: str) -> str:
"""执行 shell 命令"""
try:
result = subprocess.run(
command, shell=True, capture_output=True,
text=True, timeout=30
)
output = result.stdout + result.stderr
if len(output) > 3000:
output = output[:3000] + "\n... [输出已截断]"
return f"退出码:{result.returncode}\n{output}"
except subprocess.TimeoutExpired:
return "命令超时(30秒)"
except Exception as e:
return f"执行失败:{e}"
def python_repl(code: str) -> str:
"""执行 Python 代码并返回结果"""
try:
# 安全限制:禁止危险操作
dangerous = ['os.system', 'subprocess', 'exec(', 'eval(', '__import__', 'open(']
for d in dangerous:
if d in code:
return f"安全限制:代码包含禁止的操作 '{d}'"
result = subprocess.run(
['python3', '-c', code],
capture_output=True, text=True, timeout=10
)
return result.stdout + result.stderr
except subprocess.TimeoutExpired:
return "代码执行超时(10秒)"
except Exception as e:
return f"执行失败:{e}"
def get_datetime() -> str:
"""获取当前日期和时间"""
return datetime.now().strftime("%Y-%m-%d %H:%M:%S %A")
# ==================== 工具注册 ====================
tools = [
{
"type": "function",
"function": {
"name": "read_file",
"description": "读取文件内容,支持代码、日志、配置文件等",
"parameters": {
"type": "object",
"properties": {
"filepath": {"type": "string", "description": "文件路径"}
},
"required": ["filepath"]
}
}
},
{
"type": "function",
"function": {
"name": "write_file",
"description": "写入文件,如果目录不存在会自动创建",
"parameters": {
"type": "object",
"properties": {
"filepath": {"type": "string", "description": "文件路径"},
"content": {"type": "string", "description": "要写入的内容"}
},
"required": ["filepath", "content"]
}
}
},
{
"type": "function",
"function": {
"name": "list_files",
"description": "列出目录下的文件和子目录",
"parameters": {
"type": "object",
"properties": {
"directory": {"type": "string", "description": "目录路径,默认当前目录"},
"pattern": {"type": "string", "description": "文件匹配模式,如 '*.py'"}
},
"required": []
}
}
},
{
"type": "function",
"function": {
"name": "run_command",
"description": "执行 shell 命令,可用于运行测试、安装包、查看系统信息等",
"parameters": {
"type": "object",
"properties": {
"command": {"type": "string", "description": "要执行的命令"}
},
"required": ["command"]
}
}
},
{
"type": "function",
"function": {
"name": "python_repl",
"description": "执行 Python 代码片段,用于验证想法、计算、数据处理",
"parameters": {
"type": "object",
"properties": {
"code": {"type": "string", "description": "要执行的 Python 代码"}
},
"required": ["code"]
}
}
},
{
"type": "function",
"function": {
"name": "get_datetime",
"description": "获取当前日期和时间",
"parameters": {"type": "object", "properties": {}}
}
}
]
# ==================== 工具映射 ====================
TOOL_MAP = {
"read_file": read_file,
"write_file": write_file,
"list_files": lambda directory=".", pattern="*": list_files(directory, pattern),
"run_command": run_command,
"python_repl": python_repl,
"get_datetime": get_datetime,
}
# ==================== Agent 核心循环 ====================
def run_agent(task: str, max_rounds: int = 10):
"""运行 Agent,自动调用工具完成任务"""
messages = [
{"role": "system", "content": (
"你是一个强大的 AI Agent。你有以下工具可以使用:\n"
"- read_file: 读文件\n"
"- write_file: 写文件\n"
"- list_files: 列目录\n"
"- run_command: 执行命令\n"
"- python_repl: 执行 Python 代码\n"
"- get_datetime: 获取时间\n"
"请根据用户需求,自主决定使用哪些工具。可以连续调用多个工具。"
)},
{"role": "user", "content": task}
]
for round_num in range(max_rounds):
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
tool_choice="auto"
)
msg = response.choices[0].message
messages.append(msg)
if not msg.tool_calls:
# 没有工具调用,说明 Agent 完成了任务
return msg.content
# 处理所有工具调用
for tool_call in msg.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
print(f" 🔧 调用工具:{func_name}({func_args})")
if func_name in TOOL_MAP:
result = TOOL_MAP[func_name](**func_args)
else:
result = f"未知工具:{func_name}"
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": str(result)
})
return "达到最大轮次,任务可能未完成"
# ==================== 测试 ====================
if __name__ == "__main__":
print("🤖 AI Agent 启动!\n")
# 测试 1:查看项目结构
print("📋 任务 1:查看当前目录有哪些 Python 文件")
result = run_agent("列出当前目录下所有的 Python 文件,告诉我每个文件的大小")
print(f"✅ 结果:{result}\n")
# 测试 2:写代码并测试
print("📋 任务 2:写一个斐波那契函数并测试")
result = run_agent(
"写一个 fibonacci 函数,保存到 fibonacci.py,然后用 Python 执行测试,"
"分别计算第 10、20、30 个斐波那契数"
)
print(f"✅ 结果:{result}\n")
# 测试 3:分析代码
print("📋 任务 3:分析 fibonacci.py 的代码质量")
result = run_agent("读取 fibonacci.py,分析代码质量,给出改进建议")
print(f"✅ 结果:{result}\n")
运行效果:
🤖 AI Agent 启动!
📋 任务 1:查看当前目录有哪些 Python 文件
🔧 调用工具:list_files({directory: '.', pattern: '*.py'})
✅ 结果:当前目录下有 3 个 Python 文件...
📋 任务 2:写一个斐波那契函数并测试
🔧 调用工具:write_file({filepath: 'fibonacci.py', content: '...'})
🔧 调用工具:python_repl({code: '...'})
✅ 结果:fib(10) = 55, fib(20) = 6765, fib(30) = 832040
Agent 自己完成了三步操作:写文件 → 运行测试 → 返回结果。全程你只说了一句话。
第三章:带记忆的 Agent——白银版
青铜版有个致命问题:每次对话都是从零开始的。 Agent 不记得之前做过什么。
这就好比你每天上班都要重新介绍自己:“你好,我是张三,我负责这个项目,昨天做到哪了来着?”
记忆系统设计
class Memory:
"""Agent 的记忆系统"""
def __init__(self, max_messages: int = 50):
self.conversation: list = [] # 对话历史
self.working_memory: dict = {} # 工作记忆(临时变量)
self.episodic_memory: list = [] # 情节记忆(重要事件)
self.max_messages = max_messages
def add_message(self, role: str, content: str, **kwargs):
"""添加消息到对话历史"""
msg = {"role": role, "content": content, **kwargs}
self.conversation.append(msg)
# 超过限制时,压缩旧消息
if len(self.conversation) > self.max_messages:
self._compress_old_messages()
def remember(self, key: str, value: str):
"""记住重要信息"""
self.working_memory[key] = value
self.episodic_memory.append({
"time": datetime.now().isoformat(),
"key": key,
"value": value
})
def recall(self, key: str) -> str:
"""回忆信息"""
return self.working_memory.get(key, "我不记得这个信息")
def _compress_old_messages(self):
"""压缩旧消息,保留关键信息"""
# 保留最近 20 条,其余总结
old = self.conversation[:-20]
self.conversation = self.conversation[-20:]
# 生成摘要
summary = "以下是之前对话的摘要:\n"
for msg in old:
if msg["role"] == "user":
summary += f"- 用户问了:{msg['content'][:100]}\n"
elif msg["role"] == "assistant" and msg.get("content"):
summary += f"- AI 做了:{msg['content'][:100]}\n"
self.conversation.insert(0, {"role": "system", "content": summary})
def get_context(self) -> str:
"""获取当前上下文摘要"""
context = []
if self.working_memory:
context.append("当前工作记忆:")
for k, v in self.working_memory.items():
context.append(f" - {k}: {v}")
return "\n".join(context)
升级版 Agent:带记忆 + 进度追踪
class SmartAgent:
"""带记忆和进度追踪的 Agent"""
def __init__(self, model: str = "gpt-4o"):
self.client = openai.OpenAI()
self.model = model
self.memory = Memory()
self.tools = [...] # 同上,省略
self.tool_map = {...} # 同上,省略
# 系统提示
self.system_prompt = """你是一个强大的 AI Agent,名叫"阿花"。
你的特点:
1. 你有工具可以使用,不要只是说"你可以怎么做",而是直接去做
2. 你会记住之前的操作结果,不会重复劳动
3. 如果遇到错误,你会分析原因并尝试修复,而不是放弃
4. 你完成任务后会给出清晰的总结
记住:行动 > 建议。做 > 说。"""
def run(self, task: str, max_rounds: int = 15) -> str:
"""执行任务"""
self.memory.add_message("user", task)
# 构建完整上下文
context = self.memory.get_context()
full_prompt = f"{self.system_prompt}\n\n当前上下文:\n{context}"
messages = [
{"role": "system", "content": full_prompt}
] + self.memory.conversation
for round_num in range(max_rounds):
response = self.client.chat.completions.create(
model=self.model,
messages=messages,
tools=self.tools,
tool_choice="auto"
)
msg = response.choices[0].message
messages.append(msg)
self.memory.add_message("assistant", msg.content or "")
if not msg.tool_calls:
return msg.content
for tool_call in msg.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
print(f" 🔧 [{round_num+1}] {func_name}({json.dumps(func_args, ensure_ascii=False)[:100]})")
if func_name in self.tool_map:
result = self.tool_map[func_name](**func_args)
else:
result = f"未知工具:{func_name}"
# 记住工具调用结果
self.memory.remember(f"tool_{round_num}_{func_name}", str(result)[:500])
tool_msg = {
"role": "tool",
"tool_call_id": tool_call.id,
"content": str(result)
}
messages.append(tool_msg)
self.memory.add_message("tool", str(result))
return "达到最大轮次,任务可能未完成"
第四章:ReAct 模式——黄金版
前面的 Agent 已经很不错了,但有个问题:它不够"有条理"。
有时候 AI 会一股脑地调用一堆工具,然后乱了套。就像一个实习生,接到任务就闷头干,干到一半发现方向错了。
ReAct 是什么?
ReAct = Reasoning + Acting(推理 + 行动)
核心思想:每一步都先想清楚再动手。
思考(Thought)→ 行动(Action)→ 观察(Observation)→ 思考 → 行动 → 观察 → ... → 回答
类比一下:
- 没有 ReAct 的 Agent:看到厨房着火了 → 随便抓起一个东西就泼 → 可能是油
- 有 ReAct 的 Agent:看到厨房着火了 → “这是油锅着火” → “不能用水” → “找灭火器” → 拿灭火器 → 灭火
实现 ReAct Agent
REACT_SYSTEM_PROMPT = """你是一个使用 ReAct(推理-行动)模式的 AI Agent。
对于每个任务,你必须按照以下格式输出:
Thought: [分析当前情况,思考下一步该做什么]
Action: [选择一个工具来执行]
Observation: [工具返回的结果]
Thought: [根据结果,思考下一步]
Action: [下一个工具调用]
...
Final Answer: [最终答案]
规则:
1. 每次只调用一个工具
2. 每次调用后都要分析结果
3. 如果工具返回错误,分析原因并尝试其他方案
4. 完成所有必要操作后,给出最终答案
"""
class ReActAgent:
"""ReAct 模式 Agent"""
def __init__(self, model: str = "gpt-4o"):
self.client = openai.OpenAI()
self.model = model
self.memory = Memory()
self.tools = [...] # 同上
self.tool_map = {...} # 同上
def run(self, task: str, max_steps: int = 10) -> str:
"""执行任务,使用 ReAct 模式"""
print(f"🤔 思考:收到任务 - {task}\n")
messages = [
{"role": "system", "content": REACT_SYSTEM_PROMPT},
{"role": "user", "content": task}
]
for step in range(max_steps):
response = self.client.chat.completions.create(
model=self.model,
messages=messages,
tools=self.tools,
tool_choice="auto"
)
msg = response.choices[0].message
if not msg.tool_calls:
# 没有工具调用 = 最终答案
return msg.content
# 执行工具
for tool_call in msg.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
print(f" 💭 思考:需要调用 {func_name}")
print(f" 🔧 行动:{func_name}({json.dumps(func_args, ensure_ascii=False)[:80]})")
if func_name in self.tool_map:
result = self.tool_map[func_name](**func_args)
else:
result = f"未知工具:{func_name}"
print(f" 👀 观察:{str(result)[:100]}...")
print()
messages.append(msg)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": str(result)
})
return "达到最大步骤数"
ReAct 的威力:实战对比
任务:“帮我找到项目里所有没有写 docstring 的函数,生成一个报告”
没有 ReAct:
AI: 好的,让我来分析...(一顿乱调工具,可能漏掉文件,可能重复读取)
有 ReAct:
🤔 思考:需要遍历项目中所有 Python 文件,找到没有 docstring 的函数
💭 思考:先看看项目结构
🔧 行动:list_files({directory: '.', pattern: '*.py'})
👀 观察:找到 15 个 Python 文件
💭 思考:需要逐个检查每个文件的函数
🔧 行动:run_command({command: 'python3 -c "import ast; ..."'})
👀 观察:utils.py 中有 3 个函数没有 docstring
💭 思考:继续检查其他文件...
...
✅ 最终答案:项目中共有 15 个 Python 文件,87 个函数,其中 12 个函数没有 docstring。
以下是详细报告...
看到区别了吗? ReAct 模式让 AI 的每一步都有迹可循,不会乱来。
第五章:高级技巧——让 Agent 更靠谱
1. 错误自愈
好的 Agent 不怕出错,怕的是出了错不知道怎么办。
def run_with_retry(self, task: str, max_retries: int = 3) -> str:
"""带重试的任务执行"""
for attempt in range(max_retries):
try:
result = self.run(task)
return result
except Exception as e:
if attempt < max_retries - 1:
print(f" ⚠️ 第 {attempt+1} 次尝试失败:{e},重试中...")
# 告诉 AI 出错了,让它调整策略
self.memory.add_message("system",
f"上次执行出错:{e}。请分析原因并换一种方式尝试。")
else:
return f"任务失败(重试 {max_retries} 次):{e}"
2. 工具调用的安全边界
永远不要给 AI 无限制的工具权限。 这不是不信任 AI,是不信任 bug。
SAFE_TOOLS = {"read_file", "list_files", "get_datetime", "python_repl"}
DANGEROUS_TOOLS = {"write_file", "run_command"}
def check_permission(func_name: str, func_args: dict) -> bool:
"""检查工具调用权限"""
if func_name in SAFE_TOOLS:
return True
if func_name in DANGEROUS_TOOLS:
# 危险操作需要确认
print(f"\n⚠️ AI 想要执行危险操作:{func_name}")
print(f" 参数:{json.dumps(func_args, ensure_ascii=False)}")
confirm = input(" 允许执行?(y/n): ")
return confirm.lower() == 'y'
return False
3. 并行工具调用
有时候 AI 需要同时做多件事,比如同时读取 5 个文件。OpenAI 支持并行工具调用:
# GPT-4o 会自动在一个响应中返回多个 tool_calls
# 你只需要全部执行,然后一起返回结果
for tool_call in msg.tool_calls: # 可能有多个
func_name = tool_call.function.name
# ... 并行执行所有工具调用
4. 流式输出
用户等得不耐烦了?加个流式输出:
def run_streaming(self, task: str):
"""流式输出 Agent 的思考过程"""
messages = [
{"role": "system", "content": self.system_prompt},
{"role": "user", "content": task}
]
response = self.client.chat.completions.create(
model=self.model,
messages=messages,
tools=self.tools,
stream=True # 启用流式
)
for chunk in response:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
第六章:实战案例——让 Agent 帮你做代码审查
来一个完整的实战:让 AI Agent 自动审查你的代码。
def code_review_agent(project_path: str):
"""AI 代码审查 Agent"""
agent = SmartAgent()
task = f"""
请对 {project_path} 进行全面的代码审查:
1. 先列出项目结构
2. 逐个读取 Python 文件
3. 检查以下问题:
- 代码风格(PEP 8)
- 安全漏洞(SQL 注入、XSS 等)
- 性能问题(N+1 查询、不必要的循环等)
- 缺失的类型注解
- 缺失的 docstring
- 可能的 bug
4. 对每个问题给出具体的修复建议
5. 生成一份审查报告,保存到 review_report.md
"""
result = agent.run(task)
print(result)
# 使用
code_review_agent("./my_project")
Agent 会自动:
🔧 list_files({directory: './my_project', pattern: '*.py'})
🔧 read_file({filepath: './my_project/main.py'})
🔧 read_file({filepath: './my_project/utils.py'})
🔧 read_file({filepath: './my_project/models.py'})
...
📝 write_file({filepath: 'review_report.md', content: '...'})
最后生成一份完整的代码审查报告。
总结
| 版本 | 特点 | 适用场景 |
|---|---|---|
| 青铜版 | 基础工具调用 | 简单的自动化任务 |
| 白银版 | 带记忆系统 | 多轮对话、复杂任务 |
| 黄金版 | ReAct 模式 | 需要推理的复杂场景 |
关键要点
- Function Calling 是基础:让 AI 从"能说"变成"能做"
- 记忆是关键:没有记忆的 Agent 就像金鱼,只有 7 秒记忆
- ReAct 让 Agent 更靠谱:先想后做,步步为营
- 安全永远是第一位:永远不要给 AI 无限制的权限
- 从小处开始:先让 Agent 做简单的任务,再逐步增加复杂度
最后的话
AI Agent 不是科幻,是正在发生的现实。
当你的同行还在手动复制粘贴代码给 AI 分析的时候,你已经让 AI 自己读文件、跑测试、写报告了。
这不是降维打击,这是降本增效。
当然,AI Agent 也不是万能的。它可能读错文件,可能调用错误的函数,可能把项目搞崩。所以:
- 永远做好版本控制(git 是你的好朋友)
- 永远设置安全边界(不要让 AI 删生产数据库)
- 永远人工审核关键操作(AI 建议 ≠ AI 决定)
好了,去给你的 AI 装上手脚吧。让它从"嘴炮型选手"变成"动手型选手"。
你的 AI 值得更好的。你的生产力也是。
🔧 本文代码已测试通过,Python 3.10+,OpenAI API v1.x
💡 完整代码仓库:GitHub(欢迎 Star)
📧 有问题?评论区见!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)