<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>AI 应用 on Saiga</title>
    <link>http://localhost:1313/categories/ai-%E5%BA%94%E7%94%A8/</link>
    <description>Recent content in AI 应用 on Saiga</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <managingEditor>wuwenzen@outlook.com (wuwj)</managingEditor>
    <webMaster>wuwenzen@outlook.com (wuwj)</webMaster>
    <lastBuildDate>Wed, 01 May 2024 00:00:00 +0000</lastBuildDate>
    <atom:link href="http://localhost:1313/categories/ai-%E5%BA%94%E7%94%A8/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>让 AI 帮我做前端性能分析报告</title>
      <link>http://localhost:1313/posts/2024-05-01-ai-performance-analyzer/</link>
      <pubDate>Wed, 01 May 2024 00:00:00 +0000</pubDate><author>wuwenzen@outlook.com (wuwj)</author>
      <guid>http://localhost:1313/posts/2024-05-01-ai-performance-analyzer/</guid>
      <description>&lt;p&gt;前端做性能优化，两个常见痛点：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;报表很数据化，非技术同学看不懂&lt;/li&gt;&#xA;&lt;li&gt;每次写性能报告都很花时间：看指标 → 找问题 → 翻译成大家听得懂的结论&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;于是试了一件事：&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;我负责把数据准备好，AI 帮我写一份「结构化的性能分析报告」，我只做最后校对。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-输入与输出长啥样&#34;&gt;1. 输入与输出长啥样？&lt;/h2&gt;&#xA;&lt;h3 id=&#34;11-输入数据&#34;&gt;1.1 输入数据&lt;/h3&gt;&#xA;&lt;p&gt;主要有两部分：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Lighthouse JSON 报告&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;性能得分&lt;/li&gt;&#xA;&lt;li&gt;LCP / CLS / TBT / TTI 等指标&lt;/li&gt;&#xA;&lt;li&gt;各种「机会」与「诊断」信息&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;真实用户监控数据（RUM）&lt;/strong&gt;（可选）&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;最近一段时间的 LCP P75、FCP P75&lt;/li&gt;&#xA;&lt;li&gt;不同地区/设备的耗时对比&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;12-期望输出&#34;&gt;1.2 期望输出&lt;/h3&gt;&#xA;&lt;p&gt;希望 AI 给我的报告包含：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;一段 1～2 句话的性能整体概览&lt;/li&gt;&#xA;&lt;li&gt;用人话解释关键指标的含义和当前水平&lt;/li&gt;&#xA;&lt;li&gt;列出 3～5 个主要问题（按影响排序）&lt;/li&gt;&#xA;&lt;li&gt;每个问题配上具体可执行的优化建议&lt;/li&gt;&#xA;&lt;li&gt;告诉我「先做哪几件事最划算」&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;2-先做精简给-ai-的不是原始-json&#34;&gt;2. 先做精简：给 AI 的不是原始 JSON&lt;/h2&gt;&#xA;&lt;p&gt;原始 Lighthouse JSON 体积很大，直接给模型既浪费 Token，也容易让它迷路。&lt;br&gt;&#xA;所以写了一个小脚本，把它整理成简版结构：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-jsonc&#34; data-lang=&#34;jsonc&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://example.com&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;score&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.72&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;metrics&amp;#34;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;LCP&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3800&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;CLS&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.11&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;FID&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;25&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;TTI&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;4200&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;opportunities&amp;#34;&lt;/span&gt;: [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;减少未使用的 JavaScript&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;estimatedSavingsMs&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;800&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;消除阻塞渲染的资源&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;estimatedSavingsMs&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;600&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;diagnostics&amp;#34;&lt;/span&gt;: [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;主线程工作过多&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;部分图片未压缩&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;rum&amp;#34;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;LCP_p75&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;4200&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;FCP_p75&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;2100&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;sampleCount&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;120000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样输入既足够有信息量，又相对稳定。&lt;/p&gt;</description>
    </item>
    <item>
      <title>用大模型做一个「表单配置助手」</title>
      <link>http://localhost:1313/posts/2024-02-05-ai-powered-form-builder/</link>
      <pubDate>Mon, 05 Feb 2024 00:00:00 +0000</pubDate><author>wuwenzen@outlook.com (wuwj)</author>
      <guid>http://localhost:1313/posts/2024-02-05-ai-powered-form-builder/</guid>
      <description>&lt;p&gt;在很多中台系统里，「加一个表单页面」是非常常见的需求：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;运营要配活动&lt;/li&gt;&#xA;&lt;li&gt;风控要配规则&lt;/li&gt;&#xA;&lt;li&gt;产品要加信息收集表单&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;常规流程比较重：写需求 → 画原型 → 前端实现 → 联调 → 上线。&lt;br&gt;&#xA;对于那些只是字段多、变更频率高的小表单，其实有点浪费。&lt;/p&gt;&#xA;&lt;p&gt;所以我们尝试做了一个小工具：&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;运营用自然语言描述表单，大模型帮忙产出一份「表单配置 JSON」，前端根据配置自动渲染。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;这篇文章就简单记录一下实现思路。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-目标从一句话到一份表单配置&#34;&gt;1. 目标：从一句话到一份表单配置&lt;/h2&gt;&#xA;&lt;p&gt;我们给自己的目标很克制：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;输入&lt;/strong&gt;：一段自然语言描述，例如&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;“做一个录入投资人基本信息的表单，需要姓名、手机号、证件类型和证件号，手机号必填要校验格式，证件类型从下拉里选身份证/护照。”&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;输出&lt;/strong&gt;：一份前端能直接使用的配置 JSON：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;字段列表&lt;/li&gt;&#xA;&lt;li&gt;字段类型、标签、占位&lt;/li&gt;&#xA;&lt;li&gt;是否必填、校验规则&lt;/li&gt;&#xA;&lt;li&gt;下拉选项等&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;前端只负责：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;把描述提交给后端&lt;/li&gt;&#xA;&lt;li&gt;拿到配置 JSON&lt;/li&gt;&#xA;&lt;li&gt;交给通用 &lt;code&gt;&amp;lt;FormRenderer :config=&amp;quot;formConfig&amp;quot; /&amp;gt;&lt;/code&gt; 渲染&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;2-配置格式先把机器读得懂定义好&#34;&gt;2. 配置格式：先把「机器读得懂」定义好&lt;/h2&gt;&#xA;&lt;p&gt;要让大模型产出可用结果，首先要有一份清晰的配置格式。示例：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-jsonc&#34; data-lang=&#34;jsonc&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;投资人信息录入&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;layout&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;vertical&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;fields&amp;#34;&lt;/span&gt;: [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;姓名&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;input&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;required&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;placeholder&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;请输入姓名&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mobile&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;手机号&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;input&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;required&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;rules&amp;#34;&lt;/span&gt;: [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;regex&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;pattern&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^1\\d{10}$&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;请输入 11 位手机号&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;idType&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;证件类型&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;select&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;required&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;options&amp;#34;&lt;/span&gt;: [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;居民身份证&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ID_CARD&amp;#34;&lt;/span&gt; },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;护照&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PASSPORT&amp;#34;&lt;/span&gt; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;idNo&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;证件号码&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;input&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;required&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;前端已经有配套组件：&lt;/p&gt;</description>
    </item>
    <item>
      <title>在内部运营/中台工具里加一点 AI：从搜索到推荐</title>
      <link>http://localhost:1313/posts/2023-11-01-ai-in-internal-tools/</link>
      <pubDate>Wed, 01 Nov 2023 00:00:00 +0000</pubDate><author>wuwenzen@outlook.com (wuwj)</author>
      <guid>http://localhost:1313/posts/2023-11-01-ai-in-internal-tools/</guid>
      <description>&lt;p&gt;相比 C 端产品，「内部运营/中台工具」看起来没那么光鲜，界面经常是：&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;一堆表格、一堆配置、一堆筛选项。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;但正因为如此，AI 在这里往往很好落地：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;用户数量受控，易于试点；&lt;/li&gt;&#xA;&lt;li&gt;业务流程清晰，方便评估效果；&lt;/li&gt;&#xA;&lt;li&gt;哪怕只提升一点效率，整体价值也不小。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;这篇文章就分享几个我们在内部工具里「加一点 AI」的尝试：从搜索到推荐再到智能填写。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-智能搜索从条件筛选到自然语言搜索&#34;&gt;1. 智能搜索：从「条件筛选」到「自然语言搜索」&lt;/h2&gt;&#xA;&lt;h3 id=&#34;11-传统方式的痛点&#34;&gt;1.1 传统方式的痛点&lt;/h3&gt;&#xA;&lt;p&gt;运营同学以前查数据要：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;打开一个复杂查询页；&lt;/li&gt;&#xA;&lt;li&gt;选择 N 个下拉框（业务线、产品、日期区间、状态…）；&lt;/li&gt;&#xA;&lt;li&gt;点击查询，发现忘记勾某个条件，再重新来一次。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;于是我们考虑加一个入口：&lt;strong&gt;自然语言搜索&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;例如：&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;「最近 7 天上海地区的私募新增高净值客户」&lt;br&gt;&#xA;「失败次数超过 3 次的合同签署记录」&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h3 id=&#34;12-技术方案&#34;&gt;1.2 技术方案&lt;/h3&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;用大模型把自然语言解析成结构化查询条件；&lt;/li&gt;&#xA;&lt;li&gt;再把这些条件映射到后端已有查询接口；&lt;/li&gt;&#xA;&lt;li&gt;最终仍然走「原有 SQL / ES 查询逻辑」。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;伪代码示意：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;prompt&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;你是查询构建助手。请将用户的自然语言查询转换为 JSON 条件。...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;llmResult&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;callLLM&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;prompt&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;userQuery&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;conditions&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;JSON&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;parse&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;llmResult&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;data&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;callSearchAPI&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;conditions&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;关键点：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;不直接让模型生成 SQL&lt;/strong&gt;（安全风险 &amp;amp; 不可控）；&lt;/li&gt;&#xA;&lt;li&gt;而是生成一个受控的 JSON 条件对象。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;13-前端体验&#34;&gt;1.3 前端体验&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;搜索框下方展示「解析出的条件」，让用户确认；&lt;/li&gt;&#xA;&lt;li&gt;支持一键切换到「高级筛选」视图，展示同样条件；&lt;/li&gt;&#xA;&lt;li&gt;避免让 AI 变成黑盒——用户看得见它怎么理解的。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;2-智能推荐运营配置页也能变懂你一点&#34;&gt;2. 智能推荐：运营配置页也能变「懂你」一点&lt;/h2&gt;&#xA;&lt;p&gt;场景：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;运营在后台配置「某类用户看到哪些运营位/推荐产品」；&lt;/li&gt;&#xA;&lt;li&gt;一般是靠经验拍脑袋选；&lt;/li&gt;&#xA;&lt;li&gt;想利用历史数据做一点辅助决策。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;21-我们做了什么&#34;&gt;2.1 我们做了什么&lt;/h3&gt;&#xA;&lt;p&gt;在原有「人工配置」的基础上，增加一个「AI 建议」按钮：&lt;/p&gt;</description>
    </item>
    <item>
      <title>用 RAG 做项目文档问答：从零搭一个 Demo</title>
      <link>http://localhost:1313/posts/2023-09-10-rag-for-project-docs/</link>
      <pubDate>Sun, 10 Sep 2023 00:00:00 +0000</pubDate><author>wuwenzen@outlook.com (wuwj)</author>
      <guid>http://localhost:1313/posts/2023-09-10-rag-for-project-docs/</guid>
      <description>&lt;p&gt;之前写过一篇「文档问答助手」的早期尝试，这次想更系统地从 RAG 角度，把整个过程讲清楚。&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;RAG（Retrieval-Augmented Generation）= 检索增强生成&lt;br&gt;&#xA;简单说就是：先从你自己的文档里检索相关内容，再让大模型基于这些内容生成答案。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;这篇文章以「项目文档问答」为例，从零搭一个小 Demo。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-目标让大模型读得懂我们的项目文档&#34;&gt;1. 目标：让大模型「读得懂」我们的项目文档&lt;/h2&gt;&#xA;&lt;p&gt;设定目标：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;知识来源：代码仓库中的 README、设计文档、接口说明等；&lt;/li&gt;&#xA;&lt;li&gt;使用方式：在一个 Web 界面里提问，例如：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;「私募投资人小程序支持哪些登陆方式？」&lt;/li&gt;&#xA;&lt;li&gt;「电子合同模块的签署流程有哪些关键步骤？」&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;期望回答：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;基本准确；&lt;/li&gt;&#xA;&lt;li&gt;回答中能指出「来自哪份文档」。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;约束条件：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;不追求「端到端生产可用」，先搭一个可演示、可验证的 Demo；&lt;/li&gt;&#xA;&lt;li&gt;优先用云端 Embedding + 向量库，而不是自己训模型。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;2-文档准备与切分&#34;&gt;2. 文档准备与切分&lt;/h2&gt;&#xA;&lt;h3 id=&#34;21-文档来源&#34;&gt;2.1 文档来源&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Git 仓库中的 Markdown：&lt;code&gt;docs/&lt;/code&gt; 目录、各项目 README；&lt;/li&gt;&#xA;&lt;li&gt;内部 Wiki 导出的 HTML/Markdown；&lt;/li&gt;&#xA;&lt;li&gt;部分 API 文档（Swagger/OpenAPI 转文本）。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;统一先转成 Markdown/纯文本，方便处理。&lt;/p&gt;&#xA;&lt;h3 id=&#34;22-切分策略&#34;&gt;2.2 切分策略&lt;/h3&gt;&#xA;&lt;p&gt;RAG 很关键的一步是「chunking」，即把长文档切成小段。&lt;br&gt;&#xA;我们采用的是：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;按标题结构 + 字数混合切分&lt;/strong&gt;；&lt;/li&gt;&#xA;&lt;li&gt;每段控制在 300–600 字；&lt;/li&gt;&#xA;&lt;li&gt;保留上级标题用于提供上下文。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;示例结构：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;docId&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fund-investor-miniapp&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;docTitle&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;信e募投资人小程序技术方案&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;sectionPath&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2. 技术架构&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2.1 前端技术栈&amp;#34;&lt;/span&gt;],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;前端采用 Vue3 + uni-app...&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;index&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;12&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;经验：&lt;/p&gt;</description>
    </item>
    <item>
      <title>调用大模型 API 的几个最佳实践：重试、降级与审计</title>
      <link>http://localhost:1313/posts/2023-06-05-ai-api-best-practices/</link>
      <pubDate>Mon, 05 Jun 2023 00:00:00 +0000</pubDate><author>wuwenzen@outlook.com (wuwj)</author>
      <guid>http://localhost:1313/posts/2023-06-05-ai-api-best-practices/</guid>
      <description>&lt;p&gt;刚开始用大模型 API 时，大家一般关心的是：&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;这个模型效果好不好？回答聪不聪明？&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;但当你真的把它作为「线上能力」接入产品时，会发现很多工程问题：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;API 偶尔超时 / 报错怎么办？&lt;/li&gt;&#xA;&lt;li&gt;费用怎么控？&lt;/li&gt;&#xA;&lt;li&gt;返回内容里如果有敏感信息怎么办？&lt;/li&gt;&#xA;&lt;li&gt;出了问题，怎么排查某次请求？&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;这篇文章就是从这些「落地问题」出发，整理几条接入大模型 API 的最佳实践。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-超时与重试别把前端一直挂着&#34;&gt;1. 超时与重试：别把前端一直挂着&lt;/h2&gt;&#xA;&lt;h3 id=&#34;11-超时要有明确上限&#34;&gt;1.1 超时要有明确上限&lt;/h3&gt;&#xA;&lt;p&gt;大模型生成本身需要时间，如果不设超时，前端可能会一直转圈。&lt;br&gt;&#xA;我们一般做法：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;在 BFF / 中间层对每个调用设定超时时间（例如 10–15 秒）；&lt;/li&gt;&#xA;&lt;li&gt;超时后直接返回「超时错误」，由前端给出友好提示；&lt;/li&gt;&#xA;&lt;li&gt;前端也设置请求超时，避免被挂死。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;12-重试策略&#34;&gt;1.2 重试策略&lt;/h3&gt;&#xA;&lt;p&gt;常见错误类型：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;临时网络抖动；&lt;/li&gt;&#xA;&lt;li&gt;API 限流（429）；&lt;/li&gt;&#xA;&lt;li&gt;服务端偶发异常。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;对&lt;strong&gt;幂等请求&lt;/strong&gt;（比如生成建议文案），我们采用：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;指数退避重试&lt;/strong&gt;：例如最多重试 2 次，间隔 500ms / 1000ms；&lt;/li&gt;&#xA;&lt;li&gt;遇到某些错误码（如 4xx 中的参数错误）不重试。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;伪代码：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;callLLMWithRetry&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;payload&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;maxRetry&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;attempt&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;callLLM&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;payload&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;catch&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;e&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;any&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;isRetryableError&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;e&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;attempt&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;maxRetry&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;e&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;attempt&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sleep&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;attempt&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#xA;&lt;h2 id=&#34;2-降级模型不可用时要有备胎&#34;&gt;2. 降级：模型不可用时要有「备胎」&lt;/h2&gt;&#xA;&lt;p&gt;大模型 API 作为外部依赖，不可能 100% 可用。&lt;br&gt;&#xA;因此建议设计「降级方案」：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
