news 2026/5/7 17:11:34

飞书技能开发框架:构建企业级机器人应用的乐高式解决方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
飞书技能开发框架:构建企业级机器人应用的乐高式解决方案

1. 项目概述:一个为飞书平台注入“技能”的开发者工具箱

如果你是一名飞书生态的开发者,或者你所在的企业正在深度使用飞书,那么你很可能遇到过这样的场景:想快速在飞书里查个天气、做个翻译、或者把一段对话内容自动整理成会议纪要,却发现要么需要自己从头写一个机器人,要么得在各种零散的API文档里翻找半天。hashSTACS-Global/feishu-skills这个项目,就是为了解决这类痛点而生的。

简单来说,feishu-skills是一个开源的、面向飞书(Lark)开放平台的“技能”集合与开发框架。你可以把它理解为一个“乐高积木箱”,里面预先封装好了许多实用的功能模块(我们称之为“技能”),比如天气查询、代码执行、内容摘要、多语言翻译等等。作为开发者,你可以直接“拿来即用”,将这些技能快速集成到你自己的飞书机器人或应用里;你也可以基于它提供的框架,像搭积木一样,用极少的代码开发出属于自己的新技能。

这个项目的核心价值在于“提效”和“标准化”。它把那些在飞书生态中高频、通用的功能需求,抽象成一个个独立的、可复用的技能单元,并提供了统一的配置、部署和调用方式。这极大地降低了为飞书开发智能交互功能的技术门槛,让开发者能更专注于业务逻辑本身,而不是反复处理飞书的事件订阅、消息解析等底层细节。无论你是想快速给自己的团队打造一个便捷的工具机器人,还是想构建一个功能丰富的企业级助理应用,feishu-skills都能提供一个坚实的起点。

2. 核心架构与设计哲学:如何理解“技能”即服务

2.1 “技能”的抽象与定义

feishu-skills的设计中,“技能”是一个核心概念。它不是一个模糊的功能描述,而是一个具有清晰边界和统一接口的独立执行单元。每个技能通常对应一个明确的用户意图或任务,例如:

  • 查询类技能WeatherSkill(查询天气)、StockSkill(查询股价)。
  • 工具类技能CalculatorSkill(计算器)、TranslatorSkill(翻译)。
  • 内容处理类技能SummarySkill(文本摘要)、CodeRunnerSkill(运行代码片段)。

每个技能都遵循相同的设计模式:输入 -> 处理 -> 输出。框架负责统一接管来自飞书平台的复杂输入(如用户@机器人的消息、点击按钮的事件),将其解析并转换为技能能理解的标准化请求参数;技能内部则只需关注核心的业务逻辑处理;最后,框架再将技能的处理结果,适配成飞书平台支持的消息格式(如文本、卡片)返回给用户。

这种设计带来的最大好处是解耦可插拔。技能开发者不需要关心飞书API的更新,只需要按照框架契约实现处理逻辑;应用集成者则可以像在菜单上点菜一样,通过配置文件自由组合和启用所需的技能。

2.2 项目核心模块拆解

要深入使用或贡献代码,需要了解项目的几个关键模块:

  1. 技能仓库:这是项目的“弹药库”,所有官方维护和社区贡献的技能都存放在这里。每个技能都是一个独立的目录,包含核心逻辑代码、配置文件、说明文档和测试用例。这种组织方式便于技能的独立开发、测试和版本管理。

  2. 核心运行时框架:这是项目的“大脑和中枢神经系统”。它提供了一系列基础服务和抽象类,主要职责包括:

    • 事件路由:监听飞书平台发送的各类事件(消息、菜单点击等),并根据预定义的规则,将事件分发给对应的技能处理器。
    • 依赖注入与管理:统一管理技能运行所需的第三方服务依赖,如数据库连接、外部API密钥、缓存客户端等。通常采用配置文件或环境变量进行集中配置。
    • 生命周期管理:控制技能的加载、初始化、执行和销毁过程。
    • 统一异常处理与日志:捕获技能执行过程中的异常,并以友好的方式反馈给用户,同时记录详细的执行日志用于排查问题。
  3. 配置与部署层:这是项目的“操作手册”。它定义了如何将一个技能集合部署为一个可运行的飞书应用。核心是一个主配置文件(例如config.yamlapp.json),其中需要声明:

    • 应用凭证:飞书开发者后台获取的App IDApp Secret
    • 事件订阅:需要订阅哪些飞书事件(如im.message.receive_v1)。
    • 技能列表:启用哪些技能,以及每个技能的自定义触发关键词或权限配置。
    • 部署配置:服务器地址、端口、数据库连接等。

2.3 技术栈选型背后的考量

feishu-skills的技术栈选择反映了其追求高效、稳定和易维护的目标。

  • 主语言:从项目命名和常见实践推断,很可能采用Node.js (JavaScript/TypeScript)Python。选择 Node.js 是因为其异步非阻塞特性非常适合处理飞书大量的 Webhook 请求,生态繁荣且有官方 SDK;选择 Python 则因其在数据处理、AI 集成方面的库非常丰富,易于实现翻译、摘要等智能技能。具体需要查看项目代码确认。
  • Web框架:无论主语言是哪种,必然会使用一个轻量级 Web 框架(如 Express.js for Node, Flask/FastAPI for Python)来接收飞书平台的 HTTP Webhook 请求。
  • 飞书官方 SDK:必然会深度依赖飞书开放平台提供的官方 SDK,用于验证请求签名、封装消息发送接口等,确保与平台交互的安全性和便捷性。
  • 技能管理:可能会使用简单的文件系统扫描,或更高级的插件化架构(如require.contextimportlib)来动态加载技能模块。

注意:技术栈的选型直接决定了项目的学习成本和二次开发门槛。如果你是 Python 开发者,而项目是 Node.js 写的,你可能需要评估一下自己的投入成本。不过,框架的设计理念通常是相通的。

3. 从零开始:部署你的第一个技能集合

3.1 环境准备与飞书应用创建

假设我们准备在一个 Linux 服务器上部署一个包含“天气查询”和“翻译”技能的机器人。

第一步:基础环境搭建

# 假设项目使用 Node.js # 1. 安装 Node.js 环境 (版本需参考项目要求,如 >= 16) curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash - sudo apt-get install -y nodejs # 2. 克隆项目代码 git clone https://github.com/hashSTACS-Global/feishu-skills.git cd feishu-skills # 3. 安装项目依赖 npm install

第二步:在飞书开发者后台创建应用

  1. 登录 飞书开放平台 ,点击“创建企业自建应用”。
  2. 填写应用名称、描述,上传图标。
  3. 在“凭证与基础信息”页面,获取至关重要的App IDApp Secret,妥善保存。
  4. 在“事件订阅”页面,填写请求网址 URL。这里就是你后续部署服务器的公网地址,例如https://your-domain.com/feishu/webhook。飞书会向这个地址发送用户消息等事件。
  5. 在“事件订阅”中,添加你需要的事件权限,如im:message(接收用户单聊消息)、im:message.group_at_msg(接收群聊中@机器人的消息)。
  6. 在“权限管理”页面,为你的应用添加必要的权限,例如“获取与发送单聊、群组消息”、“获取用户邮箱、手机号”(如果技能需要)等。
  7. 发布版本并申请线上发布。如果是测试,可以先将应用添加到“测试企业与人员”中进行体验。

3.2 技能配置详解

项目根目录下通常会有一个核心配置文件,例如config/config.yaml

# config.yaml 示例 app: app_id: “cli_xxxxxx” # 替换为你的 App ID app_secret: “xxxxxx” # 替换为你的 App Secret encrypt_key: “” # 如果启用了加密,填写此处 verification_token: “xxxxxx” # 事件订阅的 Token server: port: 3000 host: “0.0.0.0” skills: # 启用天气技能 - name: “weather” enabled: true trigger_keywords: [“天气”, “weather”] # 当消息包含这些词时触发 config: api_key: ${WEATHER_API_KEY} # 建议从环境变量读取,避免泄露 default_city: “北京” # 启用翻译技能 - name: “translator” enabled: true trigger_keywords: [“翻译”, “translate”] config: provider: “youdao” # 或 “baidu”, “google” app_key: ${TRANSLATOR_APP_KEY} app_secret: ${TRANSLATOR_APP_SECRET} # 数据库配置(如果技能需要存储数据) database: url: ${DATABASE_URL}

关键配置解析:

  • trigger_keywords:这是技能触发的“开关”。你可以灵活设置。例如,设置为[“天气”],那么用户发送“北京天气怎么样?”就会触发;设置为[“/weather”],则更像一个命令。
  • 环境变量:强烈建议将app_secretapi_key等敏感信息通过环境变量(${VAR_NAME})注入,而不是硬编码在配置文件中。可以使用dotenv等库来管理。
  • 技能参数:每个技能可能有其独特的配置项,如天气技能需要的第三方天气 API 密钥,翻译技能需要的翻译服务商凭证。这些都需要提前申请。

3.3 部署与上线

部署的核心是让飞书能访问到你的服务。

方案一:使用云服务器(以 Ubuntu + PM2 为例)

# 1. 在服务器上克隆代码、安装依赖(同环境准备) # 2. 创建 .env 文件,填入所有环境变量 echo “APP_SECRET=your_secret” >> .env echo “WEATHER_API_KEY=your_key” >> .env # ... 其他变量 # 3. 使用 PM2 进程守护启动应用 npm install -g pm2 pm2 start ecosystem.config.js # 或直接 pm2 start app.js --name “feishu-bot” # 4. 配置 Nginx 反向代理(如果你的服务在 3000 端口) # 编辑 /etc/nginx/sites-available/your-domain # 添加 location /feishu/webhook 代理到 localhost:3000 sudo nginx -s reload # 5. 在飞书后台配置事件订阅 URL 为 https://your-domain.com/feishu/webhook

方案二:使用 Serverless 服务(如 Vercel, AWS Lambda)对于轻量级应用,Serverless 是更经济、免运维的选择。你需要将项目改造成符合云函数格式(通常是一个导出的 HTTP 处理函数),并配置 API 网关。飞书的 Webhook 直接指向该云函数 URL。这种方案需要仔细处理冷启动延迟和状态保持问题。

实操心得:在首次配置飞书事件订阅时,最常见的坑是“URL 验证失败”。飞书在保存订阅地址时,会立即发送一个带有特定挑战码(challenge)的 GET 请求。你的服务端必须在接口中正确解析并原样返回这个challenge值,否则无法验证通过。务必在你的 Webhook 处理函数中首先实现这个验证逻辑。

4. 核心技能开发实战:手把手创建一个“待办事项”技能

现在,让我们超越使用,深入到开发层面。假设我们要创建一个简单的TodoSkill,让用户可以对机器人说“添加待办:开会”,机器人会记录下来,并能在用户询问“我的待办”时列出清单。

4.1 技能脚手架与结构

feishu-skills项目中,创建一个新技能通常有固定的结构。我们可以在skills/目录下新建一个todo文件夹。

skills/todo/ ├── index.js (或 index.py) # 技能主入口文件,实现核心逻辑 ├── config.schema.json # (可选) 技能配置项的 JSON Schema 定义,用于验证配置 ├── package.json (或 requirements.txt) # (可选) 技能独有的依赖 ├── README.md # 技能使用说明 └── __tests__/ # (可选) 单元测试

4.2 技能逻辑实现

我们以 Node.js 为例,实现index.js

// skills/todo/index.js const { BaseSkill } = require(‘../../core/base-skill’); // 假设框架提供了基类 // 假设有一个简单的内存存储,生产环境应换成数据库 const todoStore = new Map(); // key: user_id, value: todo list array class TodoSkill extends BaseSkill { // 技能的唯一标识 static get name() { return ‘todo’; } // 技能描述 static get description() { return ‘一个简单的个人待办事项管理技能’; } // 技能触发关键词(也可在全局配置中覆盖) static get defaultKeywords() { return [‘待办’, ‘todo’]; } /** * 核心处理方法 * @param {Object} context - 框架传入的上下文,包含用户消息、用户ID、事件详情等 * @returns {Promise<Object>} - 返回给飞书的消息内容 */ async execute(context) { const { text, user_id } = context; // 用户发送的原始文本和用户ID const lowerText = text.toLowerCase(); // 1. 解析用户意图 if (lowerText.includes(‘添加’) || lowerText.includes(‘add’)) { const task = text.replace(/添加待办:|add todo:/i, ‘’).trim(); if (!task) { return { msg_type: ‘text’, content: { text: ‘请告诉我待办事项的内容,例如:添加待办:准备周报’ } }; } // 存储待办 if (!todoStore.has(user_id)) { todoStore.set(user_id, []); } todoStore.get(user_id).push({ task, id: Date.now(), done: false }); return { msg_type: ‘text’, content: { text: `已添加待办:“${task}”` } }; } else if (lowerText.includes(‘列表’) || lowerText.includes(‘list’)) { // 2. 列出待办 const list = todoStore.get(user_id) || []; if (list.length === 0) { return { msg_type: ‘text’, content: { text: ‘你还没有待办事项哦。’ } }; } const todoText = list.map((item, index) => `${index + 1}. ${item.task} ${item.done ? ‘✅’ : ‘⭕️’}`).join(‘\n’); return { msg_type: ‘text’, content: { text: `你的待办事项:\n${todoText}` } }; } else if (lowerText.includes(‘完成’)) { // 3. 标记完成(简单实现,按序号) const match = text.match(/完成(\d+)/); if (match) { const index = parseInt(match[1]) - 1; const list = todoStore.get(user_id) || []; if (list[index]) { list[index].done = true; return { msg_type: ‘text’, content: { text: `已完成待办:“${list[index].task}”` } }; } } return { msg_type: ‘text’, content: { text: ‘请指定正确的待办序号,例如:完成1’ } }; } // 4. 默认回复,引导用户 return { msg_type: ‘interactive’, // 使用飞书卡片消息,体验更好 card: { elements: [ { tag: ‘div’, text: { content: ‘**待办事项助手**\n你可以对我说:\n• 添加待办:XXX\n• 我的待办列表\n• 完成1 (标记第1项为完成)’, tag: ‘lark_md’ } } ] } }; } } module.exports = TodoSkill;

4.3 技能注册与测试

开发完成后,我们需要在全局配置中启用这个技能。

  1. 注册技能:在项目的主应用文件或配置加载器中,需要将TodoSkill类导入并注册到技能管理器。具体方式取决于框架设计,可能是在一个中央skills/index.js文件中导出,也可能通过文件扫描自动发现。
  2. 更新配置:在config.yamlskills部分添加todo技能的配置。
    skills: - name: “todo” enabled: true # trigger_keywords 可以不写,使用技能类中定义的 defaultKeywords
  3. 本地测试:启动本地服务,使用飞书开发者后台的“事件模拟”工具,或直接将测试应用拉入群聊,发送“添加待办:测试一下”来验证功能。
  4. 部署更新:将代码部署到服务器,重启应用进程。

注意事项:上面的示例使用了内存存储Map,这意味着一旦服务重启,所有数据都会丢失。这绝对不适用于生产环境!生产环境中,你必须集成一个持久化存储,如 PostgreSQL、MySQL 或 MongoDB。框架应该提供统一的数据库客户端或存储接口,你的技能只需调用接口即可,实现业务逻辑与数据存储的解耦。

5. 高级应用与企业级集成考量

当技能数量增多,或者需要服务企业内部成百上千的用户时,简单的单机部署就会遇到瓶颈。这时需要考虑更高级的架构模式。

5.1 技能的性能优化与扩展性

  • 无状态设计:确保技能本身是无状态的,所有状态(如用户会话、待办数据)都保存在外部存储(数据库、Redis)中。这样,技能实例可以水平扩展,部署在多个容器或服务器上,由负载均衡器分发请求。
  • 异步处理与队列:对于耗时的技能(如处理大型文档摘要、视频转码),不应在同步的 Webhook 请求中处理完毕。最佳实践是:立即返回一个“处理中”的提示,然后将任务推送到消息队列(如 RabbitMQ、Kafka),由后台工作进程异步处理,处理完成后再通过飞书的“消息推送”API 将结果发送给用户。这能有效避免飞书 Webhook 超时(通常为3-5秒)。
  • 技能的热加载与隔离:对于需要7x24小时运行的服务,希望新增或更新技能时能不重启主服务。这需要框架支持动态加载和卸载技能模块。同时,可以考虑使用沙箱机制(如 Node.js 的vm模块或 Docker 容器)来运行技能,防止某个技能的崩溃或内存泄漏影响整个应用。

5.2 与企业现有系统的集成

feishu-skills的真正威力在于充当“连接器”,将飞书与企业内部系统打通。

  • 连接内部 API:开发一个QueryInternalDataSkill,当用户询问“本季度销售数据”时,技能后端调用企业的 CRM 或 BI 系统内部 API,获取数据后格式化成飞书卡片或表格返回。
  • 审批流程触发:开发一个CreateApprovalSkill,用户可以在群里说“申请采购一台 MacBook Pro,预算15000元”,技能解析信息后,自动调用飞书审批流的创建接口,生成一个待审批单据,并@相关负责人。
  • 身份认证与权限:企业内技能往往需要识别用户身份并检查权限。框架需要集成企业的单点登录(SSO)系统。技能在执行时,可以从上下文获取已认证的用户对象,并根据其部门、角色来决定是否允许执行操作或返回哪些数据。

5.3 监控、日志与运维

对于生产环境,可观测性至关重要。

  • 结构化日志:技能框架应集成日志库(如 Winston、Pino),对每一条技能请求记录结构化的日志,包含请求ID、用户ID、技能名、输入、输出、耗时、错误信息等。这便于通过 ELK(Elasticsearch, Logstash, Kibana)或类似工具进行集中分析和排查问题。
  • 性能指标:使用 Prometheus 等工具暴露指标,如每个技能的调用次数、平均响应时间、错误率。这能帮你快速发现性能瓶颈或异常技能。
  • 告警机制:当技能错误率超过阈值或平均响应时间激增时,应能触发告警(通过钉钉、飞书或邮件通知运维人员)。

6. 常见问题排查与实战技巧实录

在实际开发和运维中,你一定会遇到各种问题。下面是一些典型场景和解决思路。

6.1 飞书侧交互问题

问题1:机器人完全没有反应,收不到消息。

  • 排查步骤
    1. 检查事件订阅URL:确保飞书后台配置的 URL 完全正确,且是https(飞书要求)。本地开发可使用内网穿透工具(如 ngrok、localtunnel)获取临时公网地址。
    2. 检查服务器日志:查看应用日志,确认是否收到了飞书的 POST 请求。如果没收到,可能是网络防火墙、安全组策略或 Nginx 配置问题。
    3. 检查权限:确认应用已获取了im:message等必要权限,并且已经发布版本。在“测试企业与人员”中,确保你对话的群或用户已添加为测试者。
    4. 验证签名:飞书的请求带有签名。确保你的服务端正确实现了签名验证逻辑,否则框架可能会因为验证失败而丢弃请求。

问题2:机器人回复了,但用户收不到。

  • 排查步骤
    1. 检查消息类型:飞书消息有多种类型(text,post,interactive等)。确保你的技能返回的消息体格式完全符合飞书 API 文档要求。一个常见的错误是content字段的结构不对。
    2. 检查权限:发送消息需要im:message的发送权限。确认已申请并获批。
    3. 检查回复的open_idchat_id:回复消息时,需要使用接收事件中的open_id(用户)或chat_id(群)。用错了对象会导致发送失败。
    4. 查看飞书服务器返回:你的服务端在调用飞书发送消息 API 后,应记录其响应。如果响应包含错误码(如99991663代表频率限制,99991668代表无权限),可根据错误码针对性解决。

6.2 技能开发与调试问题

问题3:技能逻辑执行出错,但用户只收到一个模糊的错误提示。

  • 解决方案
    • 完善的错误处理:在技能的execute方法内部,用try...catch包裹核心逻辑。在 catch 块中,记录详细的错误堆栈信息到日志,同时可以给用户返回一个更友好的提示,如“技能处理暂时出了点问题,工程师正在排查”。
    • 开发/生产模式:框架应支持模式切换。在开发模式下,可以将详细的错误信息直接返回给用户,方便调试;在生产模式下,则只返回通用提示,避免泄露内部信息。

问题4:如何高效调试技能的匹配和触发逻辑?

  • 技巧
    • 本地模拟:除了使用飞书事件模拟器,可以在本地写一个简单的测试脚本,直接调用技能的execute方法,传入模拟的context对象,快速验证逻辑。
    • 日志记录输入:在技能执行入口处,记录下完整的context对象。这样你就能清楚地看到飞书传过来的原始数据结构,特别是text字段是否包含预期内容,以及如何从中提取参数。
    • 使用关键词调试模式:可以在配置中为技能设置一个特殊的调试关键词(如/debug_todo),当触发时,技能不仅执行操作,还把中间解析出的所有参数都打印出来。

6.3 部署与运维问题

问题5:技能响应变慢,尤其在高峰期。

  • 排查与优化
    1. 数据库查询:检查技能中是否有低效的数据库查询。使用慢查询日志,对频繁调用的查询语句添加索引。
    2. 外部 API 调用:很多技能依赖第三方 API(如天气、翻译)。这些 API 的响应速度直接影响技能性能。为这些调用添加合理的超时设置(如3秒),并考虑使用本地缓存(Redis)来缓存一段时间内相同请求的结果。
    3. 应用性能分析:使用 Node.js 的clinic.js或 Python 的cProfile等工具进行性能剖析,找到 CPU 或内存热点。
    4. 水平扩展:如果应用本身成为瓶颈,考虑使用 Docker 容器化,并通过 Kubernetes 或简单的负载均衡器部署多个实例。

问题6:如何安全地管理众多技能的配置和密钥?

  • 最佳实践
    • 零信任配置:绝不将密钥写入代码或配置文件并提交到代码仓库。使用环境变量或专门的密钥管理服务(如 HashiCorp Vault、AWS Secrets Manager、腾讯云密钥管理系统)。
    • 配置分层:将配置分为default(默认值)、development(开发环境)、production(生产环境)。使用NODE_ENV等环境变量来加载不同的配置文件。
    • 权限最小化:为每个技能使用的第三方服务创建独立的 API 密钥,并赋予最小的必要权限。这样即使一个密钥泄露,影响范围也有限。

6.4 一个实战技巧:实现技能的“会话状态”管理

很多交互式技能需要管理会话状态。例如,一个订餐技能,用户先说“我要订餐”,机器人回复“请选择菜品:A、B、C”,用户再回复“A”,机器人接着问“请输入送餐地址”。这涉及多轮对话。

feishu-skills框架本身可能不提供复杂的会话管理,但我们可以利用外部存储实现一个简单的版本。

思路

  1. 在数据库中创建一个user_sessions表,字段包括user_idskill_namesession_state(JSON字段,存储当前状态和数据)、expires_at
  2. 当技能被触发时,先检查是否存在该用户未过期的会话。
  3. 如果存在会话,则根据session_state中的步骤(如step: ‘waiting_for_dish’)来处理用户当前输入,并更新状态。
  4. 如果不存在会话,则开始一个新的会话,设置初始状态(如step: ‘start’),并发送第一条引导消息。
  5. 设置会话过期时间(如15分钟),超时后自动清理。

这个技巧能将简单的关键词触发技能,升级为更智能、更友好的对话式技能,极大提升用户体验。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/7 17:09:04

快速原型开发中如何利用Taotoken模型广场进行AI能力选型与测试

快速原型开发中如何利用Taotoken模型广场进行AI能力选型与测试 在黑客松或新产品原型开发的早期阶段&#xff0c;团队常常面临一个关键挑战&#xff1a;如何从众多大模型中快速选出最适合当前任务的那一个。直接与多家模型厂商逐一对接、申请密钥、编写适配代码&#xff0c;这…

作者头像 李华
网站建设 2026/5/7 17:07:15

基于AI智能体的兔子行为健康监测系统设计与实践

1. 项目概述&#xff1a;为你的兔子伙伴引入专属AI智能体如果你是一位兔子主人&#xff0c;或者像我一样&#xff0c;对这群敏感、聪明又有些神秘的小动物充满好奇&#xff0c;那么你肯定理解那种渴望“听懂”它们在想什么的感受。兔子不会说话&#xff0c;但它们会用耳朵、鼻子…

作者头像 李华
网站建设 2026/5/7 17:07:00

山东大学软件学院项目实训-创新实训-计科智伴(四)—— 后端第四周:智能互动 + 练习模块

前三周做完认证、画像、学习计划后&#xff0c;这周开始做智能互动和练习模块。这个模块要对接AI、要做题目推荐和自动批改&#xff0c;还要和画像联动更新掌握度&#xff0c;比前几周的纯CRUD要稍复杂一些。今天把这周的工作和代码细节一起记下来。一、这周干了什么&#xff1…

作者头像 李华