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

日记详情

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

驾驭工程:AI编程从玩具到工程的约束、上下文与验证实践

驾驭工程:AI编程从玩具到工程的约束、上下文与验证实践

1. 从“玩具”到“工程”:为什么我们需要Harness Engineering?

如果你在过去一年里尝试过用ChatGPT、Claude或者GitHub Copilot来写代码,大概率经历过这样的场景:你向AI描述了一个需求,它“唰”地一下生成了一段看起来非常漂亮的代码。你兴冲冲地复制粘贴,点击运行,然后……要么是编译报错,要么是逻辑跑飞,要么是性能拉胯。你不得不像一个耐心的老师,一遍遍地指出错误,引导它修正。这个过程,与其说是“编程”,不如说是在“调试AI”。问题出在哪?核心在于,我们和AI的交互方式,还停留在一种原始的、非结构化的“自然语言对话”模式。这种模式充满了不确定性,就像你让一个刚入行的实习生去完成一个复杂的系统设计,只给了一句口头描述,不出问题才怪。

这就是“Harness Engineering”(约束工程,或更贴切地称为“驾驭工程”)要解决的问题。它不是一个具体的工具,而是一套工程化的思想和方法论,旨在将AI编程从一种“艺术”或“运气”,转变为一种可预测、可重复、可协作的“工程”。简单来说,它的核心目标是为AI编程套上“缰绳”(Harness),通过一系列结构化的约束、规范和流程,引导AI生成符合我们工程化要求的代码,而不是一堆需要反复调试的“草稿”。

为什么这变得如此重要?因为AI编程的“铁三角”——AI模型、开发者和工程环境——正在发生深刻变化。模型的智能在飞速提升,但它的输出是概率性的、非确定性的。开发者希望提高效率,但不想被低质量的代码拖累。工程环境要求代码必须具备可维护性、安全性、性能和一致性。Harness Engineering就是连接这三者的桥梁和粘合剂。它通过定义清晰的“游戏规则”,让AI在划定的边界内发挥创造力,从而让“AI辅助编程”真正落地为“AI工程化编程”。这不仅仅是写代码更快了,更是让代码的质量从一开始就站在了更高的起点上。

2. 拆解Harness:约束、上下文与验证的三位一体

Harness Engineering不是一个单一的技术点,而是一个由多个层面构成的体系。我们可以把它拆解为三个核心组成部分:约束定义、上下文管理和输出验证。这三者共同构成了驾驭AI编程的“铁三角”。

2.1 约束定义:给AI划定的“跑道”

约束是Harness Engineering最直观的部分。它告诉AI“什么不能做”和“最好怎么做”。这远不止是编程语言语法那么简单。我们可以把约束分为多个层级:

1. 语法与风格约束:这是最基础的层面,确保生成的代码至少能通过编译器和解释器。但工程化要求远不止于此。它还包括:

  • 代码风格:例如,强制使用特定的命名规范(camelCase, snake_case)、缩进(2空格还是4空格)、引号类型(单引号 vs 双引号)。
  • 导入/依赖管理:限制只能使用项目package.jsonrequirements.txt中声明的特定版本库,禁止引入未经审核的第三方依赖。
  • 语言特性限制:例如,在Python项目中禁止使用eval(),在JavaScript项目中推荐使用===而非==

为什么需要这些?因为AI模型是在海量、风格各异的代码上训练的。如果不加约束,它可能为同一个项目生成风格迥异的代码片段,给后续的代码审查和合并带来灾难。明确的约束让团队输出保持统一。

2. 架构与设计模式约束:这是中级约束,引导AI生成符合项目整体设计的代码。

  • 设计模式:要求生成的代码遵循特定的模式,如工厂模式、观察者模式、Repository模式等。你可以告诉AI:“为这个用户服务类生成代码,请使用依赖注入(Dependency Injection)的方式。”
  • 分层架构:强制代码遵守MVC、MVVM、Clean Architecture等分层原则。例如,约束AI不能在Controller层直接编写数据库查询逻辑,必须通过Service层。
  • 模块边界:定义清晰的模块接口和访问权限,防止AI生成违反模块化设计的代码。

3. 业务与安全约束:这是最高级的约束,直接关乎软件的功能正确性和安全性。

  • 业务规则:将业务逻辑以规则的形式注入。例如,“所有金额计算必须使用Decimal类型,禁止使用Float”,“用户状态从‘激活’到‘禁用’的转换,必须记录审计日志”。
  • 安全规约:硬性规定,如“所有用户输入在拼接SQL前必须参数化”,“向客户端返回的数据对象必须经过脱敏处理(如手机号中间四位替换为*)”。
  • 合规性要求:在金融、医疗等领域,代码可能需要满足特定的合规性条款,这些也可以作为约束条件。

实操心得:约束不是越多越好。一开始,可以从最影响团队协作和代码质量的“语法与风格约束”入手,利用现有的工具链(如ESLint、Pylint、Checkstyle)的配置文件,直接作为约束的一部分喂给AI。高级的业务和安全约束,则需要与领域专家(Domain Expert)合作,将其从文档中提炼成机器可读、可执行的规则。一个常见的坑是,约束之间可能存在冲突,需要设定优先级。例如,“性能优化”的约束(如使用循环展开)可能与“代码可读性”约束冲突,需要明确哪个优先级更高。

2.2 上下文管理:给AI配备的“项目地图”

如果说约束是交规,那么上下文就是高精地图。AI模型有“上下文窗口”的限制,它无法一次性“看到”你的整个项目。如何让它在有限的注意力范围内,获取到最相关、最关键的信息,就是上下文管理的核心。

1. 精准的上下文选取:不是把整个代码库都塞给AI。有效的方式包括:

  • 相关文件:自动识别并包含当前编辑文件所导入(import)或引用(reference)的其他关键文件。
  • 目录结构:提供项目的src/,tests/,config/等关键目录的树状结构,让AI理解项目布局。
  • API文档与类型定义:将重要的接口(Interface)、类型(Type)、协议(Protocol)定义作为上下文。对于TypeScript项目,.d.ts文件是关键;对于Go项目,接口定义是关键。
  • 最近的变更:提供最近几次相关的commit diff,让AI理解代码的演进脉络和当前的工作焦点。

2. 上下文的组织与优先级:信息不是堆砌,而是要有组织。通常的策略是:

  • 最近优先:将最近修改过的、或与光标位置最相关的代码片段放在上下文的前部。
  • 摘要化:对于冗长的文件,可以提供由另一个轻量级AI生成的摘要(如“这个文件主要导出了一个用于处理用户认证的类,包含login、logout、validateToken三个公共方法”),而不是全文。
  • 元数据:包含项目的技术栈(package.json,go.mod)、配置文件(docker-compose.yml,.env.example)等,这些是理解项目环境的基石。

为什么这很重要?我曾在一个项目中,让AI基于一个旧的、已被重构的接口去生成代码,结果生成的代码完全无法集成。根本原因就是提供的上下文过时了。良好的上下文管理,能极大减少AI的“幻觉”(即生成看似合理但基于错误前提的代码)。

实操技巧:许多先进的AI编程助手(如Cursor、Claude Code)已经开始集成“语义搜索”功能。它们能理解你的查询意图,自动从代码库中检索相关片段作为上下文。作为开发者,我们可以通过编写清晰的代码注释、维护良好的文档字符串(docstring)和类型定义,来主动“喂养”和优化这个检索过程。把你的代码写得更“AI-Friendly”,本身就是Harness Engineering的一部分。

2.3 输出验证:给AI代码上的“质量检测线”

生成了代码,事情只完成了一半。Harness Engineering要求我们必须有自动化的手段来验证AI的输出是否符合预期。这不仅仅是运行一下看有没有报错。

1. 静态验证:在代码运行之前就进行检查。

  • 类型检查:对于TypeScript、Python(with mypy)、Go等语言,运行类型检查器是第一步。AI生成的代码必须通过严格的类型校验。
  • 代码风格检查:用Linter(ESLint, Pylint)跑一遍,确保符合约束中定义的风格规则。
  • 静态安全扫描:使用SonarQube、Semgrep等工具进行基础的漏洞模式匹配。

2. 动态验证:让代码真正跑起来,但是在一个受控的环境中。

  • 单元测试生成与运行:高级的Harness流程可以要求AI在生成代码的同时,也生成对应的单元测试用例。然后自动运行这些测试,确保核心逻辑正确。
  • 集成测试:对于涉及多个模块的代码,可以将其放入一个轻量级的集成测试环境中运行,检查模块间的交互是否正确。
  • 性能基准测试:对于关键路径的代码,可以运行简单的基准测试,确保没有引入严重的性能回退(例如,一个O(n²)的算法被无意中生成)。

3. 人工验证的协同:自动化不能解决所有问题,最终需要人来做判断。

  • 差异高亮:代码审查工具(如GitHub Pull Request)应能清晰展示AI生成代码与原有代码的差异,并自动关联相关的约束规则。
  • 解释生成:要求AI为它生成的复杂代码段提供简短的自然语言解释,比如“这段代码使用了双指针法来避免数组的重复遍历”,这能极大提升审查效率。
  • 置信度提示:AI可以对其生成的内容提供一个置信度评分,对于低置信度的部分,工具应重点标出,提示开发者仔细审查。

踩坑实录:我曾经依赖AI生成了一组数据库查询的优化代码,静态检查全过,单元测试也通过了。但上线后,在某个特定并发场景下出现了死锁。原因是AI生成的代码虽然语法正确,但未能理解底层数据库事务隔离级别的细微差别。这个教训告诉我,动态验证的环境必须尽可能贴近生产环境,并且对于数据库、网络调用等I/O操作,必须要有集成测试甚至压力测试。Harness中的验证环节,其严格程度应该与代码变更的风险等级成正比。

3. 实战构建:从零搭建一个简单的Harness工作流

理论说了这么多,我们来点实际的。假设我们是一个使用TypeScript开发Node.js后端服务的小团队,现在希望为我们的AI编程助手(比如Cursor或Claude in IDE)建立一个初步的Harness工作流。我们不追求大而全,而是解决最痛的点:代码风格一致性和类型安全。

3.1 第一步:定义并固化你的约束规则

我们的约束主要依靠现有的工具链来实现。

1. 创建或完善你的eslint配置 (.eslintrc.js):这不是普通的ESLint配置,而是你的“核心约束法典”。你需要和团队一起,制定并明确写入规则。

// .eslintrc.js module.exports = { parser: '@typescript-eslint/parser', plugins: ['@typescript-eslint'], extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', // 引入严格的代码风格规则,这是关键! 'plugin:@typescript-eslint/recommended-requiring-type-checking', ], parserOptions: { project: './tsconfig.json', }, rules: { // 1. 风格类硬约束 'indent': ['error', 2], // 强制2空格缩进 'quotes': ['error', 'single'], // 强制单引号 'semi': ['error', 'always'], // 强制分号 '@typescript-eslint/explicit-function-return-type': 'error', // 强制函数写明返回类型 '@typescript-eslint/no-explicit-any': 'error', // 禁止使用any类型,这是TypeScript项目的生命线! // 2. 安全/最佳实践类约束 'no-eval': 'error', 'no-console': 'warn', // 警告生产代码中的console.log // 3. 项目特定约束(举例) // 强制使用我们自定义的日志库,而不是console 'no-restricted-imports': ['error', { 'patterns': ['console'] }], // 强制异步错误处理使用try-catch,禁止忽略.catch '@typescript-eslint/no-floating-promises': 'error', }, };

2. 创建或完善你的tsconfig.json:TypeScript的编译配置本身就是最强的约束之一。

{ "compilerOptions": { "target": "ES2022", "module": "commonjs", "strict": true, // 启用所有严格类型检查选项 "noImplicitAny": true, // 禁止隐式的any类型 "strictNullChecks": true, // 严格的null检查 "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "outDir": "./dist" }, "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.test.ts"] }

3. 创建项目级的“提示词”文件 (.aicontextPROMPT.md):这是一个纯文本文件,放在项目根目录,用来给AI提供固定的、高优先级的上下文和指令。你可以把它理解为给AI的“入职培训手册”。

# 项目开发守则 (AI请严格遵守) ## 技术栈与版本 - 语言: TypeScript (严格模式) - 运行时: Node.js 18+ - 框架: Express.js - 数据库: PostgreSQL, 使用Prisma ORM ## 核心约束(必须遵守) 1. **绝对禁止使用 `any` 类型**。如果遇到类型难以定义的情况,请使用 `unknown` 或泛型,并在代码旁添加 `// TODO: 优化此类型` 注释。 2. **所有异步操作必须显式处理错误**。使用 `try-catch` 或 `.catch()`,禁止静默忽略Promise。 3. **数据库操作必须通过Prisma Client**。禁止手动拼接SQL字符串。 4. **API响应格式必须统一**。成功响应使用 `{ success: true, data: ... }`,错误响应使用 `{ success: false, error: { code: string, message: string } }`。 ## 代码风格 - 缩进:2个空格。 - 字符串:使用单引号。 - 分号:必须。 - 导出的函数、类必须有JSDoc注释。 ## 文件与目录结构 - `src/controllers/`: 处理HTTP请求,只做参数校验和响应格式化。 - `src/services/`: 核心业务逻辑。 - `src/repositories/`: 数据访问层,使用Prisma。 - `src/utils/`: 纯函数工具。 - `src/types/`: 全局类型定义。 ## 示例(请参考以下风格) ```typescript // src/services/userService.ts import { PrismaClient } from '@prisma/client'; import { CreateUserDto } from '../types/user'; const prisma = new PrismaClient(); /** * 创建新用户 * @param userData 用户创建数据 * @returns 新创建的用户对象(不包含密码) */ export async function createUser(userData: CreateUserDto): Promise<User> { try { // 业务逻辑:检查邮箱是否已存在 const existingUser = await prisma.user.findUnique({ where: { email: userData.email }, }); if (existingUser) { throw new Error('USER_EMAIL_EXISTS'); // 抛出特定错误码 } // 创建用户 const newUser = await prisma.user.create({ data: userData, select: { id: true, email: true, name: true, createdAt: true }, // 明确选择返回字段,排除密码 }); return newUser; } catch (error) { // 记录日志,这里简化处理 console.error(`创建用户失败: ${error.message}`); // 重新抛出,由上层Controller处理 throw error; } }
### 3.2 第二步:配置你的IDE与AI助手 以VS Code + Cursor为例: 1. **安装必要插件**:确保ESLint和Prettier插件已安装并启用。Prettier的格式化规则最好与ESLint保持一致(可使用`eslint-config-prettier`)。 2. **配置Cursor的“项目上下文”**:在Cursor中,你可以将上面创建的`.aicontext`或`PROMPT.md`文件,以及`tsconfig.json`、`package.json`等文件标记为“项目上下文”。这样,每次你向Cursor提问或要求生成代码时,它会优先参考这些文件中的信息。 3. **启用“Lint on Save”**:在VS Code设置中,开启保存时自动运行ESLint检查。这样,AI生成的代码一旦保存,任何违反约束的地方都会立刻以错误或警告的形式标红,给你即时反馈。 ### 3.3 第三步:设计并执行验证流水线 我们不能依赖人工每次保存都去检查。需要将验证自动化。 1. **本地Git钩子(Pre-commit Hook)**: 使用`husky`和`lint-staged`,在代码提交前自动执行验证。 ```bash # 安装 npm install --save-dev husky lint-staged # 初始化husky npx husky init ``` 在`package.json`中配置: ```json { "lint-staged": { "src/**/*.{ts,tsx}": [ "eslint --fix", // 自动修复部分风格问题 "tsc --noEmit" // 进行类型检查,不输出文件 ] } } ``` 然后,在`.husky/pre-commit`钩子文件中添加`npx lint-staged`。这样,任何试图提交的代码,包括AI生成的,都必须先通过ESLint和TypeScript编译器的检查。 2. **CI/CD流水线集成**: 在GitHub Actions或GitLab CI中,添加一个专门的“Code Quality” job。 ```yaml # .github/workflows/ci.yml 示例片段 jobs: lint-and-typecheck: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 - run: npm ci - run: npm run lint # 对应 package.json 中的 "lint": "eslint src/**/*.ts" - run: npm run type-check # 对应 "type-check": "tsc --noEmit" ``` 如果检查失败,流水线会中断,阻止有问题的代码合并到主分支。 **这个工作流的效果是**:当AI(或开发者)在项目中编写代码时,会持续受到约束(ESLint规则、TypeScript配置、项目提示词)的引导。写出的代码会立即被验证(保存时lint、提交前hook、合并前CI)。任何偏离“跑道”的行为都会被迅速发现并纠正。这就构成了一个最基本的Harness Engineering闭环。 ## 4. 进阶场景:当Harness遇到复杂工程问题 基础的风格和类型约束只是开始。随着项目复杂度的提升,Harness Engineering需要应对更棘手的挑战。 ### 4.1 场景一:管理AI生成的测试代码 让AI生成业务代码的同时也生成单元测试,听起来很美,但实践起来坑很多。 **问题**:AI生成的测试用例往往流于表面,只测试“快乐路径”,缺乏边界条件、异常场景和Mock复杂依赖的测试。更糟糕的是,测试代码本身也可能违反约束(比如包含`any`类型)。 **Harness策略**: 1. **为测试代码单独定义约束**:在`.eslintrc.js`中,通过`overrides`为`**/*.test.ts`或`**/*.spec.ts`文件配置稍宽松但核心规则不变的约束。例如,允许在测试中使用`any`来快速构造测试数据,但业务逻辑的断言必须严格。 2. **提供测试工具上下文**:在项目提示词中,明确写出团队使用的测试框架(Jest, Vitest)、Mock库(ts-mockito, jest-mock-extended)的示例用法。让AI“学会”你们团队的测试风格。 3. **验证测试的有效性**:不仅要求测试通过,还要评估测试覆盖率。可以在CI流水线中加入一个步骤,在AI生成代码并补充测试后,运行测试并检查覆盖率是否达到预设门槛(如80%)。这倒逼AI生成更有意义的测试,而不是敷衍了事。 4. **模式化测试生成**:对于常见的CRUD操作,可以编写一些测试模板或脚手架代码。当AI需要为新的`UserService`生成测试时,你可以提示它:“请参考`productService.test.ts`的模式,为`createUser`, `getUserById`, `updateUser`方法生成测试,特别注意对Prisma Mock的用法。” ### 4.2 场景二:数据库操作与事务一致性 这是AI编程的重灾区。AI很容易生成看似正确,但在并发下会导致数据不一致的代码。 **问题**:AI可能会生成先查询、再计算、最后更新的代码,这在没有事务包裹的情况下,在多线程/多进程环境下是危险的。 **Harness策略**: 1. **强约束数据库访问模式**:在项目提示词中,以最大字号强调:“**所有涉及多个数据表写操作,或先读后写的业务逻辑,必须包裹在Prisma事务`$transaction`中。**” 并给出正面和反面示例。 2. **上下文提供Schema**:将Prisma的`schema.prisma`文件作为关键上下文提供给AI。让AI清晰掌握数据模型、关联关系和约束(如`@unique`, `@default`)。 3. **生成事务模板**:对于复杂的业务逻辑,可以要求AI先生成一个事务代码的骨架,开发者再填充细节。例如: ```typescript // AI,请为“用户下单”这个操作生成一个Prisma事务骨架,涉及User, Order, Inventory表。 await prisma.$transaction(async (tx) => { // 1. 验证用户状态 (使用tx.user) // 2. 锁定并检查库存 (使用tx.inventory) // 3. 创建订单记录 (使用tx.order) // 4. 更新库存 (使用tx.inventory) // 任何一步失败,整个事务回滚 }); ``` 4. **集成测试验证**:为涉及事务的核心服务函数编写集成测试,该测试需要启动一个真实的测试数据库(如使用TestContainers或内存数据库),并在测试中模拟并发操作,验证事务是否能正确保证一致性。 ### 4.3 场景三:第三方API集成与错误处理 集成外部服务时,网络超时、鉴权失败、响应格式变化都是常态。AI生成的代码往往对错误处理考虑不周。 **Harness策略**: 1. **强制定义外部契约**:使用TypeScript的`interface`或`type`明确定义你期望的第三方API的请求体和响应体。即使对方没有提供,你自己也要定义一份。这既是约束,也是给AI的清晰上下文。 ```typescript // src/types/external/payment.ts export interface PaymentGatewayRequest { orderId: string; amount: number; currency: 'USD' | 'EUR'; } export interface PaymentGatewayResponse { transactionId: string; status: 'SUCCESS' | 'PENDING' | 'FAILED'; timestamp: string; } export interface PaymentGatewayError { code: string; message: string; details?: unknown; } ``` 2. **包装与重试策略**:在项目提示词中规定,所有对外部API的调用,必须通过一个统一的`HttpClient`或`ServiceClient`类进行,该类内置了超时设置、重试逻辑(针对5xx错误)和断路器模式。禁止在业务代码中直接使用`fetch`或`axios`。 3. **错误处理模板**:提供标准的错误处理模式。 ```typescript // 在提示词中提供示例 try { const response = await externalServiceClient.post<PaymentGatewayResponse>('/pay', requestData); return response.data; } catch (error) { if (error instanceof ExternalServiceTimeoutError) { // 触发告警,记录日志,可能触发补偿事务 throw new ApplicationError('PAYMENT_GATEWAY_TIMEOUT', '支付网关响应超时'); } if (error instanceof ExternalServiceAuthError) { // 刷新令牌,或触发严重告警 throw new ApplicationError('PAYMENT_GATEWAY_AUTH_FAILED', '支付网关认证失败'); } // 其他未知错误 throw new ApplicationError('EXTERNAL_SERVICE_ERROR', `支付网关未知错误: ${error.message}`); } ``` 4. **生成Mock与测试**:要求AI在生成调用第三方API的代码时,同时生成用于单元测试的Mock对象,模拟成功、失败、超时等各种情况,确保错误处理路径被覆盖到。 ## 5. 工具链展望与团队文化适配 Harness Engineering的实践离不开工具的支持,也离不开团队文化的转变。 **现有工具生态**: * **AI编程助手**:Cursor, GitHub Copilot, Claude Code, Codeium等,是直接的“执行者”。它们的“自定义指令”、“项目上下文”功能是实施Harness的入口。 * **代码分析工具**:ESLint, Pylint, Checkstyle, SonarQube等,是“约束检查器”。它们的规则文件就是约束的载体。 * **测试框架**:Jest, Pytest, Mocha等,是“验证器”。自动化测试是验证AI输出正确性的关键。 * **CI/CD平台**:GitHub Actions, GitLab CI, Jenkins等,是“自动化流水线”。它将约束检查、测试验证等步骤串联起来,形成强制性的质量门禁。 * **新兴专用工具**:一些专门为“AI代码管理”设计的工具正在出现,它们可能提供更细粒度的约束定义、更智能的上下文检索和更强大的验证流程。 **团队文化转型**: Harness Engineering最大的挑战往往不是技术,而是人。它要求团队: 1. **从“个人技艺”到“集体规约”**:接受代码风格、设计模式不是个人喜好,而是需要共同遵守、并写入工具的团队契约。 2. **重视“非功能需求”的早期注入**:性能、安全、可维护性不再是事后考虑的事情,而是一开始就作为约束条件提给AI。 3. **重新定义“开发效率”**:效率不再是“生成代码行的速度”,而是“生成**符合生产要求**的代码的速度”。接受在提示词工程、约束定义上花费时间,是为了在调试、重构、故障排查上节省十倍百倍的时间。 4. **代码审查的焦点转移**:审查者不再纠结于缩进和分号(这些已由工具保证),而是更专注于AI生成的代码是否真正理解了业务意图,算法是否最优,是否有潜在的边缘情况未处理。 我个人在团队中推行Harness Engineering的体会是,起步阶段阻力最大。开发者会觉得“束手束脚”,怀念那种“自由发挥”的感觉。但一旦大家尝到了甜头——比如新同事生成的代码几乎无需修改就能通过审查,或者再也没出现过因低级风格问题导致的合并冲突——整个团队就会形成正向循环。我们会一起打磨约束规则,讨论如何编写更有效的上下文提示,就像以前一起制定编码规范一样自然。 最终,Harness Engineering的目标不是用机器取代开发者,而是让开发者和AI形成一种“人机协同”的最佳状态:开发者专注于高层次的架构设计、业务逻辑拆解和约束规则制定;AI则像一个严格遵循SOP(标准作业程序)的超级实习生,高效、可靠地完成具体的编码实现。当我们把这套“缰绳”驾驭得越来越熟练时,我们才真正进入了AI编程的工程化时代。
← 返回列表