从零实现AI编程助手:基于本地大模型构建Claude Code核心引擎 1. 项目概述为什么我们要亲手实现一个“Claude Code”最近在AI编程圈子里“Claude Code”这个概念的热度居高不下。很多朋友在搜索怎么安装、怎么配置甚至想搞清楚它和Codex有什么区别。但说实话作为一个在AI工具和自动化开发领域摸爬滚打了多年的老手我更感兴趣的是“实现”本身。市面上现成的工具固然方便但知其然更要知其所以然。今天我们就抛开那些复杂的安装包和商业API回归本质用Python从零开始手搓一个具备基础能力的“AI编程助手核心”。这不仅能让你彻底理解所谓“Claude Code”或“AI Agent”在编程场景下的工作原理更能让你获得根据自己需求定制和优化它的能力这才是真正的“超级小白入门指南”的终极形态。我们这里要实现的不是一个要替代VS Code的庞然大物而是一个聚焦于“代码理解与生成”的智能体Agent核心引擎。你可以把它想象成一个命令行工具或者未来集成到你的IDE插件里的“大脑”。它的核心任务是接收你的自然语言描述比如“写一个Python函数计算斐波那契数列”理解你的意图然后调用合适的工具比如代码生成模型、代码解释器来完成任务最后把可运行、可验证的代码交还给你。整个过程我们将深入每一个环节从环境搭建、模型选择与接入、智能体逻辑设计到最后的集成与测试全程代码级实操。2. 核心思路与架构设计2.1 目标拆解一个最小可行产品MVP应该做什么在开始写代码之前我们必须明确目标。一个全功能的AI编程助手涉及代码补全、错误诊断、代码重构、文档生成等数十个功能。我们不可能一蹴而就。因此我决定为这个“手搓版Claude Code”设定一个清晰的MVP目标实现一个能够理解简单编程任务描述并生成对应Python代码的对话式智能体。具体来说它需要完成以下闭环自然语言理解能解析用户诸如“帮我写个快速排序算法”、“创建一个从API获取数据并保存到CSV的脚本”这样的指令。任务规划与工具调用根据指令决定需要调用哪些“工具”。在我们的MVP里核心工具就是一个“代码生成器”。未来可以扩展“代码执行器”、“代码分析器”等。代码生成与返回利用大语言模型LLM生成符合要求的Python代码并以清晰、安全的方式呈现给用户。基于这个目标我们的技术栈选择就非常明确了Python作为主语言利用其丰富的AI生态选择一款性能足够且易于本地部署或API调用的开源LLM作为“大脑”设计一个轻量级的智能体框架来组织逻辑。2.2 技术选型背后的“为什么”为什么用Python这几乎是AI项目的事实标准。从模型调用OpenAI SDK Hugging Face Transformers到智能体框架LangChain LlamaIndexPython拥有最完善的库支持。我们的项目本质是AI应用用Python能最大程度减少环境摩擦。模型选型本地还是云端这是关键决策。直接使用Claude或GPT-4的API最简单但涉及网络、费用和隐私。为了追求“从零实现”的纯粹性和可控性我选择使用本地部署的开源模型。这里我推荐DeepSeek-Coder系列模型它在代码生成任务上表现非常出色并且有不同规模的版本如1.3B, 6.7B, 33B可以根据你的显卡显存量力而行。使用本地模型意味着我们需要解决模型加载、推理加速等问题但这正是学习的价值所在。智能体框架造轮子还是用轮子LangChain非常强大但为了极致地理解原理我决定自己实现核心的智能体循环。这能让我们对智能体如何思考、如何决策有肌肉记忆般的理解。当然在后续优化中我们可以借鉴成熟框架的设计思想。最终架构图景整个项目将分为几个核心模块ModelClient: 封装与大语言模型的交互无论是本地模型还是云端API。CodeAgent: 智能体的核心类包含对话历史管理、任务解析和工具调用的逻辑。Tools: 工具集合至少包含一个CodeGenerationTool。Main: 提供命令行交互界面启动智能体循环。3. 环境准备与核心依赖安装3.1 Python环境搭建要点虽然标题是“从零实现”但我假设你已经安装了Python。这里重点强调版本和包管理器的选择。强烈建议使用Python 3.10或3.11这是目前多数AI库兼容性最好的版本。避免使用最新的3.12或较旧的3.7可能会遇到意想不到的依赖冲突。包管理器首推uv或pdm它们比传统的pip更快、更现代能更好地处理依赖隔离。但为了最广泛的适用性我们这里还是使用pip配合venv虚拟环境。# 创建并激活虚拟环境 (Linux/macOS) python3.10 -m venv claude-code-env source claude-code-env/bin/activate # 创建并激活虚拟环境 (Windows) python -m venv claude-code-env claude-code-env\Scripts\activate激活后命令行提示符前会出现(claude-code-env)这代表你正工作在一个干净的Python沙箱中。3.2 安装关键依赖库接下来安装我们项目所需的库。我们将主要依赖transformers和torch来运行本地LLM。# 首先升级pip pip install --upgrade pip # 安装PyTorch请根据你的CUDA版本到官网https://pytorch.org/获取最准确的安装命令 # 例如对于CUDA 11.8 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 安装Transformers和加速库 pip install transformers accelerate sentencepiece # 安装其他辅助库用于工具调用结果验证的ast和codeop是标准库无需安装。 # 安装一个颜色输出库让命令行更美观可选 pip install rich注意PyTorch的安装是最大的坑点之一。务必去官网核对你的CUDA版本通过nvidia-smi查看选择对应的安装命令。如果没有NVIDIA显卡就安装CPU版本 (pip install torch torchvision torchaudio)但推理速度会慢很多。3.3 模型下载与准备我们选择deepseek-ai/deepseek-coder-1.3b-instruct这个模型作为起点。它参数量小对显存要求低约3GB适合大多数消费级显卡且指令跟随能力不错。我们可以通过编程方式在第一次运行时下载但为了更稳定建议预先下载到本地。使用huggingface-cli工具安装huggingface_hub库后可用或直接使用snapshot_download。# 这是一个预下载模型的脚本你可以保存为 download_model.py 并运行 from huggingface_hub import snapshot_download model_id deepseek-ai/deepseek-coder-1.3b-instruct local_dir ./models/deepseek-coder-1.3b-instruct snapshot_download(repo_idmodel_id, local_dirlocal_dir, local_dir_use_symlinksFalse) print(f模型已下载到: {local_dir})运行这个脚本它会将模型文件下载到当前目录下的models文件夹中。请确保你的磁盘有足够的空间约2.5GB。4. 核心模块一大语言模型客户端封装4.1 设计一个通用的ModelClient类我们的智能体需要与模型对话所以第一步是抽象出一个模型客户端。这个客户端要能处理不同的模型后端虽然我们现在只用本地DeepSeek-Coder为未来切换模型比如换用Qwen-Coder或调用OpenAI API留出接口。# model_client.py import torch from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline from typing import Optional, List, Dict, Any class ModelClient: def __init__(self, model_path: str, model_type: str local): 初始化模型客户端。 Args: model_path: 模型路径。对于本地模型是本地目录路径对于API模型是API端点。 model_type: 模型类型local 或 openai (未来扩展)。 self.model_type model_type self.model_path model_path self.device cuda if torch.cuda.is_available() else cpu print(f正在使用设备: {self.device}) if model_type local: self._load_local_model() else: # 这里可以扩展 OpenAI 或其他 API 客户端的初始化 raise NotImplementedError(f模型类型 {model_type} 尚未实现) def _load_local_model(self): 加载本地 Hugging Face 模型和分词器。 print(f正在从 {self.model_path} 加载模型和分词器...) try: self.tokenizer AutoTokenizer.from_pretrained(self.model_path, trust_remote_codeTrue) # 注意对于代码生成模型通常需要设置 pad_token if self.tokenizer.pad_token is None: self.tokenizer.pad_token self.tokenizer.eos_token self.model AutoModelForCausalLM.from_pretrained( self.model_path, torch_dtypetorch.float16 if self.device cuda else torch.float32, # GPU上用半精度节省显存 device_mapauto, # 让 accelerate 库自动分配模型层到设备 trust_remote_codeTrue ) # 创建文本生成管道简化调用 self.pipe pipeline( text-generation, modelself.model, tokenizerself.tokenizer, deviceself.device, ) print(模型加载完成) except Exception as e: print(f模型加载失败: {e}) raise def generate(self, prompt: str, max_new_tokens: int 512, temperature: float 0.7) - str: 根据提示词生成文本。 Args: prompt: 输入的提示文本。 max_new_tokens: 最大生成token数。 temperature: 采样温度控制随机性。越低越确定越高越有创意。 Returns: 生成的文本。 if self.model_type local: return self._generate_local(prompt, max_new_tokens, temperature) # 其他类型的生成逻辑... def _generate_local(self, prompt: str, max_new_tokens: int, temperature: float) - str: 使用本地模型生成。 try: # 使用pipeline进行生成并设置生成参数 outputs self.pipe( prompt, max_new_tokensmax_new_tokens, temperaturetemperature, do_sampleTrue, # 启用采样 top_p0.95, # 核采样参数与temperature配合使用 pad_token_idself.tokenizer.pad_token_id, eos_token_idself.tokenizer.eos_token_id, return_full_textFalse, # 只返回新生成的部分 ) generated_text outputs[0][generated_text] return generated_text.strip() except Exception as e: return f[模型生成错误] {e}这个类做了几件关键事1) 自动检测并使用GPU2) 使用pipeline简化调用3) 设置了适合代码生成的参数如temperature0.7在创造性和准确性间取得平衡4) 良好的错误处理。trust_remote_codeTrue对于某些自定义模型的加载是必须的。4.2 模型调用参数详解与调优心得在_generate_local方法中我们设置了一系列参数它们直接影响到生成代码的质量max_new_tokens512对于大多数函数级代码片段足够了。如果你需要生成整个文件可以增加到1024或2048但要警惕模型“胡言乱语”或生成无关内容。temperature0.7这是我经过多次测试后认为适合代码生成的“甜点”。temperature0.1会使输出非常确定但可能死板、重复temperature1.0又会太天马行空可能生成语法错误的代码。0.7左右能在遵循指令和保持多样性间取得不错平衡。top_p0.95这是“核采样”Nucleus Sampling参数。它和温度采样一起工作限制模型只从概率质量占前95%的词汇中采样能有效避免生成低概率的奇怪token提高输出质量。do_sampleTrue必须设置为True才能启用温度采样和核采样。如果设为False模型将使用贪婪解码每次都选概率最高的词结果会非常单调。实操心得不同的模型对参数敏感度不同。DeepSeek-Coder对温度比较敏感而有些模型可能对top_p更敏感。最好的方法是针对你的主要任务如“写排序算法”、“写数据处理脚本”准备一组测试用例然后微调这些参数观察生成代码的准确性、简洁性和多样性找到最适合你当前模型和任务的“黄金参数”。5. 核心模块二工具Tools的设计与实现5.1 定义工具基类在智能体范式中工具Tool是智能体可以调用来执行特定操作的函数。我们先定义一个所有工具都必须遵循的基类确保接口统一。# tools/base_tool.py from abc import ABC, abstractmethod from typing import Dict, Any class BaseTool(ABC): 所有工具的基类。 name: str # 工具的唯一名称用于智能体识别 description: str # 工具的自然语言描述用于提示工程 abstractmethod def run(self, **kwargs) - str: 运行工具的核心方法。 Args: **kwargs: 工具运行所需的参数。 Returns: 工具执行结果的字符串描述。 pass def to_dict(self) - Dict[str, Any]: 将工具信息转换为字典方便构造提示词。 return { name: self.name, description: self.description }5.2 实现代码生成工具这是我们智能体最核心的工具。它的run方法接收一个“任务描述”然后调用我们之前封装的ModelClient来生成代码。# tools/code_generation_tool.py from .base_tool import BaseTool from model_client import ModelClient import re class CodeGenerationTool(BaseTool): 根据自然语言描述生成Python代码的工具。 name generate_python_code description 根据用户的自然语言描述生成相应的Python代码。输入应为清晰的任务描述。 def __init__(self, model_client: ModelClient): super().__init__() self.model_client model_client # 构造一个更有效的系统提示词引导模型生成高质量代码 self.system_prompt 你是一个专业的Python程序员助手。你的任务是根据用户的请求生成正确、高效、可读的Python代码。 请遵循以下规则 1. 只输出代码本身不要输出任何解释、注释以外的额外文本。 2. 如果请求不明确请生成一个合理的、通用的实现。 3. 确保代码语法正确并包含必要的导入语句。 4. 如果生成函数请包含一个简单的示例调用注释掉或放在 if __name__ __main__: 块中。 用户请求 def run(self, task_description: str) - str: 生成Python代码。 Args: task_description: 用自然语言描述的编程任务。 Returns: 生成的Python代码字符串或错误信息。 if not task_description: return 错误任务描述不能为空。 full_prompt self.system_prompt task_description print(f[工具调用] {self.name}: 正在为任务生成代码...) try: raw_output self.model_client.generate(full_prompt, max_new_tokens768) # 后处理尝试从模型输出中提取代码块。模型有时会输出 Markdown 格式。 cleaned_code self._extract_code(raw_output) return cleaned_code except Exception as e: return f代码生成过程中出现错误: {e} def _extract_code(self, text: str) - str: 从模型输出中提取Python代码块。 # 匹配Markdown代码块 python ... pattern r(?:python)?\n?(.*?) matches re.findall(pattern, text, re.DOTALL) if matches: # 返回最后一个代码块的内容模型有时会先解释再给代码 return matches[-1].strip() else: # 如果没有代码块假设整个输出就是代码去除可能的前导/尾随空白行 lines text.strip().split(\n) # 简单过滤掉明显不是代码的行以“解释”、“首先”等开头的中文句子 code_lines [line for line in lines if not line.startswith((解释, 首先, 其次, 然后, 最后, 因此, 所以, 例如))] return \n.join(code_lines).strip()这个工具类有几个设计亮点系统提示词System Prompt这是引导模型行为的关键。我们明确要求模型“只输出代码”并给出了一些格式要求这能显著提高输出代码的纯净度。后处理_extract_code方法非常重要。大语言模型喜欢用Markdown格式输出代码我们需要将其剥离只返回纯代码。这个简单的正则匹配能解决80%的情况。错误处理在工具层面进行基本的输入验证和异常捕获防止智能体主循环因单个工具失败而崩溃。注意事项系统提示词的编写是门艺术。过于简略模型可能输出多余解释过于严格又可能限制其创造力。这里的提示词是一个不错的起点你可以根据生成结果不断迭代优化。例如如果你发现模型经常忘记写导入可以把规则3改成“必须包含所有必要的导入语句”。6. 核心模块三智能体Agent的逻辑与循环6.1 构建智能体核心记忆、思考与行动智能体是大脑它需要记忆对话历史、思考分析用户输入决定做什么和行动调用工具。我们实现一个简单的基于ReActReasoning Acting模式的智能体。# agent/code_agent.py from typing import List, Dict, Any from tools.base_tool import BaseTool from model_client import ModelClient import json class CodeAgent: 一个简单的代码生成智能体。 def __init__(self, model_client: ModelClient, tools: List[BaseTool]): 初始化智能体。 Args: model_client: 用于智能体自身“思考”的模型客户端。 tools: 智能体可以使用的工具列表。 self.model_client model_client self.tools {tool.name: tool for tool in tools} # 工具字典便于按名称查找 self.conversation_history: List[Dict[str, str]] [] # 存储对话轮次 # 智能体“思考”时使用的系统提示词 self.agent_system_prompt 你是一个AI编程助手。你的目标是理解用户的请求并决定使用哪个工具来完成任务。 你可以使用的工具如下 {tools_list} 请严格按照以下格式回应 1. 首先分析用户请求思考需要完成什么任务。 2. 然后决定使用哪个工具必须是上述工具之一。如果用户请求无法用现有工具处理请直接回复“我无法处理这个请求”。 3. 最后以JSON格式输出你的决定格式为{{thought: 你的思考过程, tool_to_use: 工具名称, tool_input: {{参数名: 参数值}}}}。 用户请求 def _format_tools_list(self) - str: 将工具列表格式化为字符串用于构造提示词。 tools_str_list [] for tool in self.tools.values(): tools_str_list.append(f- {tool.name}: {tool.description}) return \n.join(tools_str_list) def _parse_agent_response(self, response: str) - Dict[str, Any]: 解析智能体“思考”后的响应提取JSON部分。 这是一个简单的解析实际应用中可能需要更鲁棒的方法。 # 尝试找到JSON块 try: # 查找第一个 { 和最后一个 } start response.find({) end response.rfind(}) 1 if start -1 or end 0: raise ValueError(未找到有效的JSON响应) json_str response[start:end] return json.loads(json_str) except (ValueError, json.JSONDecodeError) as e: print(f解析智能体响应失败: {e}, 原始响应: {response}) # 返回一个安全的默认响应 return { thought: 响应解析失败。, tool_to_use: None, tool_input: {} } def process_request(self, user_input: str) - str: 处理用户的一次输入。 Args: user_input: 用户输入的自然语言请求。 Returns: 智能体的最终回复通常是工具执行结果。 print(f\n[用户] {user_input}) # 1. 更新对话历史 self.conversation_history.append({role: user, content: user_input}) # 2. 智能体“思考”决定使用哪个工具 tools_list_str self._format_tools_list() prompt_for_agent self.agent_system_prompt.format(tools_listtools_list_str) user_input agent_thinking self.model_client.generate(prompt_for_agent, max_new_tokens256, temperature0.3) # 思考过程需要更确定 print(f[智能体思考] {agent_thinking}) # 3. 解析思考结果 decision self._parse_agent_response(agent_thinking) thought_process decision.get(thought, ) tool_name decision.get(tool_to_use) tool_input decision.get(tool_input, {}) # 4. 执行工具 if tool_name and tool_name in self.tools: print(f[智能体决策] 决定使用工具: {tool_name}, 输入: {tool_input}) tool self.tools[tool_name] # 这里假设工具输入是一个字典且键对应工具的run方法参数名。 # 对于我们的代码生成工具键是task_description。 try: # 将字典解包作为关键字参数传入 tool_result tool.run(**tool_input) except TypeError as e: tool_result f工具调用参数错误: {e}。期望参数: {tool_input} else: tool_result 抱歉我无法找到合适的工具来处理您的请求。 # 5. 将结果返回给用户并更新历史 self.conversation_history.append({role: assistant, content: tool_result}) return tool_result这个CodeAgent类实现了核心的ReAct循环接收请求将用户输入加入对话历史。思考Reasoning利用一个专门的“思考模型”这里为了简化和生成代码用同一个模型但用了更低的temperature0.3使其决策更稳定分析请求并规划行动。系统提示词明确要求输出结构化的JSON。解析决策从模型的文本响应中提取出JSON格式的决策。行动Acting根据决策调用对应的工具并传入参数。观察与响应将工具执行结果作为智能体的响应返回给用户并存入历史。6.2 智能体提示词工程实战智能体的性能很大程度上取决于提示词。我们的agent_system_prompt有几个关键设计明确角色和工具告诉模型“你是谁”和“你能用什么”。强制结构化输出要求模型以特定JSON格式回应这极大简化了后续的解析逻辑。这是一种“指令微调”的思想引导模型输出机器可读的格式。分步思考提示词中要求“首先...然后...”这鼓励模型进行链式思考Chain-of-Thought往往能提高决策的准确性。_parse_agent_response方法是一个简单的解析器。在实际生产环境中你可能需要使用更高级的技术比如让模型输出严格的JSON通过设置response_format参数如果API支持或者使用专门的解析库来处理模型可能输出的非标准JSON。7. 主程序集成与交互界面7.1 组装所有部件现在让我们把模型、工具和智能体组装起来并创建一个简单的命令行交互界面。# main.py import sys import os sys.path.append(os.path.dirname(os.path.abspath(__file__))) from model_client import ModelClient from tools.code_generation_tool import CodeGenerationTool from agent.code_agent import CodeAgent def main(): print( * 50) print( Claude Code 核心引擎 - 从零实现版) print( * 50) # 1. 初始化模型客户端 # 修改为你的模型实际路径 MODEL_PATH ./models/deepseek-coder-1.3b-instruct if not os.path.exists(MODEL_PATH): print(f错误未在 {MODEL_PATH} 找到模型文件。) print(请先运行 download_model.py 下载模型。) return print(正在初始化模型客户端...) try: model_client ModelClient(model_pathMODEL_PATH, model_typelocal) except Exception as e: print(f模型客户端初始化失败: {e}) return # 2. 初始化工具 print(正在初始化工具...) code_tool CodeGenerationTool(model_client) # 3. 初始化智能体并为其装配工具 print(正在初始化智能体...) agent CodeAgent(model_clientmodel_client, tools[code_tool]) # 4. 启动交互循环 print(\n智能体就绪请输入你的编程任务例如写一个函数计算圆的面积输入 quit 或 exit 退出。) print(- * 50) while True: try: user_input input(\n ).strip() except (EOFError, KeyboardInterrupt): print(\n\n再见) break if user_input.lower() in [quit, exit, q]: print(再见) break if not user_input: continue # 处理请求 response agent.process_request(user_input) print(f\n[助手] \npython\n{response}\n) if __name__ __main__: main()这个主程序流程清晰初始化模型 - 初始化工具 - 初始化智能体 - 进入REPL读取-求值-打印循环交互模式。用户输入自然语言指令智能体处理后返回生成的代码。7.2 首次运行与效果测试现在激动人心的时刻到了。在项目根目录下运行python main.py你会看到加载模型的输出然后出现提示符。尝试输入一些指令 写一个Python函数计算斐波那契数列的第n项如果一切顺利几秒到几十秒后取决于你的硬件你将看到类似以下的输出[智能体思考] 首先用户请求是写一个计算斐波那契数列第n项的Python函数。这是一个明确的代码生成任务。我可以使用 generate_python_code 工具。工具输入应该是任务描述。{thought: 用户需要生成计算斐波那契数列的代码。, tool_to_use: generate_python_code, tool_input: {task_description: 写一个Python函数计算斐波那契数列的第n项}} [智能体决策] 决定使用工具: generate_python_code, 输入: {task_description: 写一个Python函数计算斐波那契数列的第n项} [工具调用] generate_python_code: 正在为任务生成代码... [助手] python def fibonacci(n): if n 0: return 输入必须为正整数 elif n 1: return 0 elif n 2: return 1 else: a, b 0, 1 for _ in range(2, n): a, b b, a b return b if __name__ __main__: # 示例调用 print(fibonacci(10)) # 输出第10项恭喜你已经成功运行了你亲手打造的“Claude Code”核心它理解了你的指令决定调用代码生成工具并生成了可运行的Python代码。虽然可能不如顶尖商业模型生成得完美比如斐波那契数列通常认为前两项是0,1或1,1这里采用了0,1的定义但作为一个1.3B参数本地模型这个结果已经相当可用。 ## 8. 性能优化与功能扩展实战 ### 8.1 推理速度优化技巧 本地模型推理慢是最大的体验瓶颈。除了升级硬件我们可以在软件层面做很多优化 1. **量化Quantization**将模型权重从FP16半精度转换为INT8甚至INT4能大幅减少显存占用并提升推理速度精度损失通常可控。使用 bitsandbytes 库可以轻松实现4/8位量化加载。 python # 修改 model_client.py 中的 _load_local_model 方法 from transformers import BitsAndBytesConfig # 在加载模型前配置量化 quantization_config BitsAndBytesConfig( load_in_4bitTrue, # 使用4位量化 bnb_4bit_compute_dtypetorch.float16, bnb_4bit_use_double_quantTrue, bnb_4bit_quant_typenf4 # 一种高效的4位量化类型 ) self.model AutoModelForCausalLM.from_pretrained( self.model_path, quantization_configquantization_config, # 加入这行 device_mapauto, trust_remote_codeTrue ) 使用4位量化后原本需要3GB显存的模型可能只需要不到1GB推理速度也能提升。 2. **使用更快的推理后端**transformers 的 pipeline 很方便但未必最快。可以尝试 vLLM 或 TGI (Text Generation Inference) 等专门优化的推理服务器它们支持连续批处理、PagedAttention等技术吞吐量极高。对于本地开发vLLM 易于集成。 3. **缓存Caching**对于重复或相似的提示词可以缓存模型的输出避免重复计算。这在交互式对话中很有效。 ### 8.2 扩展新工具代码执行与验证 一个只会生成代码的助手是不够的。让我们为其增加一个“代码执行工具”让智能体可以运行生成的代码并返回结果实现“生成-运行-调试”的闭环。 python # tools/code_execution_tool.py import subprocess import tempfile import os from .base_tool import BaseTool class CodeExecutionTool(BaseTool): 在安全沙箱中执行Python代码并返回结果的工具。 name execute_python_code description 执行一段Python代码字符串并返回其输出或错误信息。输入应为 {code: 要执行的代码字符串}。 def run(self, code: str) - str: if not code: return 错误代码字符串为空。 # 创建一个临时文件来存放代码 with tempfile.NamedTemporaryFile(modew, suffix.py, deleteFalse) as f: f.write(code) temp_file_path f.name try: # 使用 subprocess 运行代码设置超时防止死循环 result subprocess.run( [sys.executable, temp_file_path], # 使用当前Python解释器 capture_outputTrue, textTrue, timeout10, # 10秒超时 cwdos.path.dirname(temp_file_path) # 在临时文件所在目录运行 ) output result.stdout error result.stderr if result.returncode 0: return f执行成功:\n{output} if output else 执行成功无输出。 else: return f执行出错返回码 {result.returncode}:\n{error} except subprocess.TimeoutExpired: return 错误代码执行超时超过10秒可能包含死循环。 except Exception as e: return f执行过程发生异常: {e} finally: # 清理临时文件 os.unlink(temp_file_path)安全警告执行任意代码是极度危险的操作上述实现使用了subprocess在独立的进程中运行代码并设置了超时这提供了一定的隔离性但绝非完全安全。恶意代码仍可能消耗大量资源、访问受限文件等。在生产环境中必须使用更严格的沙箱技术如 Docker 容器、gVisor 或专门的代码执行服务。将这个新工具加入到主程序的工具列表中并更新智能体的系统提示词包含新工具的描述。现在你可以对智能体说“生成一个计算阶乘的函数并执行它看看结果。” 智能体会先调用generate_python_code再调用execute_python_code并将最终结果返回给你。8.3 实现多轮对话与上下文管理目前的智能体虽然维护了conversation_history但在“思考”时并没有充分利用完整的对话历史作为上下文。为了实现真正的多轮对话例如用户说“优化一下刚才的函数”我们需要修改process_request方法在构造给“思考模型”的提示词时附上最近几轮的历史。# 在 CodeAgent 类中修改或添加方法 def _construct_agent_prompt(self, user_input: str) - str: 构造包含对话历史的智能体提示词。 tools_list_str self._format_tools_list() prompt self.agent_system_prompt.format(tools_listtools_list_str) # 添加最近3轮对话历史可根据需要调整 recent_history self.conversation_history[-6:] # 最近3轮每轮userassistant if recent_history: history_text \n之前的对话\n for msg in recent_history: role 用户 if msg[role] user else 助手 history_text f{role}: {msg[content]}\n prompt history_text prompt f\n当前用户请求{user_input} return prompt # 然后在 process_request 中用 self._construct_agent_prompt(user_input) 替换原来的 prompt_for_agent这样智能体在决策时就能“记得”之前说过什么从而实现基于上下文的连续对话。9. 常见问题排查与调试心得在实际运行中你肯定会遇到各种问题。这里记录一些我踩过的坑和解决方案。9.1 模型加载失败或推理错误报错CUDA out of memory原因模型太大显存不足。解决换用更小的模型如deepseek-coder-1.3b-instruct-deepseek-coder-6.7b-instruct需要更多显存。启用量化如上述的4位量化。使用CPU模式devicecpu但速度极慢。使用device_mapauto让accelerate自动将模型层分配到多个GPU或CPU和GPU之间。报错The model XXX is not supported for text-generation原因模型本身不是因果语言模型Causal LM或者transformers库无法自动识别其架构。解决检查模型卡Model Card确认它是否支持文本生成任务。对于某些自定义模型可能需要传递trust_remote_codeTrue并确保有对应的generation_config。生成结果乱码或毫无意义原因温度 (temperature) 设置过高或者提示词 (prompt) 格式不符合模型训练时的格式。解决降低temperature如从0.7调到0.3。检查并模仿模型训练时使用的提示词模板。例如DeepSeek-Coder-Instruct 模型通常使用### Instruction:\n{instruction}\n\n### Response:\n这样的格式。修改CodeGenerationTool中的system_prompt来匹配这个格式可能会显著提升效果。9.2 智能体决策逻辑错误智能体总是选择错误的工具或不输出JSON原因提示词不够清晰或者“思考模型”的能力不足。解决强化提示词在agent_system_prompt中更严格地规定输出格式甚至给出例子Few-Shot Prompting。例如在提示词末尾加上示例输出{thought: ..., tool_to_use: generate_python_code, tool_input: {task_description: ...}}。使用更强的模型进行思考如果条件允许可以用一个更大的模型如Qwen-7B专门负责“思考”和规划用较小的模型如DeepSeek-Coder-1.3B负责代码生成。这被称为“模型级联”Model Cascading。后处理纠错在_parse_agent_response中实现更鲁棒的逻辑比如如果解析JSON失败可以尝试用正则表达式提取关键字段或者让模型重试。工具调用参数不匹配原因智能体输出的tool_input字典的键与工具run方法的参数名不匹配。解决确保一致性。例如CodeGenerationTool.run期望参数task_description那么智能体输出的JSON中就必须是tool_input: {task_description: ...}。可以在工具类中定义一个expected_args属性并在智能体提示词中明确说明。9.3 代码生成质量不佳生成的代码有语法错误或逻辑错误原因模型能力有限或提示词未强调代码正确性。解决迭代提示词在CodeGenerationTool的system_prompt中加入更具体的要求如“请确保生成的代码可以直接被Python解释器执行没有语法错误”、“请为函数添加类型注解Type Hints以提高可读性”。后置代码检查在工具返回结果前使用Python的ast模块解析代码检查基本语法。或者集成一个简单的linter如flake8进行静态检查。自我修正Self-Correction这是一个高级技巧。当代码执行出错时可以将错误信息连同原始代码和问题描述再次喂给模型要求它修复错误。这需要将CodeExecutionTool和CodeGenerationTool组合成一个更复杂的“调试工具”。9.4 项目结构与代码组织建议随着工具和功能增多项目结构会变得混乱。我建议采用以下模块化结构claude-code-core/ ├── model_client.py # 模型客户端封装 ├── agent/ │ ├── __init__.py │ └── code_agent.py # 智能体核心 ├── tools/ │ ├── __init__.py │ ├── base_tool.py # 工具基类 │ ├── code_generation_tool.py │ └── code_execution_tool.py ├── utils/ # 辅助函数 │ └── prompt_templates.py # 存放各种提示词模板 ├── config.py # 配置文件模型路径、参数等 ├── main.py # 主程序入口 └── requirements.txt # 依赖列表使用config.py集中管理所有路径和参数方便调整。将提示词模板抽离到单独的文件便于管理和优化。经过以上所有步骤你已经拥有了一个功能完整、可扩展的“Claude Code”核心引擎。它从零开始涵盖了本地模型加载、智能体决策、工具调用、代码生成与执行等关键环节。虽然它比不上拥有万亿参数和庞大工程体系的商业产品但这个过程让你深入理解了AI编程助手的内核。你可以在此基础上继续扩展更多工具如代码解释、单元测试生成、代码重构优化提示词工程甚至尝试用更强大的模型作为核心打造一个真正属于你个人的、高度定制化的AI编程伙伴。