先说一个观察:最近 AI 助手产品的商业化动作明显变多了。千问 App 的部分探索类功能开始尝试收费,而豆包目前仍然以免费体验为主。很多开发者看到这个现象的第一反应是“怎么突然收费了”“豆包免费是不是更香”。但如果我们只停留在产品吐槽层面,很容易忽略背后的技术逻辑和工程成本。
这篇文章我想换个角度来聊:功能收费和技术实现有什么关系?为什么有的产品敢收费,有的产品选择继续免费?作为开发者,如果要给 AI 应用加上“免费额度 + 按量计费 + 会员权益”这一套体系,技术上该怎么做?
无论你是 App 开发者、后端工程师,还是正在设计 AI 产品商业模式的独立开发者,这篇文章应该都能给你一些可落地的思路。我会结合权益设计、计费模块、配额管理等方向,给出完整的表结构、接口示例和代码片段。
1. 现象背景:一次关于 AI 产品商业模式的讨论
1.1 千问 App 的探索收费和豆包的免费策略
先从现象说起。千问 App 是阿里巴巴推出的 AI 助手应用,提供问答、写作、翻译、代码生成等一系列能力。它内置了一个“探索”入口,主要用来承载更强的推理、更深度的研究类任务。从公开信息来看,这类探索场景在部分功能上开始尝试收费,比如按次消耗积分、会员优先体验、部分高级模式需要付费解锁等。
豆包则是字节跳动推出的 AI 助手 App,特点是对普通用户非常友好,大部分基础功能免费使用,并通过对话体验、智能体生态来吸引用户留存。豆包目前并不是没有商业化考虑,只是它的商业化重点更偏向大规模用户覆盖和生态建设,而不是急于在单一功能上收费。
这两种策略没有绝对的对错,只是产品阶段、成本结构、用户群体不同,选择的路径也不同。
1.2 为什么开发者要关心这个话题
很多人觉得 AI 产品收费是运营和产品经理的事,跟技术没关系。实际上完全不是这样。
一个功能一旦涉及收费,就意味着后面要接入一套完整的交易链路:用户身份识别、权益判定、调用计量、配额扣减、订单生成、支付回调、异常补偿。这些都不是产品经理拿 Excel 画一画就能搞定的,而是需要后端工程师真正写代码实现的。
另外,收费功能对系统稳定性、数据准确性、安全防护的要求都会显著提高。免费阶段系统挂了可以说“服务拥挤”,收费之后用户就会说“我付了钱为什么用不了”。所以,从技术角度研究 AI 功能收费,是非常实际的需求。
1.3 文章内容规划
我会先用相对通俗的方式拆解 AI 应用的几种商业化模式,然后从工程角度分析“探索收费”需要用到的技术模块,再通过一个可运行的小项目演示整套实现思路,最后整理常见问题和最佳实践。
这篇文章不打算评价哪家产品更良心,而是希望把商业模式和工程实现串起来,让读完的人既能看懂产品逻辑,也能写出代码。
2. AI 应用的商业化模式拆解
2.1 按调用量计费:最直接的商业模式
按调用量计费是目前 AI 应用最常见的收费方式。用户可以免费使用一定额度,超出后按次或按 Token 计费。这种模式的优点是对用户公平——用多少付多少;缺点是用户不容易预估成本,容易在不知不觉中产生费用。
从技术角度看,按量计费需要解决的核心问题是计量。每一次 AI 调用都要被准确记录,并且要能在毫秒级完成余额判断。这里通常会引入两个模块:
- 计量模块:负责记录调用次数、输入 Token 数、输出 Token 数。
- 配额模块:负责判断当前用户是否还有可用余额。
这两个模块如果设计得不好,很容易出现“用户额度用完了还能继续调用”的漏洞,或者“明明刚充值了还是提示余额不足”的体验问题。
2.2 订阅制:稳定现金流和更高用户粘性
订阅制是另一种主流的商业化模式。用户按月或按年付费,获得一个较大的使用配额,比如每月 1000 次高级探索、100GB 存储空间等。
订阅制的技术实现比按量计费更复杂一些,因为它涉及:
- 订阅状态管理(生效中、过期、续费、取消);
- 配额周期重置(按月、按年);
- 订阅变更时的即时生效与延期生效。
在实际项目中,订阅制经常和按量计费混合使用。订阅用户先消耗订阅配额,超出后再按量扣费。这种方式对用户体验更友好,也能让产品的收入结构更加多元。
2.3 广告和增值服务:间接商业化
目前 AI 助手类产品直接放广告的情况还不算多,因为广告会严重打断对话体验。但增值服务的思路很常见,比如:
- 更高的并发优先级;
- 更快的响应速度;
- 更长上下文的记忆能力;
- 专属智能体或专业工具链。
这些增值服务不一定单独收费,往往会被打包进会员体系。技术实现上,它们本质上还是“权益控制”问题,也就是根据用户身份返回不同的服务配置。
2.4 模型成本决定了商业模式
不管是千问还是豆包,背后都有真实且不低的算力成本。大模型 API 按 Token 计费,用户一次长对话可能消耗几万 Token,如果完全免费,平台的成本压力会非常大。
所以,我们看到的现象是:基础能力免费拉新,高级能力收费转化。这是 AI 应用商业化的通用路径。而从技术实现来看,关键就在于如何在同一个应用里,同时支持免费、会员、按量计费等不同模式,并且让用户体验尽量平滑。
3. 从技术看“功能收费”:权益体系设计思路
在动手写代码之前,我们先要建立一套完整的权益体系设计思路。一个 AI 功能如果要收费,后端一定会有下面几个核心模块:
- 用户身份识别;
- 功能开关(Feature Gate);
- 权益模型(用户拥有什么权益);
- 配额与计量(用了多少,还剩多少);
- 订单与支付(钱从哪里来)。
下面逐个拆开讲。
3.1 用户身份识别
收费的前提是知道“谁在用”。AI App 通常使用手机号或第三方 OAuth 登录,登录后服务端会为每个用户生成一个唯一的用户 ID,后续所有请求都通过 Token 携带用户身份。
这个模块没什么特别高深的地方,但需要注意的是:所有计费判定必须以后端身份为准,不能信任前端传过来的用户 ID 或会员状态。否则用户完全可以伪造请求,绕过收费逻辑直接调用 AI 接口。
3.2 功能开关(Feature Gate)
功能开关的作用是控制某个功能对用户是否可用。它可以小到一个按钮,大到一个完整模型服务。
常见的功能开关实现方式有两种:
- 配置中心方式:把功能可见性放在配置中心里面,例如 Apollo、Nacos,动态调整,不需要发版。
- 代码硬编码方式:直接在后端代码里判断用户类型。适合小型项目,但不好维护。
正规做法是两者结合:功能码(Feature Code)定义功能的唯一标识,功能开关决定全局是否放量,用户权益决定个人是否可用。比如explore:deep_research就是一个功能码,它对应的开关可能先对 5% 的用户开放,其中会员用户可用 100 次,非会员用户可用 3 次。
3.3 权益模型
权益模型描述的是用户对某个功能的可用程度。一个简单的模型可以包含:
- 用户 ID;
- 功能码;
- 剩余次数或剩余额度;
- 额度到期时间;
- 额度来源(免费赠送、会员赠送、单独购买)。
这个模型要支撑两种常见操作:
- 查询权益(调用前检查);
- 扣减权益(调用成功或调用发起时扣减)。
一个有经验的开发者会告诉你:扣减权益和调用 AI 接口不是一个原子操作,必须设计好顺序和补偿逻辑。简单说就是,先扣额度再调用接口,如果接口调用失败,就把额度加回来。否则容易出现“额度扣了但没出结果”的客诉。
3.4 订单与支付闭环
如果用户额度不够,就需要引导用户购买。购买流程涉及:
- 创建订单;
- 发起支付(微信、支付宝、App Store 或应用商店支付);
- 支付回调处理;
- 订单状态同步;
- 对账。
这部分属于偏传统的电商交易链路,技术已经很成熟,但在 AI 应用里容易被忽略。因为很多 AI 团队是由算法工程师组成的,他们对支付回调、幂等、对账这些概念比较陌生,这就容易在商业化落地时踩坑。
4. 一个小型 Demo:实现 AI 功能收费
接下来,我们用代码演示一个简化但完整的“AI 功能收费”后端。项目假设如下:
- 用户登录后可以调用一个名为“深度探索”的 AI 功能;
- 每个用户有 3 次免费额度;
- 使用完后需要购买“探索积分包”;
- 购买成功后,积分自动到账;
- 调用 AI 接口前校验余额,调用后扣减。
这个 Demo 使用 Java + Spring Boot 实现核心接口,使用 Python 写一个计量脚本方便理解,数据库表结构用 SQL 表示。
4.1 创建项目结构
先创建一个 Spring Boot 项目,目录结构如下:
ai-charge-demo/ ├── pom.xml ├── src/main/java/com/example/aicharge/ │ ├── AiChargeApplication.java │ ├── controller/ │ │ ├── ExploreController.java │ │ └── OrderController.java │ ├── service/ │ │ ├── QuotaService.java │ │ ├── ExploreService.java │ │ └── OrderService.java │ ├── entity/ │ │ ├── UserQuota.java │ │ └── OrderInfo.java │ └── mapper/ │ ├── UserQuotaMapper.java │ └── OrderInfoMapper.java └── src/main/resources/ └── application.yml4.2 数据库表结构
我们需要两张核心表:用户配额表和订单表。
用户配额表:
CREATE TABLE user_quota ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id VARCHAR(64) NOT NULL COMMENT '用户ID', feature_code VARCHAR(64) NOT NULL COMMENT '功能码', total_quota INT NOT NULL DEFAULT 0 COMMENT '总配额', used_quota INT NOT NULL DEFAULT 0 COMMENT '已用配额', expire_time DATETIME DEFAULT NULL COMMENT '到期时间', update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uk_user_feature (user_id, feature_code) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户功能配额表';订单表:
CREATE TABLE order_info ( id BIGINT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(64) NOT NULL COMMENT '订单号', user_id VARCHAR(64) NOT NULL COMMENT '用户ID', product_code VARCHAR(64) NOT NULL COMMENT '商品编码', amount DECIMAL(10,2) NOT NULL COMMENT '支付金额', status TINYINT NOT NULL DEFAULT 0 COMMENT '0待支付 1已支付 2已关闭', create_time DATETIME DEFAULT CURRENT_TIMESTAMP, pay_time DATETIME DEFAULT NULL, UNIQUE KEY uk_order_no (order_no) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';如果是真实项目,还需要一张“商品表”来定义不同积分包的价格和赠送配额。这里为了演示,直接在订单服务里用常量表示。
4.3 权益校验服务
在调用 AI 功能之前,我们需要一个服务来校验用户是否还有配额。下面是一个简化的QuotaService:
// 文件路径:src/main/java/com/example/aicharge/service/QuotaService.java @Service public class QuotaService { @Resource private UserQuotaMapper userQuotaMapper; /** * 校验用户是否还有可用配额 */ public boolean checkQuota(String userId, String featureCode) { UserQuota quota = userQuotaMapper.findByUserIdAndFeatureCode(userId, featureCode); if (quota == null) { // 首次使用,初始化免费额度 quota = new UserQuota(); quota.setUserId(userId); quota.setFeatureCode(featureCode); quota.setTotalQuota(3); quota.setUsedQuota(0); userQuotaMapper.insert(quota); } // 判断是否过期 if (quota.getExpireTime() != null && quota.getExpireTime().before(new Date())) { return false; } return quota.getUsedQuota() < quota.getTotalQuota(); } /** * 扣减配额 */ public boolean deductQuota(String userId, String featureCode) { UserQuota quota = userQuotaMapper.findByUserIdAndFeatureCode(userId, featureCode); if (quota == null) { return false; } if (quota.getUsedQuota() >= quota.getTotalQuota()) { return false; } int result = userQuotaMapper.increaseUsedQuota(userId, featureCode); return result > 0; } /** * 配额回补,用于AI调用失败时的补偿 */ public void compensateQuota(String userId, String featureCode) { userQuotaMapper.decreaseUsedQuota(userId, featureCode); } }这里有几个细节需要注意:
checkQuota和deductQuota是两个独立方法,调用方需要在业务逻辑中排序执行。increaseUsedQuota应该使用乐观锁或原子更新,防止并发情况下超扣。- 如果 AI 服务调用失败,需要调用
compensateQuota把额度还回去。
4.4 核心调用接口
ExploreService负责调用 AI 大模型服务。这里我用一个模拟方法代替真实模型调用,核心是展示配额扣减和异常补偿的流程。
// 文件路径:src/main/java/com/example/aicharge/service/ExploreService.java @Service public class ExploreService { private static final Logger logger = LoggerFactory.getLogger(ExploreService.class); @Resource private QuotaService quotaService; /** * 执行深度探索 */ public String explore(String userId, String featureCode, String prompt) { // 1. 校验配额 if (!quotaService.checkQuota(userId, featureCode)) { throw new RuntimeException("配额不足,请购买探索积分包"); } // 2. 扣减配额 boolean deductResult = quotaService.deductQuota(userId, featureCode); if (!deductResult) { throw new RuntimeException("配额扣减失败,请稍后重试"); } try { // 3. 调用真实AI接口,这里用模拟方法代替 String result = callRemoteAi(prompt); logger.info("AI调用成功,userId={}, featureCode={}", userId, featureCode); return result; } catch (Exception e) { // 4. 调用失败,回补配额 logger.error("AI调用失败,开始回补配额,userId={}", userId, e); quotaService.compensateQuota(userId, featureCode); throw new RuntimeException("AI服务暂不可用,请稍后重试"); } } private String callRemoteAi(String prompt) { // 真实项目中这里调用千问、豆包或其他大模型API // 示例思路如下,需按实际模型服务地址和鉴权方式调整 return "模拟AI返回结果:" + prompt; } }从这段代码可以看出,收费功能的核心并不是 AI 调用本身,而是调用前后的权益处理和异常补偿机制。真实项目中还需要考虑并发问题:多个请求同时到达时,如何保证配额不会超扣?一个常见方案是使用数据库乐观锁:
UPDATE user_quota SET used_quota = used_quota + 1 WHERE user_id = #{userId} AND feature_code = #{featureCode} AND used_quota < total_quota;这样即使并发请求同时到达,数据库行锁也会保证只有一个请求能更新成功。
4.5 订单服务与支付回调
再来看订单服务。下面是一个简化版的下单和支付回调处理:
// 文件路径:src/main/java/com/example/aicharge/service/OrderService.java @Service public class OrderService { @Resource private OrderInfoMapper orderInfoMapper; @Resource private UserQuotaMapper userQuotaMapper; private static final BigDecimal PRICE_P10 = new BigDecimal("9.90"); private static final String PRODUCT_P10 = "explore_p10"; /** * 创建订单 */ public String createOrder(String userId, String productCode) { OrderInfo order = new OrderInfo(); order.setOrderNo(generateOrderNo()); order.setUserId(userId); order.setProductCode(productCode); order.setAmount(PRICE_P10); order.setStatus(0); orderInfoMapper.insert(order); return order.getOrderNo(); } /** * 支付回调 */ public boolean handlePayCallback(String orderNo, String payTradeNo) { OrderInfo order = orderInfoMapper.findByOrderNo(orderNo); if (order == null || order.getStatus() != 0) { // 订单不存在或已处理,直接返回成功,保证接口幂等 return true; } // 修改订单状态 order.setStatus(1); order.setPayTime(new Date()); orderInfoMapper.update(order); // 给用户发放配额 UserQuota quota = userQuotaMapper.findByUserIdAndFeatureCode( order.getUserId(), "explore:deep_research"); if (quota == null) { quota = new UserQuota(); quota.setUserId(order.getUserId()); quota.setFeatureCode("explore:deep_research"); quota.setTotalQuota(10); quota.setUsedQuota(0); userQuotaMapper.insert(quota); } else { userQuotaMapper.increaseTotalQuota(order.getUserId(), "explore:deep_research", 10); } return true; } private String generateOrderNo() { return System.currentTimeMillis() + String.format("%06d", ThreadLocalRandom.current().nextInt(1000000)); } }这里要特别注意幂等处理。支付回调可能会被支付平台推送多次,甚至网络超时后重复推送,所以回调处理必须保证“同一笔订单只生效一次”。上面的代码通过判断订单状态来保证幂等,这是最基础也最关键的保障。
4.6 运行与验证
启动 Spring Boot 应用后,可以用下面的流程验证:
- 先调用
/api/explore接口,传入一个未注册用户 ID。 - 第一次、第二次、第三次应该正常返回 AI 模拟结果。
- 第四次应该返回“配额不足”。
- 调用
/api/order/create创建订单。 - 模拟支付回调
/api/order/callback。 - 再次调用
/api/explore,应该又能正常使用。
从这套链路可以看到,AI 功能收费并不是一个孤立功能,它实际上打通了用户、权益、计费、支付四个子系统。这也是为什么很多团队在做 AI 应用商业化时,会明显感觉到“算法模型不是瓶颈,业务系统才是瓶颈”。
5. 免费策略与收费策略背后的工程差异
5.1 免费模式对系统架构的挑战
选择免费策略的产品,比如豆包,核心目标是快速获取用户并提升活跃。这种模式看起来简单,但技术挑战反而更大:
- 用户量上来之后,并发请求量会非常大,模型推理成本需要靠工程优化来摊薄;
- 免费用户大多没有付费预期,对响应速度和可用性要求反而更高;
- 没有支付和订单链路的“门槛”,攻击者可以低成本刷接口,需要额外的风控投入。
所以在免费模式下,工程团队的核心目标通常是降低成本、提升吞吐、做好限流和降级。
5.2 收费模式对系统架构的挑战
收费模式的技术挑战更多集中在“钱相关”的逻辑。比如:
- 计费系统必须准确,不能让用户多扣费;
- 订单、支付回调、退款流程必须完整;
- 权益发放和扣减要做到最终一致;
- 遇到用户投诉时,要有完整的操作流水可查。
这些能力在免费时代可有可无,一旦收费就成了硬性要求。很多 AI 创业公司早期为了快速上线,选择先免费、后收费,结果到了收费阶段才发现,底层系统完全没有为商业化做准备,导致排期延期严重。这个经验教训值得所有做 AI 应用的人提前重视。
5.3 两种模式可以共存
千问和豆包看起来是两种路线,实际上并不冲突。很多 AI 产品都会走“免费基础功能 + 付费高级功能”的混合模式。差别只在比例和节奏:有的产品愿意拉长免费期,有的产品则更快验证付费意愿。
从工程角度看,实现混合模式并不难,难的是权益模型的灵活设计。只要在第一天就把功能码、用户权益、配额计量这些抽象做好,后面无论免费还是收费,都只是配置层面的变化。
6. 常见问题与排查思路
在 AI 功能收费的开发和运营过程中,下面这些问题是出现频率最高的。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 用户额度扣了但 AI 调用失败 | 配额扣减和 AI 调用没有做补偿 | 增加异常补偿机制,调用失败自动回补配额 |
| 支付回调重复处理导致多次发放积分 | 回调接口没有做幂等 | 通过订单状态或唯一流水号做幂等控制 |
| 并发请求导致超扣 | 使用普通 update 语句并发更新 | 使用条件更新WHERE used_quota < total_quota |
| 用户反馈充值后权益未到账 | 支付回调与权益发放不在同一个事务 | 使用事务保证订单状态和积分变更原子性 |
| 免费用户通过伪造请求调用付费功能 | 前后端都做了校验,但后端未做用户校验 | 所有计费判断以后端用户身份为准 |
| 消耗记录不透明引发投诉 | 缺少操作流水表 | 建立调用流水表,记录每次 AI 调用的时间、费用、状态 |
这里我特别想强调一点:计费系统一定要有流水表。免费功能可以不记录明细,但一旦涉及扣费和支付,每一笔操作的来龙去脉都必须能查清楚。没有流水表,用户一句“我没用为什么扣了”就能让你陷入被动。
7. 最佳实践与工程建议
7.1 权益设计要做到可扩展
不要只为一个功能设计权益体系。建议从第一天就用“功能码”的方式抽象所有付费点。每个功能在权益层都拥有独立的配额字段和计量规则,这样产品经理以后新增任何一个收费功能,后端不需要改表结构,只需要新增一条功能码配置。
7.2 用事务保证资金安全
订单状态修改、支付流水记录、权益发放这三件事必须放在同一个数据库事务里。如果某个步骤失败,整体回滚,避免出现“钱收了但权益没到账”的问题。
7.3 所有回调接口要幂等
不管是支付宝、微信支付还是苹果支付,支付平台都会多次回调同一个订单。不要假设回调只会发生一次,要在代码里显式处理重复回调。
7.4 注意异步扣减和补偿
老牌的计费系统往往采用“先扣后调用、失败返还”的模式。这种方式逻辑清晰,但需要注意补偿的时效性。建议在 AI 调用超时或者返回异常时,立刻触发异步补偿任务,避免长时间占用用户配额。
7.5 计量数据要采集
计费系统上线后,要采集每个功能码的调用量、成功量、失败量、扣费量、退费量。这些指标不仅能帮助你判断功能是否健康,也能为定价策略提供数据支撑。
7.6 灰度发布和开关
任何收费策略都不建议直接全量发布。建议先通过功能开关开放给内部用户体验,再灰度到 5% 的用户,确认没有计费问题后再逐步放量。如果是涉及价格调整,还要考虑老用户的权益保护方案。
7.7 安全与合规
收费涉及资金流,一定要遵守平台规则和法律法规。App 上架的虚拟支付必须走应用商店的支付渠道,否则会有下架风险。会员自动续费也需要提供清晰的取消入口,避免合规问题。
8. 总结与学习路线
回到标题的问题:千问 App 部分探索功能想学豆包,能不能跑通?我的看法是,与其纠结“要不要学豆包”,不如先把“功能收费”这套技术基础打好。免费策略和收费策略并不是对立关系,而是产品不同阶段的组合选择。真正的难点不在于模型本身,而在于:权益体系、配额计量、支付闭环、异常补偿、数据对账。
如果你正在做 AI 应用,方向建议是先给应用增加一个简单的配额表,免费用户默认给几次调用额度,然后在调用链路里加上校验和扣减逻辑。这个过程不需要太复杂,但足以帮助你建立对计费系统的整体感知。之后再去研究订阅制、支付回调、对账体系,就会顺畅很多。
需要注意的是,我今天给出的代码是一个最小闭环示例,距离生产级还有不少距离。真实项目中,你还需要引入配置中心来管理功能开关,引入消息队列来提高回调处理的吞吐能力,引入分布式事务或最终一致性方案来保证多个服务之间的数据一致。这些内容每一条都可以单独展开写成一篇文章,留给大家逐步深入。
如果你在落地 AI 功能收费的过程中遇到具体问题,欢迎把报错信息或设计文档发在评论区交流。实践出真知,踩过的坑多了,商业化的路自然就越走越顺。