用Claude Code从零搭建AI取名小程序:云开发+腾讯混元大模型实战全记录|TaoToken统一Key接入

发布时间:2026/10/4 18:53:54
用Claude Code从零搭建AI取名小程序:云开发+腾讯混元大模型实战全记录|TaoToken统一Key接入 1. 从需求到架构AI取名小程序到底难在哪想做一个能输入姓氏和风格、返回名字建议的小程序听起来简单真正动手会卡在三个地方后端服务怎么部署、大模型怎么稳定调用、前端和模型之间的数据格式怎么对齐。我试过用传统方式搭一套 Node 服务再对接模型接口光是服务器配置和鉴权就耗掉大半天对个人开发者来说性价比太低。微信云开发把后端这块直接抹平了。云函数、云数据库、云存储开箱即用不需要买服务器、不需要配 Nginx、不需要操心 HTTPS 证书。你只需要在微信开发者工具里点几下开通环境就能把注意力放回业务逻辑本身。这对 AI 取名小程序这种“轻后端、重提示词”的项目来说非常合适。腾讯混元大模型在微信生态里的接入路径也比较顺。云开发提供了 AI 扩展能力云函数里可以直接创建模型实例并调用省掉了单独申请密钥、拼接签名、处理跨域这些环节。不过实际开发中我发现如果后续想统一管理多个模型的 Key、或者在不同项目之间复用同一套调用通道还是需要一个更灵活的接入层。这也是我在项目里引入 TaoToken 统一 Key 通道的原因——它把模型调用的入口收敛成一个 Base URL 加一个 Key切换模型时不用改业务代码。这个项目适合谁如果你是小程序开发者想试水 AI 能力或者你有一个具体的取名场景需求想快速验证再或者你想学云函数 大模型的完整链路这篇记录都能直接照着做。最终交付的是一个可运行的小程序用户输入姓氏、选择风格文雅、大气、可爱等云函数拼接提示词调用混元返回 8 到 10 个名字建议每个名字附带寓意说明。整体架构分三层。前端是小程序原生页面负责收集输入和渲染结果。中间是云函数承担参数校验、提示词拼接、模型调用、结果解析。底层是模型服务通过统一通道访问混元。数据流是用户点击生成 → 前端 callFunction → 云函数组装 prompt → 调用模型 → 解析返回文本 → 结构化后回传前端展示。这里有个关键设计决策提示词模板放在云函数里而不是前端。原因有两个一是前端传参容易被篡改二是提示词需要根据场景动态拼接放在服务端更可控。云函数的目录结构我按功能拆分避免所有逻辑堆在一个 index.js 里cloudfunctions/ generateName/ index.js // 入口路由分发 promptBuilder.js // 提示词模板与拼接 modelClient.js // 模型调用封装 parser.js // 结果解析与格式化 package.json这样拆的好处是提示词要调整时只改 promptBuilder.js模型通道要换时只改 modelClient.js互不影响。接下来我会按这个结构逐步把每个文件写出来你可以直接复制到自己的项目里。2. TaoToken 统一 Key 接入Base URL、Key 与 Model ID 三件套在讲具体配置之前先说清楚为什么要在云开发原生调用之外再加一层统一通道。云开发自带的混元调用确实方便但它和微信环境绑定较深。如果你后续想在小程序之外——比如本地脚本、其他后端服务、或者 Claude Code 里——复用同一套模型能力就需要一个独立的接入点。TaoToken 提供的就是这个接入点一个 Base URL、一个 Key、按模型名切换。它的 API 地址是https://taotoken.net/api兼容 OpenAI 风格的接口格式。这意味着你不需要为每个模型写不同的 SDK 适配层只要改 Model ID 就能切换。对取名小程序来说混元负责生成但你可能还想用其他模型做名字打分或者风格润色统一通道能让这些扩展变得简单。先拿 Key。打开https://taotoken.net/api-keys登录后创建一个新的 API Key。建议按项目命名比如name-generator-dev方便后续区分。创建后立即复制保存页面刷新后就不再完整显示。这个 Key 就是后面所有配置里的TAOTOKEN_API_KEY。接下来确认 Model ID。混元系列在 TaoToken 上的模型名通常形如hunyuan-standard或hunyuan-pro具体以控制台模型列表为准。你可以在https://taotoken.net/models查看可用模型和对应的 ID。选hunyuan-standard做取名场景足够生成质量稳定响应速度也快。三件套汇总一下配置项值获取位置Base URLhttps://taotoken.net/api固定API Keysk-xxxxxxAPI Keys 页面创建Model IDhunyuan-standard模型列表页确认在云函数里我建议把这三个值放在环境变量而不是硬编码。微信云开发支持在云函数配置里设置环境变量路径是云开发控制台 → 云函数 → 选中函数 → 配置 → 环境变量。添加TAOTOKEN_API_KEY、TAOTOKEN_BASE_URL、TAOTOKEN_MODEL_ID三个变量。这样本地调试和线上部署可以用不同的 Key也避免密钥泄露到代码仓库。如果你在本地用 Claude Code 辅助开发可以在项目根目录建一个.env.local文件存放这些值但记得加到.gitignore里。Claude Code 读取环境变量后生成云函数代码时会自动引用正确的变量名减少手写错误。还有一点要注意TaoToken 的接口是标准 HTTP 调用云函数里用axios或 Node 原生https模块都可以。我选axios因为拦截器和超时配置更直观。在package.json里加上依赖{ name: generateName, version: 1.0.0, dependencies: { wx-server-sdk: latest, axios: ^1.6.0 } }装依赖时在云函数目录下执行npm install然后在微信开发者工具里右键云函数选择“上传并部署云端安装依赖”。这一步做完模型调用的基础设施就齐了。3. 可复制配置云函数目录结构与混元调用片段这一节直接给可复制的代码。你按目录结构建好文件把内容贴进去改掉环境变量引用就能跑。先看modelClient.js它封装了模型调用对外只暴露一个chat方法// cloudfunctions/generateName/modelClient.js const axios require(axios); const BASE_URL process.env.TAOTOKEN_BASE_URL || https://taotoken.net/api; const API_KEY process.env.TAOTOKEN_API_KEY; const MODEL_ID process.env.TAOTOKEN_MODEL_ID || hunyuan-standard; const client axios.create({ baseURL: BASE_URL, timeout: 30000, headers: { Content-Type: application/json, Authorization: Bearer ${API_KEY} } }); async function chat(messages, options {}) { const payload { model: MODEL_ID, messages: messages, temperature: options.temperature ?? 0.7, max_tokens: options.maxTokens ?? 2000 }; const res await client.post(/v1/chat/completions, payload); return res.data.choices[0].message.content; } module.exports { chat };注意这里用的是/v1/chat/completions路径这是 OpenAI 兼容格式的标准端点。TaoToken 的 Base URL 是https://taotoken.net/api拼接后完整地址是https://taotoken.net/api/v1/chat/completions。如果你在本地用 curl 测试命令是这样的curl https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -d { model: hunyuan-standard, messages: [{role: user, content: 给姓李的男孩取3个文雅的名字}], temperature: 0.7 }返回的 JSON 里choices[0].message.content就是模型生成的文本。云函数里拿到这个文本后交给parser.js做结构化解析。再看promptBuilder.js它根据取名类型拼接不同的提示词// cloudfunctions/generateName/promptBuilder.js function buildPrompt(nameType, params) { const style params.style || 文雅; const surname params.surname || ; const templates { baby: 你是一位精通诗词典故和姓名学的取名顾问。请为姓氏「${surname}」的${params.gender girl ? 女 : 男}孩生成8个${style}风格的名字。每个名字按以下格式输出不要添加额外说明 1. 名字xxx 寓意xxx 出处xxx, company: 你是一位品牌命名专家。请为${params.industry || 科技}行业的公司生成8个${style}风格的名字。每个名字按以下格式输出 1. 名字xxx 寓意xxx 适配性xxx, pet: 你是一位宠物爱好者。请为一只${params.petType || 猫}生成8个${style}风格的名字。每个名字按以下格式输出 1. 名字xxx 寓意xxx }; return templates[nameType] || templates.baby; } module.exports { buildPrompt };提示词里强制约定了输出格式用1. 名字xxx这样的结构方便后续用正则拆分。这是踩过坑之后的写法——早期没约定格式时模型有时返回 Markdown 表格有时返回纯段落前端解析经常失败。parser.js负责把模型返回的文本拆成结构化数组// cloudfunctions/generateName/parser.js function parseNames(text) { const blocks text.split(/\n(?\d\.\s*名字)/).filter(Boolean); return blocks.map(block { const nameMatch block.match(/名字[:]\s*(.)/); const meaningMatch block.match(/寓意[:]\s*(.)/); const sourceMatch block.match(/出处[:]\s*(.)/); return { name: nameMatch ? nameMatch[1].trim() : , meaning: meaningMatch ? meaningMatch[1].trim() : , source: sourceMatch ? sourceMatch[1].trim() : }; }).filter(item item.name); } module.exports { parseNames };最后是入口index.js把上面几个模块串起来// cloudfunctions/generateName/index.js const cloud require(wx-server-sdk); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }); const { chat } require(./modelClient); const { buildPrompt } require(./promptBuilder); const { parseNames } require(./parser); exports.main async (event) { const { nameType baby, params {} } event; if (!params.surname nameType baby) { return { code: 400, message: 请提供姓氏 }; } const prompt buildPrompt(nameType, params); try { const text await chat([ { role: system, content: 你是一个专业取名助手只输出约定格式的内容。 }, { role: user, content: prompt } ], { temperature: 0.8, maxTokens: 2000 }); const names parseNames(text); return { code: 0, data: names, raw: text }; } catch (err) { console.error(模型调用失败, err.response?.data || err.message); return { code: 500, message: 生成失败请稍后重试 }; } };这套代码上传部署后在云开发控制台点“测试”传入{nameType:baby,params:{surname:李,gender:boy,style:文雅}}就能看到返回的名字数组。如果返回code: 500先检查环境变量是否配好再看云函数日志里的具体错误。4. 验证请求与真机预览从本地调试到成功返回代码写完后验证分两步走先在云开发控制台做单函数测试再回到小程序端做真机预览。控制台测试是最快发现配置问题的方式。进入云开发控制台 → 云函数 → generateName → 测试在测试参数里填入{ nameType: baby, params: { surname: 林, gender: girl, style: 文雅 } }点击运行如果配置正确返回结果类似{ code: 0, data: [ { name: 林清婉, meaning: 清雅温婉出自诗词意象, source: 化用古典诗词 }, { name: 林知韵, meaning: 知书达理韵致悠长, source: 古典文学意象 } ], raw: ... }看到code: 0并且data数组里有名字说明云函数到模型的链路通了。如果返回code: 500日志里通常会打印err.response.data里面会写明是 401Key 无效还是 404模型名不对还是超时。本地调试通过后回到小程序端。前端页面pages/index/index.js里调用云函数Page({ data: { surname: , gender: boy, style: 文雅, names: [], loading: false }, onSurnameInput(e) { this.setData({ surname: e.detail.value }); }, onStyleChange(e) { this.setData({ style: e.detail.value }); }, async onGenerate() { if (!this.data.surname) { wx.showToast({ title: 请输入姓氏, icon: none }); return; } this.setData({ loading: true }); try { const res await wx.cloud.callFunction({ name: generateName, data: { nameType: baby, params: { surname: this.data.surname, gender: this.data.gender, style: this.data.style } } }); if (res.result.code 0) { this.setData({ names: res.result.data }); } else { wx.showToast({ title: res.result.message, icon: none }); } } catch (err) { console.error(err); wx.showToast({ title: 调用失败, icon: none }); } finally { this.setData({ loading: false }); } } });对应的 WXML 里用wx:for渲染名字列表每个卡片展示名字、寓意、出处。样式部分按自己的审美调核心是让结果清晰可读。真机预览时点击“编译”生成二维码用微信扫码打开。输入姓氏“林”选“文雅”点生成等待 2 到 5 秒应该能看到名字卡片列表。如果一直转圈检查云函数是否部署成功、环境变量是否生效。如果提示“调用失败”在开发者工具的“云开发 → 云函数 → 日志”里看具体报错。实测下来混元在取名场景的响应速度通常在 2 到 4 秒max_tokens设 2000 足够返回 8 个名字加寓意。如果超过 5 秒还没返回可能是网络波动可以在前端加一个超时提示让用户重试。5. 常见报错排查401、local proxy failed、reading choices 与 OAuth这一节把开发过程中真实遇到的报错和排查路径列出来你遇到时可以直接对照。401 Unauthorized。这是最常见的错误日志里会显示err.response.status 401。原因通常是 API Key 没配、配错、或者环境变量没生效。排查步骤先在云开发控制台确认TAOTOKEN_API_KEY环境变量存在且值以sk-开头然后在云函数里临时打印process.env.TAOTOKEN_API_KEY的前 8 位确认读取到的是正确值最后用 curl 在本地直接测同一个 Key排除 Key 本身失效的可能。如果 curl 能通但云函数不通就是环境变量配置问题。local proxy failed。这个报错通常出现在本地调试云函数时提示无法连接代理。原因是本地环境可能设置了 HTTP_PROXY 或 HTTPS_PROXY 环境变量而云函数运行时不走这个代理。解决办法是在云函数配置里显式清除代理变量或者在modelClient.js里给 axios 设置proxy: falseconst client axios.create({ baseURL: BASE_URL, timeout: 30000, proxy: false, headers: { ... } });reading choices。报错信息类似Cannot read properties of undefined (reading choices)。这说明res.data是 undefined通常是接口返回了非预期结构。可能原因Base URL 拼错导致 404、请求体格式不对导致 400、或者模型名不存在。排查时先把res.data完整打印出来看实际返回了什么。如果是{error:{message:model not found}}就去模型列表确认 Model ID 拼写。OAuth 相关报错。如果你在 Claude Code 里配置 TaoToken 时遇到 OAuth 报错通常是因为 Claude Code 默认走 Anthropic 的 OAuth 流程而 TaoToken 用的是 API Key 模式。需要在 Claude Code 的配置里显式指定 Base URL 和 Key。配置文件路径通常是~/.claude/settings.json或项目级的.claude/settings.json内容如下{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的Key } }如果你用的是 Codex配置文件在~/.codex/auth.json格式类似{ api_key: sk-你的Key, base_url: https://taotoken.net/api }配置完重启 Claude Code 或 Codex再执行请求就不会走 OAuth 流程了。这里的三件套依然是 Base URL、Key、Model ID缺一不可。还有一个容易忽略的点云函数的超时时间默认是 3 秒部分环境是 20 秒而模型调用可能需要 3 到 5 秒。如果日志显示Task timed out after 3.00 seconds需要在云函数配置里把超时时间调到 30 秒。路径是云开发控制台 → 云函数 → 配置 → 超时时间。6. 持续迭代用 Coding Plan 把取名小程序做成长期项目取名小程序跑通之后你可能会想加更多功能名字打分、历史记录、多轮对话调整风格、甚至根据用户反馈自动优化提示词。这些迭代如果每次都手动改代码、部署、测试效率会很低。我的做法是把 Claude Code 接入日常开发流用 Coding Plan 来管理长期的编码任务。具体来说在项目根目录初始化 Claude Code 后我会把常用的操作写成 prompt 模板。比如“帮我优化 promptBuilder.js 里宝宝取名的提示词让输出更符合诗词典故风格”或者“检查 parser.js 的正则是否能兼容模型返回的多种格式”。Claude Code 读取项目文件后直接给出修改建议我确认后应用再部署测试。这个过程比手动翻文档快很多。对于需要长期维护的编码任务Coding Plan 提供了更稳定的调用额度。你可以在https://taotoken.net/coding-plan查看套餐详情。它的价值在于当你频繁用 Claude Code 做代码生成、调试、重构时不用担心额度突然耗尽打断工作流。对个人开发者来说按月订阅比按量付费更可控。回到取名小程序本身后续迭代我建议按这个优先级来第一加结果缓存相同姓氏和风格的请求直接读云数据库减少模型调用第二加用户反馈按钮把“喜欢/不喜欢”的记录存下来后续用来微调提示词第三扩展场景从宝宝取名延伸到公司取名、宠物取名、游戏 ID每个场景一套提示词模板。云开发的云数据库在这里能派上大用场。建一个name_history集合每次生成后写入openid、surname、style、results、timestamp。前端加一个“历史记录”页面用wx.cloud.database().collection(name_history).where({ _openid: {openid} }).get()拉取当前用户的历史。权限设置为“仅创建者可读写”避免数据泄露。如果你在接入过程中遇到模型返回格式不稳定的问题可以在parser.js里加一层兜底当正则匹配不到名字时直接把原始文本按行拆分取前 8 行作为候选。这样即使模型偶尔不按格式输出前端也不会白屏。最后一步验证在真机上输入不同姓氏和风格组合连续生成 5 次观察返回时间和结果质量。如果某次返回为空检查云函数日志里的raw字段看模型实际返回了什么。多数情况下是提示词需要微调而不是接口问题。把每次调整后的提示词版本记录下来慢慢就能找到最适合你场景的那一版。