三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

基于LangChain与LLM的智能体工作流:从自然语言需求到代码自动生成

基于LangChain与LLM的智能体工作流:从自然语言需求到代码自动生成

最近在WAIC现场体验了一款新工具,它能把模糊的自然语言需求,直接变成可运行的应用。这背后其实是一套完整的“智能体(Agent)”工作流在支撑。对于开发者而言,理解这套从需求到代码的自动化链路,远比单纯使用某个工具更有价值。本文将深入拆解这类“需求驱动开发”新范式的核心原理,并手把手带你构建一个简化版的智能体系统,涵盖环境搭建、核心模块实现到工程化实践的全流程。

无论你是想了解AI编程前沿,还是希望将自动化开发能力集成到自己的项目中,这篇文章都能提供从概念到落地的完整参考。

1. 智能体工作流:从模糊需求到完整应用的核心架构

所谓“说出需求,自动干活”的新物种,其本质是一个由多个AI智能体协同工作的复杂系统。它并不是单一模型的神奇魔法,而是一个精心设计的工程化流水线。理解这个架构,是复现或应用此类技术的前提。

一个典型的智能体工作流通常包含以下几个核心环节:

  1. 需求分析与拆解智能体:接收用户模糊、不完整的自然语言描述,通过大语言模型(LLM)进行意图识别、歧义消除和场景补全。例如,用户说“做个管理会员的页面”,智能体会追问“需要哪些字段?(如姓名、电话、等级)”、“需要什么功能?(增删改查、搜索、导出)”等,将模糊需求转化为清晰、结构化的功能清单。
  2. 技术方案设计智能体:根据结构化的需求,选择合适的技术栈(如前端用Vue3+Element Plus,后端用Spring Boot),设计数据库表结构,规划API接口,并输出初步的项目目录结构。这一步相当于高级架构师。
  3. 代码生成智能体:这是最核心的编码环节。它根据技术方案,分别调用不同的子智能体或工具,生成前端组件、后端控制器、服务层、数据访问层以及SQL脚本等具体代码。每个子智能体专注于特定类型的代码生成。
  4. 代码验证与集成智能体:生成的代码可能存在语法错误、逻辑缺陷或接口不匹配。此智能体负责运行静态检查、执行单元测试(甚至能自动生成测试用例)、尝试构建项目,并将各个模块的代码进行集成,确保它们能协同工作。
  5. 部署与交付智能体:将验证通过的代码,自动部署到指定的环境(如本地服务器、Docker容器或云平台),并生成可供访问的链接或安装包。

整个流程形成了一个闭环,智能体之间通过共享“结构化需求文档”、“设计稿”、“代码库”等中间产物进行通信和迭代。接下来,我们将聚焦最核心的代码生成与验证部分,构建一个演示性的智能体系统。

2. 环境准备与核心技术选型

为了构建一个可运行的演示系统,我们需要选择合适的技术栈。本示例将采用Python,因为它拥有丰富的AI库和快速的开发迭代能力。我们将构建一个控制台应用,模拟接收一个简单的“创建用户管理CRUD API”需求,并自动生成对应的Spring Boot后端代码。

基础环境:

  • 操作系统:Windows 10/11, macOS 或 Linux (如Ubuntu 20.04+)。
  • Python版本:3.8 或更高版本 (推荐3.9+)。本文示例基于 Python 3.9。
  • 包管理工具pip

核心依赖库:我们将使用LangChain这个流行的框架来构建智能体链,并使用 OpenAI 的 GPT 模型作为“大脑”。当然,你也可以替换为其他兼容的模型API(如国内大模型平台提供的接口)。

# 创建项目目录并初始化虚拟环境(推荐) mkdir ai_agent_demo && cd ai_agent_demo python -m venv venv # 激活虚拟环境 # Windows: venv\Scripts\activate # macOS/Linux: source venv/bin/activate # 安装核心依赖 pip install langchain langchain-openai # 安装用于处理结构化输出的库 pip install langchain-experimental # 安装用于生成代码后格式化的库(可选但推荐) pip install black

项目结构预览:在开始编码前,我们先规划一下目录结构,这有助于理解后续的代码模块。

ai_agent_demo/ ├── requirements.txt # 项目依赖列表 ├── main.py # 主程序入口 ├── agents/ # 智能体模块目录 │ ├── __init__.py │ ├── requirement_analyzer.py # 需求分析智能体 │ ├── tech_designer.py # 技术设计智能体 │ └── code_generator.py # 代码生成智能体 ├── templates/ # 代码模板目录(可选) │ └── spring_boot_controller.java.tpl └── output/ # 生成的代码输出目录 ├── UserController.java ├── UserService.java └── ...

重要配置:API密钥使用OpenAI API需要配置密钥。请务必通过环境变量管理,不要硬编码在代码中。

# 在终端中设置环境变量(临时) # Windows: setx OPENAI_API_KEY "your-api-key-here" # macOS/Linux: export OPENAI_API_KEY="your-api-key-here"

或者在代码中通过os.environ设置(仅用于演示,生产环境应用更安全的方式):

# 在main.py开头添加 import os os.environ["OPENAI_API_KEY"] = "your-api-key-here"

3. 核心模块拆解与实现

我们的简化版智能体系统包含三个核心模块。我们将使用LangChainLCEL(LangChain Expression Language) 来以声明式的方式组合它们。

3.1 需求分析智能体:将模糊需求结构化

这个智能体的任务是理解用户的自然语言输入,并将其转换为机器可处理的、结构化的数据。我们将使用Pydantic来定义这个结构。

首先,定义结构化输出的数据模型:

# file: agents/requirement_analyzer.py from pydantic import BaseModel, Field from typing import List from langchain.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI # 定义需求分析的结果结构 class StructuredRequirement(BaseModel): """从模糊需求中提取的结构化信息""" core_function: str = Field(description="核心功能描述,如‘用户增删改查’") entities: List[str] = Field(description="涉及的主要实体对象,如[‘用户’, ‘订单’]") fields: dict = Field(description="每个实体包含的字段,格式如{‘用户’: [‘id’, ‘name’, ‘email’]}") operations: List[str] = Field(description="需要支持的操作,如[‘create’, ‘read’, ‘update’, ‘delete’, ‘list’]") # 构建提示词模板 requirement_analysis_prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个资深软件需求分析师。请将用户模糊、不完整的业务需求,转化为结构化的技术需求描述。"), ("human", "用户需求:{user_input}\n\n请严格按照给定的JSON格式输出。") ]) # 创建带有结构化输出的链 def create_requirement_analyzer(): llm = ChatOpenAI(model="gpt-4", temperature=0.1) # 使用低temperature保证输出稳定 # 使用with_structured_output绑定输出模型 structured_llm = llm.with_structured_output(StructuredRequirement) chain = requirement_analysis_prompt | structured_llm return chain # 使用示例 if __name__ == "__main__": analyzer = create_requirement_analyzer() user_input = "我想做一个管理公司员工信息的系统,要能记录姓名、工号、部门和入职时间,并且可以新增、查询和修改。" result = analyzer.invoke({"user_input": user_input}) print(f"核心功能: {result.core_function}") print(f"实体: {result.entities}") print(f"字段: {result.fields}") print(f"操作: {result.operations}")

运行上述代码,你会得到类似这样的结构化输出:

核心功能: 员工信息增删改查 实体: [‘员工’] 字段: {‘员工’: [‘姓名’, ‘工号’, ‘部门’, ‘入职时间’]} 操作: [‘create’, ‘read’, ‘update’]

这就把一句模糊的话,变成了程序可以明确理解的数据对象。

3.2 技术设计智能体:生成项目蓝图

拿到结构化的需求后,下一个智能体负责进行“技术设计”。它需要决定技术栈、数据库表结构、API路径等。这里我们以生成一个简单的Spring Boot项目设计为例。

# file: agents/tech_designer.py from pydantic import BaseModel, Field from typing import List from langchain.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI class TechnicalDesign(BaseModel): """技术设计方案""" tech_stack: dict = Field(description="技术栈,如{‘backend’: ‘Spring Boot 3.x’, ‘database’: ‘MySQL 8.0’}") entity_classes: List[str] = Field(description="需要生成的实体类名,如[‘User’]") api_endpoints: dict = Field(description="API端点设计,格式如{‘User’: {‘POST’: ‘/api/users’, ‘GET’: ‘/api/users/{id}’}}") database_schema: str = Field(description="简化的数据库建表SQL语句") tech_design_prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个Java后端架构师。根据结构化的业务需求,生成一份可直接指导开发的技术设计方案。请为Spring Boot项目设计。"), ("human", "业务需求:{structured_requirement}\n\n请输出技术设计方案。") ]) def create_tech_designer(): llm = ChatOpenAI(model="gpt-4", temperature=0.2) structured_llm = llm.with_structured_output(TechnicalDesign) chain = tech_design_prompt | structured_llm return chain if __name__ == "__main__": # 这里模拟接收上一个智能体的输出 from agents.requirement_analyzer import StructuredRequirement mock_requirement = StructuredRequirement( core_function="员工信息管理", entities=["员工"], fields={"员工": ["id", "name", "employee_id", "department", "hire_date"]}, operations=["create", "read", "update", "list"] ) designer = create_tech_designer() design = designer.invoke({"structured_requirement": mock_requirement.json()}) print(f"技术栈: {design.tech_stack}") print(f"实体类: {design.entity_classes}") print(f"API端点: {design.api_endpoints}") print(f"数据库Schema:\n{design.database_schema}")

这个智能体会输出一份详细的设计文档,包括建议的依赖、类名、API路径和SQL语句,为代码生成提供了精确的“图纸”。

3.3 代码生成智能体:根据图纸编写代码

这是最激动人心的部分。我们将创建一个智能体,它接收技术设计方案,并为每个指定的实体类生成对应的Java代码。为了提高生成代码的质量和一致性,我们可以使用更细致的提示词和少量示例(Few-Shot Learning)。

# file: agents/code_generator.py from langchain.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate from langchain_openai import ChatOpenAI import os # 定义代码生成的示例(Few-Shot Examples) examples = [ { "input": "生成一个Spring Boot的User实体类,包含字段:Long id, String username, String email。", "output": """ ```java package com.example.demo.entity; import jakarta.persistence.*; import lombok.Data; @Entity @Table(name = "users") @Data public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, unique = true) private String username; @Column(nullable = false) private String email; }
""" },

]

构建Few-Shot提示词模板

example_prompt = ChatPromptTemplate.from_messages([ ("human", "{input}"), ("ai", "{output}") ]) few_shot_prompt = FewShotChatMessagePromptTemplate( example_prompt=example_prompt, examples=examples, )

构建完整的代码生成提示词

code_gen_prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个经验丰富的Java开发专家。请根据给定的技术设计和实体描述,生成符合Spring Boot和JPA规范的、可直接运行的Java代码。代码要简洁、规范,包含必要的注解(如@Entity, @RestController)。只输出代码块,不要额外解释。"), few_shot_prompt, ("human", "技术设计概述:{tech_design_summary}\n\n请为实体类‘{entity_name}’生成代码,包含字段:{fields}。") ])

def create_code_generator(): llm = ChatOpenAI(model="gpt-4", temperature=0.1) # 低温度保证代码确定性 chain = code_gen_prompt | llm return chain

def generate_and_save_code(tech_design, output_dir="output"): """根据技术设计,为每个实体生成并保存代码文件""" generator = create_code_generator() os.makedirs(output_dir, exist_ok=True)

# 这里简化处理,假设tech_design是TechnicalDesign对象 # 实际应用中,需要解析这个对象 for entity in tech_design.entity_classes: # 构造请求(这里需要根据实际数据结构调整) fields_str = ", ".join(tech_design.fields.get(entity, [])) # 假设fields在tech_design中 prompt_input = { "tech_design_summary": f"技术栈:{tech_design.tech_stack}", "entity_name": entity, "fields": fields_str } code = generator.invoke(prompt_input).content # 清理代码块标记,保存文件 clean_code = code.strip().strip("```java").strip("```").strip() file_path = os.path.join(output_dir, f"{entity}.java") with open(file_path, 'w', encoding='utf-8') as f: f.write(clean_code) print(f"[+] 已生成文件:{file_path}")

ifname== "main": # 模拟技术设计输入 class MockTechDesign: entity_classes = ["Employee", "Department"] tech_stack = {"backend": "Spring Boot 3.x", "database": "H2"} fields = {"Employee": ["id:Long", "name:String", "employeeId:String"], "Department": ["id:Long", "name:String"]}

generate_and_save_code(MockTechDesign())
运行此代码,将在`output`目录下生成`Employee.java`和`Department.java`两个实体类文件,内容符合JPA规范。 ## 4. 构建完整智能体工作流与实战演示 现在,我们将三个智能体串联起来,形成一个完整的、端到端的流水线。我们创建一个主程序来协调整个流程。 ```python # file: main.py import asyncio import os from agents.requirement_analyzer import create_requirement_analyzer, StructuredRequirement from agents.tech_designer import create_tech_designer, TechnicalDesign from agents.code_generator import generate_and_save_code from langchain_core.runnables import RunnablePassthrough def main(): """主函数:串联智能体工作流""" print("=== AI智能体代码生成系统 ===") user_input = input("请输入您的业务需求(例如:做一个管理图书借阅的系统):\n> ") print("\n[阶段一] 需求分析中...") # 1. 需求分析 analyzer = create_requirement_analyzer() structured_req: StructuredRequirement = analyzer.invoke({"user_input": user_input}) print(f" 分析完成:核心功能 - {structured_req.core_function}") print("\n[阶段二] 技术设计中...") # 2. 技术设计 designer = create_tech_designer() # 将结构化需求转换为JSON字符串传递给设计器 tech_design: TechnicalDesign = designer.invoke({"structured_requirement": structured_req.json()}) print(f" 设计完成:技术栈 - {tech_design.tech_stack}") print("\n[阶段三] 代码生成中...") # 3. 代码生成与保存 # 注意:这里需要将TechnicalDesign对象适配到generate_and_save_code函数 # 我们创建一个适配的简单对象 class SimpleDesignForGen: def __init__(self, tech_design: TechnicalDesign, structured_req: StructuredRequirement): self.entity_classes = tech_design.entity_classes self.tech_stack = tech_design.tech_stack # 将需求中的字段映射到设计中的实体(这里做简单假设,第一个实体对应需求中的第一个实体) self.fields = {} if structured_req.entities and structured_req.fields: for i, entity in enumerate(tech_design.entity_classes): req_entity = structured_req.entities[i % len(structured_req.entities)] self.fields[entity] = structured_req.fields.get(req_entity, []) design_for_gen = SimpleDesignForGen(tech_design, structured_req) generate_and_save_code(design_for_gen, output_dir="./generated_code") print(f"\n✅ 流程结束!生成的代码已保存至 ./generated_code 目录。") print(f" 数据库Schema建议:\n{tech_design.database_schema}") if __name__ == "__main__": # 设置API密钥(生产环境请使用环境变量) os.environ["OPENAI_API_KEY"] = "your-api-key-here" main()

运行演示:

  1. 在项目根目录下执行python main.py
  2. 输入需求:“做一个简单的员工管理系统,需要记录员工姓名、工号、邮箱和所属部门,能进行增删改查。”
  3. 观察控制台输出,查看./generated_code目录下生成的Java实体类文件。

一个可能生成的Employee.java文件内容如下:

package com.example.demo.entity; import jakarta.persistence.*; import lombok.Data; import java.time.LocalDate; @Entity @Table(name = "employees") @Data public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String name; @Column(name = "employee_number", nullable = false, unique = true) private String employeeNumber; @Column(nullable = false) private String email; @Column(nullable = false) private String department; @Column(name = "hire_date") private LocalDate hireDate; }

5. 常见问题与排查思路

在构建和运行此类AI智能体系统时,你可能会遇到一些典型问题。

问题现象可能原因解决思路
调用API时超时或报错1. 网络连接不稳定。
2. API密钥无效或余额不足。
3. 请求速率超限。
1. 检查网络,尝试使用更稳定的环境。
2. 在OpenAI控制台验证API密钥状态和余额。
3. 降低请求频率,为代码添加重试机制和指数退避。
生成的代码结构混乱或不符合规范1. 提示词(Prompt)不够精确。
2. 大语言模型“温度”(temperature)参数过高,随机性太强。
3. 缺少Few-Shot示例引导。
1. 细化系统提示词,明确角色、框架、规范和输出格式。
2. 将temperature调低(如0.1),使输出更确定。
3. 在提示词中添加高质量、符合规范的代码示例。
智能体间数据传递格式错误上一个智能体的输出格式不符合下一个智能体的输入预期。1. 使用Pydantic等工具严格定义智能体间传递的数据结构(Schema)。
2. 在串联智能体时,添加数据格式转换和验证层。
生成代码存在语法或逻辑错误大语言模型并非编译器,可能产生看似合理但有细微错误的代码。1.必须引入验证环节:集成代码静态分析工具(如对于Java可以用Checkstyle、PMD)、尝试编译或解释执行。
2. 建立“测试生成智能体”,为关键代码自动生成单元测试并运行。
处理复杂需求时效果差单一提示词或链难以处理过于复杂、步骤繁多的任务。采用“规划-执行”模式。先让一个“规划智能体”将大任务分解为多个原子性子任务,再分发给不同的“执行智能体”处理,最后汇总结果。

6. 工程化最佳实践与扩展方向

将演示系统转化为可用于实际项目的生产级工具,需要考虑更多工程化因素。

1. 提示词工程与管理:

  • 模板化:将提示词存储在外部文件(如YAML、JSON)或数据库中,便于版本管理和A/B测试。
  • 变量注入:动态将用户输入、上下文信息、历史对话等注入提示词模板。
  • 评估与迭代:建立提示词效果评估体系,根据生成代码的质量(通过率、规范符合度)持续优化提示词。

2. 智能体的鲁棒性增强:

  • 异常处理与重试:为每个智能体调用包裹完善的异常处理逻辑,并设计合理的重试策略。
  • 验证与回退:在关键节点(如生成代码后)设置验证点。如果验证失败(如编译错误),应能触发回退机制,例如让另一个智能体修复代码,或提示用户澄清需求。
  • 流控与限速:管理对大语言模型API的调用频率,避免因超额请求导致失败或产生高额费用。

3. 生成代码的质量保障:

  • 集成代码格式化工具:生成代码后,自动调用black(Python)、prettier(JS)、google-java-format(Java)等工具进行格式化。
  • 静态分析与安全扫描:集成SonarQubeBandit(Python)、SpotBugs(Java)等工具,对生成的代码进行质量和安全漏洞扫描。
  • 容器化与沙箱运行:对于需要验证运行结果的场景,可以将生成代码放在Docker容器中执行,确保环境隔离与安全。

4. 扩展为多语言、全栈生成:

  • 前端智能体:基于技术设计,生成Vue/React组件、页面路由和状态管理代码。
  • 数据库智能体:生成更复杂的SQL迁移脚本、索引优化建议。
  • 部署配置智能体:生成Dockerfile、Kubernetes YAML、CI/CD流水线配置(如GitHub Actions)。

5. 构建交互式与持续学习系统:

  • 人机交互:当需求模糊或智能体不确定时,应能主动向用户提问,例如“您希望的搜索功能是精确匹配还是模糊查询?”。这可以通过LangChain的Tool概念来实现,让智能体拥有“提问”的能力。
  • 反馈循环:记录每次用户对生成结果的反馈(接受、修改、拒绝),并利用这些数据微调提示词或训练奖励模型,让系统越用越智能。

从“说出需求”到“自动生成代码”的智能体系统,代表了软件开发范式的一次重要演进。它并非要取代开发者,而是成为开发者的“超级副驾”,将开发者从重复性的基础编码中解放出来,更专注于架构设计、复杂逻辑和创造性工作。通过本文的拆解与实践,希望你不仅能够搭建一个演示系统,更能理解其背后的设计哲学与工程挑战,从而在自己的领域中探索AI赋能的无限可能。

← 返回列表