📃作者主页:编程的一拳超人
⛺️ 欢迎关注:👍点赞 👂🏽留言 🌟收藏 💞 💞 💞
于高山之巅,方见大河奔涌;于群峰之上,更觉长风浩荡。
📌专栏系列:C++ AI Agent 实战 / 大模型工具调用 / 智能编程助手
⭐如果本文对你有帮助,欢迎点赞、收藏、关注三连支持!
💬问题交流:评论区留言或私信,看到必回
- C++ 手写 AI 编程 Agent(10):主程序整合与端到端实战演示
- 7. 主程序与交互界面
- 7.1 完整的 main.cpp
- 8. 完整操作流程演示
- 8.1 端到端示例:创建一个完整的 C++ 计算器项目
- 8.2 编译失败自修复的完整过程
- 8.3 代码重构任务示例
- 8.4 Bug 定位与修复示例
- 📚 系列目录
C++ 手写 AI 编程 Agent(10):主程序整合与端到端实战演示
适用标准:C++17 |难度:中级 |阅读时间:约 15 分钟
本文是「C++ 手写 AI 编程 Agent」12篇系列的第10篇,把所有模块组装起来跑通完整流程。
7. 主程序与交互界面
7.1 完整的 main.cpp
// src/main.cpp#include"agent.h"#include"file_tools.h"#include"compile_tool.h"#include"shell_tool.h"#include<fmt/core.h>#include<iostream>#include<fstream>#include<sstream>#include<cstdlib>/// 从文件加载 system promptstd::stringload_system_prompt(conststd::string&path){std::ifstreamfile(path);if(!file.is_open()){fmt::print(stderr,"Warning: Cannot load system prompt from {}\n",path);return"You are a helpful C++ coding assistant.";}std::stringstream ss;ss<<file.rdbuf();returnss.str();}/// 注册所有内置工具voidregister_all_tools(Agent&agent){// 文件操作工具agent.register_tool(make_read_file_tool());agent.register_tool(make_write_file_tool());agent.register_tool(make_edit_file_tool());agent.register_tool(make_list_directory_tool());agent.register_tool(make_search_in_files_tool());// 编译工具agent.register_tool(make_compile_tool());// Shell 工具agent.register_tool(make_shell_tool());fmt::print("\n✓ All tools registered.\n\n");}voidprint_banner(){fmt::print(R"( ╔══════════════════════════════════════════╗ ║ C++ AI Agent v1.0 ║ ║ Read · Write · Compile · Self-Fix ║ ╚══════════════════════════════════════════╝ Commands: /reset - Reset conversation /stats - Show statistics /quit - Exit )");}intmain(){// 从环境变量获取 API Keyconstchar*api_key_env=std::getenv("OPENAI_API_KEY");if(!api_key_env){fmt::print(stderr,"Error: OPENAI_API_KEY environment variable not set.\n""Please set it: export OPENAI_API_KEY=sk-...\n");return1;}// 配置 AgentAgentConfig config;config.api_key=api_key_env;config.base_url=std::getenv("OPENAI_BASE_URL")?std::getenv("OPENAI_BASE_URL"):"https://api.openai.com/v1";config.model=std::getenv("AGENT_MODEL")?std::getenv("AGENT_MODEL"):"gpt-4o";config.system_prompt=load_system_prompt("system_prompt.txt");config.max_iterations=20;config.verbose=true;// 创建 Agent 并注册工具Agentagent(config);register_all_tools(agent);// 设置回调(可选:自定义输出格式)AgentCallbacks callbacks;callbacks.on_think=[](intiter,conststd::string&thought){fmt::print("\n💭 [Think #{}] {}\n",iter,thought);};callbacks.on_tool_call=[](conststd::string&tool,constjson&args){fmt::print("🔧 [Call] {}({})\n",tool,args.dump());};callbacks.on_tool_result=[](conststd::string&tool,constToolResult&r){fmt::print("{} [Result] {}: {}\n",r.success?"✅":"❌",tool,r.output.substr(0,200));};callbacks.on_complete=[](conststd::string&answer){fmt::print("\n{'='*60}\n");fmt::print("🎯 FINAL ANSWER:\n{}\n",answer);fmt::print("{'='*60}\n");};agent.set_callbacks(std::move(callbacks));print_banner();// REPL 主循环std::string input;while(true){fmt::print("\n👤 You: ");if(!std::getline(std::cin,input))break;// 去除首尾空白autotrim=[](std::string&s){s.erase(0,s.find_first_not_of(" \t\r\n"));s.erase(s.find_last_not_of(" \t\r\n")+1);};trim(input);if(input.empty())continue;// 特殊命令处理if(input=="/quit"||input=="/exit"){fmt::print("Goodbye!\n");break;}if(input=="/reset"){agent.reset();fmt::print("Conversation reset.\n");continue;}if(input=="/stats"){autostats=agent.get_stats();fmt::print("Iterations: {}, Tool calls: {}, Tokens: {}\n",stats.total_iterations,stats.total_tool_calls,stats.total_tokens);continue;}// 运行 Agenttry{std::string response=agent.run(input);// 最终回复已通过回调输出}catch(conststd::exception&e){fmt::print(stderr,"\n❌ Error: {}\n",e.what());}}return0;}8. 完整操作流程演示
8.1 端到端示例:创建一个完整的 C++ 计算器项目
用户输入:
Create a simple calculator library with add, subtract, multiply, divide functions. Include a main.cpp that demonstrates usage. Set up CMakeLists.txt. Then compile and verify everything works.Agent 思考过程逐步展示:
============================================================ Iteration 1/20 ============================================================ 💭 [Think #1] I need to create three files: the header, implementation, main.cpp, and CMakeLists.txt. Let me start by creating the project structure. 🔧 [Call] write_file({"path": "include/calculator.h", "content": "#pragma once\n..."}) ✅ [Result] write_file: Successfully wrote 245 bytes to include/calculator.h 🔧 [Call] write_file({"path": "src/calculator.cpp", "content": "#include ..."}) ✅ [Result] write_file: Successfully wrote 389 bytes to src/calculator.cpp 🔧 [Call] write_file({"path": "src/main.cpp", "content": "#include ..."}) ✅ [Result] write_file: Successfully wrote 512 bytes to src/main.cpp 🔧 [Call] write_file({"path": "CMakeLists.txt", "content": "cmake_minimum..."}) ✅ [Result] write_file: Successfully wrote 328 bytes to CMakeLists.txt ============================================================ Iteration 2/20 ============================================================ 💭 [Think #2] All files created. Now I need to compile to verify correctness. 🔧 [Call] compile({"build_dir": "./build"}) ❌ [Result] compile: Build FAILED (exit code 1). src/calculator.cpp:3:10: fatal error: 'calculator.h' file not found #include "calculator.h" ============================================================ Iteration 3/20 ============================================================ 💭 [Think #3] The include path is wrong. I need to fix the include directive to use the correct relative path since headers are in include/. 🔧 [Call] edit_file({"path": "src/calculator.cpp", "old_string": "#include \"calculator.h\"", "new_string": "#include \"../include/calculator.h\""}) ✅ [Result] edit_file: Replaced 1 occurrence(s) in src/calculator.cpp ============================================================ Iteration 4/20 ============================================================ 💭 [Think #4] Fixed the include path. Let me also update CMakeLists.txt to properly set include directories, then recompile. 🔧 [Call] edit_file({"path": "CMakeLists.txt", "old_string": "add_executable(calc src/main.cpp src/calculator.cpp)", "new_string": "add_executable(calc src/main.cpp src/calculator.cpp)\ntarget_include_directories(calc PRIVATE include)"}) ✅ [Result] edit_file: Replaced 1 occurrence(s) in CMakeLists.txt 🔧 [Call] compile({"build_dir": "./build", "clean": true}) ✅ [Result] compile: Build succeeded. ============================================================ Iteration 5/20 ============================================================ 💭 [Think #5] Build succeeded! Let me run the program to verify output. 🔧 [Call] shell_exec({"command": "./build/calc"}) ✅ [Result] shell_exec: Calculator Demo 5 + 3 = 8 10 - 4 = 6 6 * 7 = 42 15 / 3 = 5 🎯 FINAL ANSWER: Successfully created a calculator project with the following files: - include/calculator.h: Header with function declarations - src/calculator.cpp: Implementation - src/main.cpp: Demo program - CMakeLists.txt: Build configuration Encountered one issue: include path was incorrect initially. Fixed by adding target_include_directories to CMakeLists.txt. Project compiles and runs correctly. ✅8.2 编译失败自修复的完整过程
这个例子展示了 Agent 最核心的价值——自动发现并修复编译错误:
- Agent 编写代码 → 编译失败
- Agent 阅读错误信息 → 分析原因
- Agent 编辑代码 → 重新编译
- 如果仍然失败 → 重复步骤 2-3
- 编译通过 → 报告完成
关键在于 system prompt 中的“VERIFY AFTER CHANGES”原则,以及 LLM 对编译器错误的理解能力。
8.3 代码重构任务示例
User: Refactor the calculator to use a class-based design with operator overloading. Agent 思考链: 1. read_file("include/calculator.h") → 了解当前接口 2. read_file("src/calculator.cpp") → 了解当前实现 3. read_file("src/main.cpp") → 了解使用方式 4. write_file("include/calculator.h") → 重写为类设计 5. write_file("src/calculator.cpp") → 重写实现 6. edit_file("src/main.cpp") → 更新使用方式 7. compile() → 验证编译 8. shell_exec("./build/calc") → 验证运行结果8.4 Bug 定位与修复示例
User: The divide function returns wrong results for negative numbers. Fix it. Agent 思考链: 1. read_file("src/calculator.cpp") → 查看 divide 实现 2. Thought: "I see the issue - integer division truncates toward zero, but the expected behavior might be floor division..." 3. read_file("src/main.cpp") → 查看测试用例 4. edit_file(...) → 修复逻辑 5. compile() → 验证 6. shell_exec("./build/calc") → 验证输出正确📚 系列目录
- 第1篇:AI Agent概念入门与ReAct架构设计
- 第2篇:环境搭建与CMake依赖管理
- 第3篇:工具注册表与文件操作工具集
- 第4篇:编译诊断工具与Shell执行引擎
- 第5篇:工具超时缓存与链式组合模式
- 第6篇:Agent核心循环消息管理与LLM调用
- 第7篇:Token窗口管理与错误恢复策略
- 第8篇:记忆系统规划引擎与多Agent协作
- 第9篇:Prompt工程从System Prompt到AB测试
- ✅第10篇:主程序整合与端到端实战演示(当前阅读)
- 第11篇:Reflexion与Tree-of-Thought等高级模式
- 第12篇:性能优化安全防护与FAQ总结
⬅️上一篇:第9篇:Prompt工程从System Prompt到AB测试
➡️下一篇:第11篇:Reflexion与Tree-of-Thought等高级模式