<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Zhang Zhemin</title>
    <description>The latest articles on DEV Community by Zhang Zhemin (@zhang_zhemin_22ab34ce2f74).</description>
    <link>https://dev.to/zhang_zhemin_22ab34ce2f74</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4123619%2Fe5cf79e4-f39b-4387-acc3-3da05f1dac46.png</url>
      <title>DEV Community: Zhang Zhemin</title>
      <link>https://dev.to/zhang_zhemin_22ab34ce2f74</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zhang_zhemin_22ab34ce2f74"/>
    <language>en</language>
    <item>
      <title>从 JS 宏到 WPS AI：高级软件工程师的文档自动化与插件开发实战指南</title>
      <dc:creator>Zhang Zhemin</dc:creator>
      <pubDate>Wed, 16 Sep 2026 07:15:22 +0000</pubDate>
      <link>https://dev.to/zhang_zhemin_22ab34ce2f74/cong-js-hong-dao-wps-aigao-ji-ruan-jian-gong-cheng-shi-de-wen-dang-zi-dong-hua-yu-cha-jian-kai-fa-shi-zhan-zhi-nan-4d9c</link>
      <guid>https://dev.to/zhang_zhemin_22ab34ce2f74/cong-js-hong-dao-wps-aigao-ji-ruan-jian-gong-cheng-shi-de-wen-dang-zi-dong-hua-yu-cha-jian-kai-fa-shi-zhan-zhi-nan-4d9c</guid>
      <description>&lt;h1&gt;
  
  
  从 JS 宏到 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; AI：高级软件工程师的文档自动化与插件开发实战指南
&lt;/h1&gt;

&lt;h2&gt;
  
  
  一、为什么文档自动化又回到了工程化视野
&lt;/h2&gt;

&lt;p&gt;过去十年，文档自动化常被简化为“写个宏”。但在真实企业环境里，需求早已从批量替换、格式统一，演进到数据驱动生成、流程编排、AI 辅助写作。作为高级软件工程师，我们需要的不是零散脚本，而是一套可维护、可测试、可分发的文档自动化体系。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 在这个场景里非常有代表性：它兼容主流 Office 格式，提供 JS 宏，也支持基于 Web 技术的加载项，并逐步融入 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; AI 能力。无论你从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 获取开发文档，还是完成 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt; 后本地调试，&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 都能覆盖从轻量宏到企业插件的完整路径。&lt;/p&gt;

&lt;h2&gt;
  
  
  二、JS 宏：最快进入 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 自动化的入口
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 的 JS 宏（常称 JSA）使用 JavaScript 语法操作文档对象模型。对于熟悉前端或 Node.js 的工程师，它比 VBA 更亲切。&lt;/p&gt;

&lt;p&gt;在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 中启用“开发工具”后，可以打开 JS 宏编辑器。下面是一个批量生成简报的示例：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;buildBrief&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ActiveDocument&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;InsertAfter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;项目简报&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;InsertAfter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;生成时间：&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;指标&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;数值&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;完成率&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;92%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JS 宏的优势是轻量、即时、无需打包。但它也有边界：难以做复杂 UI、难以版本管理、难以安全分发。因此，当脚本开始服务多个团队时，就应该考虑加载项。&lt;/p&gt;

&lt;h2&gt;
  
  
  三、从宏到加载项：&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 插件架构
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 加载项通常基于 HTML、CSS、JavaScript 构建，通过 manifest 描述功能入口、Ribbon 按钮和任务窗格。它更接近现代前端工程，可以接入 npm、TypeScript、构建工具和 CI/CD。&lt;/p&gt;

&lt;p&gt;一个简化 manifest 示例：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"doc-auto-plugin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"wps"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ribbon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"btnGenerate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"生成周报"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"onAction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"generateWeeklyReport"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"taskpane"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"taskpane.html"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;在任务窗格中，你可以通过 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 提供的 JSAPI 获取活动文档、选区、表格数据，也可以调用后端服务或 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; AI。&lt;/p&gt;

&lt;h2&gt;
  
  
  四、实战：周报自动生成插件
&lt;/h2&gt;

&lt;p&gt;假设我们有一个 Excel 数据源，需要生成 Word 周报，并附带 AI 摘要。推荐流程如下：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 查阅最新加载项文档和 API 变更。&lt;/li&gt;
&lt;li&gt;在测试机完成 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt;，安装与生产环境一致的版本。&lt;/li&gt;
&lt;li&gt;初始化前端项目：&lt;code&gt;npm init&lt;/code&gt;，引入 TypeScript 和打包工具。&lt;/li&gt;
&lt;li&gt;配置 manifest，注册 Ribbon 按钮与任务窗格。&lt;/li&gt;
&lt;li&gt;在任务窗格中读取 Excel 数据，生成 Word 内容。&lt;/li&gt;
&lt;li&gt;调用 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; AI 生成摘要、润色标题，并插入文档。&lt;/li&gt;
&lt;li&gt;导出 PDF，回传业务系统。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;核心代码可以抽象成服务层：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateWeeklyReport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;wps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;WpsApplication&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ActiveDocument&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Selection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TypeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;本周工作摘要&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TypeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;项目&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;进展&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;工程化重点不是这段代码本身，而是错误处理、日志、重试、数据校验和版本兼容。&lt;/p&gt;

&lt;h2&gt;
  
  
  五、接入 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; AI：让插件从规则走向智能
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; AI 能提供文本生成、摘要、翻译、润色等能力。对插件开发者而言，关键是把 AI 当成一个可能失败、可能延迟、需要降级的外部服务。&lt;/p&gt;

&lt;p&gt;一个典型封装：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;summarizeWithAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;请用三条要点总结以下周报内容：&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;text&lt;/span&gt;
  &lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;wps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;maxTokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[WPS](https://www.wps.com/) AI 调用失败&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AI 摘要暂不可用，请查看原文。&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;实际开发中，应加入超时、缓存、敏感信息过滤和人工确认。尤其是法务、财务文档，不能把未脱敏内容直接送出去。&lt;/p&gt;

&lt;h2&gt;
  
  
  六、调试、分发与维护
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 加载项可以在开发模式下加载本地目录，配合控制台和日志排查问题。发布时可以选择内网分发、离线安装包或加载项市场。&lt;/p&gt;

&lt;p&gt;维护清单：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;锁定 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; JSAPI 版本，记录兼容矩阵。&lt;/li&gt;
&lt;li&gt;为 manifest 和业务代码建立独立版本号。&lt;/li&gt;
&lt;li&gt;在 CI 中执行 lint、单元测试和打包。&lt;/li&gt;
&lt;li&gt;为 AI 调用增加开关，允许企业关闭外部模型。&lt;/li&gt;
&lt;li&gt;引导用户从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 获取正式版本，避免使用来路不明的 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt; 渠道。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  七、常见坑与最佳实践
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;不要频繁跨进程调用 JSAPI，尽量批量读写。&lt;/li&gt;
&lt;li&gt;宏中避免 &lt;code&gt;alert&lt;/code&gt; 阻塞，插件中避免同步长任务。&lt;/li&gt;
&lt;li&gt;文档对象操作前后要处理撤销栈和选区恢复。&lt;/li&gt;
&lt;li&gt;AI 输出必须校验，不能直接覆盖原文。&lt;/li&gt;
&lt;li&gt;对表格、页眉页脚、批注等对象分别测试。&lt;/li&gt;
&lt;li&gt;在企业环境里，优先从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 完成 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt; 和版本管理。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  八、结语
&lt;/h2&gt;

&lt;p&gt;从 JS 宏到 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 加载项，再到 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; AI，文档自动化的边界正在从“操作文档”扩展到“理解文档”。高级软件工程师的价值，不只是写出能跑的脚本，而是把脚本沉淀为可维护、可观测、可分发的产品能力。&lt;/p&gt;

&lt;p&gt;如果你准备开始，建议先从一个小型 JS 宏验证流程，再迁移到加载项；同时通过 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 获取权威资料，完成 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt; 并保持版本更新。这样，你就能在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 生态里构建真正可用的文档自动化与智能插件。&lt;/p&gt;

</description>
      <category>wpsai</category>
      <category>javascript</category>
      <category>documentautomation</category>
      <category>plugindevelopment</category>
    </item>
    <item>
      <title>软件工程师的 WPS 进阶指南：用 JS 宏、开放 API 与 AI 打造自动化办公流</title>
      <dc:creator>Zhang Zhemin</dc:creator>
      <pubDate>Wed, 16 Sep 2026 03:45:07 +0000</pubDate>
      <link>https://dev.to/zhang_zhemin_22ab34ce2f74/ruan-jian-gong-cheng-shi-de-wps-jin-jie-zhi-nan-yong-js-hong-kai-fang-api-yu-ai-da-zao-zi-dong-hua-ban-gong-liu-4olo</link>
      <guid>https://dev.to/zhang_zhemin_22ab34ce2f74/ruan-jian-gong-cheng-shi-de-wps-jin-jie-zhi-nan-yong-js-hong-kai-fang-api-yu-ai-da-zao-zi-dong-hua-ban-gong-liu-4olo</guid>
      <description>&lt;h1&gt;
  
  
  软件工程师的 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 进阶指南：用 JS 宏、开放 API 与 AI 打造自动化办公流
&lt;/h1&gt;

&lt;h2&gt;
  
  
  为什么软件工程师要关注 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 自动化
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 不只是文档编辑器。它提供 JS 宏、加载项、开放 API 等能力，能把重复的报表、合同、审批流自动化。先从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 了解版本与开放能力，再完成 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt;，开启开发工具。&lt;/p&gt;

&lt;h2&gt;
  
  
  一、环境准备：从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 到 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;访问 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt;，根据操作系统选择个人版或专业版，完成 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 中打开：工具 -&amp;gt; 开发工具 -&amp;gt; JS 宏。若没有该菜单，检查版本或安装宏插件。&lt;/li&gt;
&lt;li&gt;建议使用 Windows 版，JS 宏与 COM/加载项生态更完整。&lt;/li&gt;
&lt;li&gt;把宏代码导出为 .js 文件，用 Git 管理。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  二、JS 宏：用 JavaScript 操作表格与文档
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; JS 宏的 API 风格接近 VBA，但使用 JavaScript 语法。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ActiveDocument&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ActiveSheet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastRow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Cells&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nc"&gt;End&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xlUp&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;lastRow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Cells&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Value2&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Cells&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastRow&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Value2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;合计：&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;要点：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;用 try/catch 包住核心逻辑，避免宏中断。&lt;/li&gt;
&lt;li&gt;批量读写 Range，比逐单元格快。&lt;/li&gt;
&lt;li&gt;宏环境不一定支持浏览器 DOM，但通常有 fetch 或可与外部程序通信。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  三、开放 API：让 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 与业务系统对话
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放平台提供云文档、文件、协作等 REST API。典型流程：业务系统触发 -&amp;gt; 云函数 -&amp;gt; 调用 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; API -&amp;gt; 生成/更新文档 -&amp;gt; Webhook 回调。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createDoc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://open.wps.cn/api/v3/files&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bearer &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;自动化报告&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;doc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[WPS](https://www.wps.com/) API error: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;工程建议：鉴权信息放环境变量；对 429/5xx 做指数退避；写操作保证幂等。&lt;/p&gt;

&lt;h2&gt;
  
  
  四、AI 加持：摘要、分类与内容生成
&lt;/h2&gt;

&lt;p&gt;把 AI 服务封装成内部网关，再由 JS 宏或开放 API 调用。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;aiSummarize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://your-ai-gateway/summarize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;场景：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;批量读取表格评论，生成摘要并回写。&lt;/li&gt;
&lt;li&gt;根据工单内容自动分类，填充处理人。&lt;/li&gt;
&lt;li&gt;用 AI 生成公式、SQL、正则，再由人工确认。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;注意：敏感数据脱敏，权限最小化，保留审计日志。&lt;/p&gt;

&lt;h2&gt;
  
  
  五、实战：日报自动化流
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;定时任务从数据库/API 拉取数据。&lt;/li&gt;
&lt;li&gt;Node.js 清洗数据，计算指标。&lt;/li&gt;
&lt;li&gt;调用 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放 API 打开模板，替换占位符。&lt;/li&gt;
&lt;li&gt;导出 PDF，推送到企业微信/飞书。&lt;/li&gt;
&lt;li&gt;若在本地，可用 JS 宏读取 CSV，更新图表，再调用外部命令发送邮件。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  六、工程化清单
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;代码：模块化、配置与密钥分离、日志可追踪。&lt;/li&gt;
&lt;li&gt;版本：宏文件、模板、API 封装都进 Git。&lt;/li&gt;
&lt;li&gt;测试：mock &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; API，覆盖空数据、超长文本、异常状态码。&lt;/li&gt;
&lt;li&gt;安全：OAuth 最小权限，密钥轮换，审计导出。&lt;/li&gt;
&lt;li&gt;部署：&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 加载项、任务计划、云函数、容器。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  七、常见坑
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;JS 宏与浏览器 JS 不同：没有 window/document，要查 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 对象模型。&lt;/li&gt;
&lt;li&gt;异步支持因版本而异，必要时用轮询或外部服务。&lt;/li&gt;
&lt;li&gt;路径、编码、换行符在跨平台时容易出问题。&lt;/li&gt;
&lt;li&gt;开放 API 有频率限制，必须重试与降级。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  结语
&lt;/h2&gt;

&lt;p&gt;从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 获取最新文档，完成 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt;，先把一个重复流程宏化，再接入开放 API，最后用 AI 增强。&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 不只是办公软件，也可以成为软件工程师的自动化底座。&lt;/p&gt;

</description>
      <category>wpsautomation</category>
      <category>javascriptmacros</category>
      <category>openapi</category>
      <category>aiintegration</category>
    </item>
    <item>
      <title>用 WPS 开放 API + AI Agent 重写文档自动化：一名软件工程师的实战笔记</title>
      <dc:creator>Zhang Zhemin</dc:creator>
      <pubDate>Wed, 16 Sep 2026 02:05:19 +0000</pubDate>
      <link>https://dev.to/zhang_zhemin_22ab34ce2f74/yong-wps-kai-fang-api-ai-agent-zhong-xie-wen-dang-zi-dong-hua-ming-ruan-jian-gong-cheng-shi-de-shi-zhan-bi-ji-1737</link>
      <guid>https://dev.to/zhang_zhemin_22ab34ce2f74/yong-wps-kai-fang-api-ai-agent-zhong-xie-wen-dang-zi-dong-hua-ming-ruan-jian-gong-cheng-shi-de-shi-zhan-bi-ji-1737</guid>
      <description>&lt;h1&gt;
  
  
  用 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放 API + AI Agent 重写文档自动化：一名软件工程师的实战笔记
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. 背景：文档自动化为什么需要重写
&lt;/h2&gt;

&lt;p&gt;过去我们做文档自动化，套路通常是：找模板、复制、填字段、人工校验、导出 PDF、发邮件。模板一多，字段映射就散落在脚本和 Excel 里；格式一改，维护成本指数上升。&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放 API 的出现，让我们可以把“文档操作”从业务代码里抽离出来，交给稳定的文档服务；而 AI Agent 则负责理解自然语言任务、规划步骤、调用工具。两者结合，不是简单堆叠，而是把流程从“人驱动脚本”变成“Agent 编排、&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 执行、人只审核”。&lt;/p&gt;

&lt;h2&gt;
  
  
  2. 整体架构
&lt;/h2&gt;

&lt;p&gt;系统分四层：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;接入层：Webhook、定时任务、IM 消息、表单。&lt;/li&gt;
&lt;li&gt;Agent 层：LLM + 规划器 + 工具调用 + 记忆 + 规则校验。&lt;/li&gt;
&lt;li&gt;工具层：封装 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放 API，包括创建文档、替换书签/占位符、导出 PDF、设置权限、读取元数据。&lt;/li&gt;
&lt;li&gt;存储层：模板库、任务库、对象存储、审计日志。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;关键原则：不让 LLM 直接生成复杂文档 XML，而是让它输出结构化 JSON，由工具层调用 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放 API。这样可控、可测、可回滚。&lt;/p&gt;

&lt;h2&gt;
  
  
  3. 准备 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放平台环境
&lt;/h2&gt;

&lt;p&gt;先到 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 进入开放平台，注册开发者账号，创建应用，获取 App ID、App Secret 和回调地址。本地联调时，建议从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 或 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt; 页面安装最新版 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; Office，保证加载项、云文档和 API 版本一致。&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt; 要认准官方渠道，避免第三方安装包带来安全风险；&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 有完整的 API 文档、SDK、调试工具和错误码说明。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放 API 常见鉴权方式包括 OAuth2 和签名鉴权。生产环境要把 token 放密钥管理，不要硬编码。access_token 要缓存，并处理过期与刷新，避免并发刷新触发限流。&lt;/p&gt;

&lt;h2&gt;
  
  
  4. AI Agent 的角色
&lt;/h2&gt;

&lt;p&gt;Agent 的核心循环可以概括为：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;理解任务：例如“根据销售数据生成周报，套用公司模板，导出 PDF 并发给王经理”。&lt;/li&gt;
&lt;li&gt;规划步骤：取数、填模板、校验、导出、通知。&lt;/li&gt;
&lt;li&gt;调用工具：get_sales_data、wps_create_doc、wps_replace_placeholders、wps_export_pdf、send_message。&lt;/li&gt;
&lt;li&gt;自我反思：检查字段缺失、金额格式、日期范围、权限边界。&lt;/li&gt;
&lt;li&gt;输出结果：返回文档链接、PDF、审计记录。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;用 Function Calling 定义工具 schema，例如：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;wps_replace_placeholders&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;在 [WPS](https://www.wps.com/) 文档中替换占位符&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;parameters&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;properties&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;doc_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mapping&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;required&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;doc_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mapping&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;注意：工具描述要准确，参数校验要严格。LLM 可能编造模板 ID 或字段，工具层必须拒绝非法请求。&lt;/p&gt;

&lt;h2&gt;
  
  
  5. 调用 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放 API 的代码骨架
&lt;/h2&gt;

&lt;p&gt;下面是一段 Python 示例，展示认证、创建文档、替换占位符的骨架。实际路径、参数和鉴权方式以 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 开放平台文档为准。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;WPS&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;app_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;app_secret&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://open.wps.cn/api/v1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app_id&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app_secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app_secret&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/oauth/token&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app_secret&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app_secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;grant_type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;client_credentials&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;access_token&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;template_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_token&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/docs&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;template_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;template_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;doc_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;replace_placeholders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_token&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/docs/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;doc_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/replace&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mapping&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;这段代码的重点不是路径本身，而是分层：&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt;Client 只负责 HTTP 和鉴权，Agent 不直接拼请求。这样后期替换成 SDK 或调整 API 版本，改动面很小。&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Agent 编排伪代码
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;llm_plan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;args&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;wps_create_doc&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;doc_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;template_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;wps_replace_placeholders&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;wps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace_placeholders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;doc_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mapping&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;wps_export_pdf&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pdf_url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;export_pdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;doc_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;每一轮循环都要做三件事：参数校验、权限校验、审计记录。特别是权限，Agent 只能访问当前用户有权限的模板和文档。越权风险不能靠 prompt 解决，要靠工具层和鉴权系统。&lt;/p&gt;

&lt;h2&gt;
  
  
  7. 实战中踩过的坑
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;模板格式漂移：&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 模板里的书签被误删，替换失败。解决：模板版本化，替换前先校验书签清单。&lt;/li&gt;
&lt;li&gt;Token 并发刷新：多个任务同时刷新 token，触发限流。解决：单飞 + 分布式锁 + 提前刷新。&lt;/li&gt;
&lt;li&gt;大文档性能：一次替换上千字段很慢。解决：批量接口、分片、异步任务、进度回调。&lt;/li&gt;
&lt;li&gt;权限边界：Agent 不能越权访问文档。解决：最小权限、用户身份透传、操作审计。&lt;/li&gt;
&lt;li&gt;PDF 字体缺失：导出后排版变化。解决：服务端预装字体，或使用 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 推荐方案。&lt;/li&gt;
&lt;li&gt;错误码不透明：&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放 API 返回错误时，要记录 request_id，方便排查。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  8. 效果与总结
&lt;/h2&gt;

&lt;p&gt;重写后，周报生成从 30 分钟降到 2 分钟，人工只做审核；合同生成、发票整理也在复用同一套工具层。&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放 API 负责稳定的文档操作，AI Agent 负责灵活的任务理解与编排。建议从单一高频场景切入，先把工具层做稳，再让 Agent 逐步接管更多步骤。&lt;/p&gt;

&lt;p&gt;最后提醒：从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 获取最新 API 文档，从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt; 安装官方客户端联调。&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放 API + AI Agent 不是替代人，而是把工程师从重复劳动中解放出来。&lt;/p&gt;

</description>
      <category>wpsopenapi</category>
      <category>agents</category>
      <category>documentautomation</category>
      <category>workfloworchestration</category>
    </item>
    <item>
      <title>美图秀秀的 AIGC 工程化实战：端侧模型、实时滤镜与亿级图像架构拆解</title>
      <dc:creator>Zhang Zhemin</dc:creator>
      <pubDate>Tue, 15 Sep 2026 21:35:14 +0000</pubDate>
      <link>https://dev.to/zhang_zhemin_22ab34ce2f74/mei-tu-xiu-xiu-de-aigc-gong-cheng-hua-shi-zhan-duan-ce-mo-xing-shi-shi-lu-jing-yu-yi-ji-tu-xiang-jia-gou-chai-jie-2jmb</link>
      <guid>https://dev.to/zhang_zhemin_22ab34ce2f74/mei-tu-xiu-xiu-de-aigc-gong-cheng-hua-shi-zhan-duan-ce-mo-xing-shi-shi-lu-jing-yu-yi-ji-tu-xiang-jia-gou-chai-jie-2jmb</guid>
      <description>&lt;h1&gt;
  
  
  &lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;的 AIGC 工程化实战：端侧模型、实时滤镜与亿级图像架构拆解
&lt;/h1&gt;

&lt;h2&gt;
  
  
  一、背景：AIGC 进入影像生产系统
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;作为一款国民级影像应用，功能从基础修图、滤镜、拼图，演进到 AI 消除、AI 画质修复、AI 风格化、AI 扩图等 AIGC 能力。对用户而言，体验变化只是点一下就出图；对工程团队而言，背后是端侧推理、实时渲染、云端任务编排、海量图像存储分发的系统工程。用户从&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;获取安装包，完成&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;后，真正决定口碑的是首帧速度、滤镜跟手性、生成成功率和成本。&lt;/p&gt;

&lt;h2&gt;
  
  
  二、端侧模型：把 AIGC 放进手机
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. 端侧与云端的边界
&lt;/h3&gt;

&lt;p&gt;AIGC 模型参数量大，直接端侧推理不现实。工程上通常采用端云协同：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;端侧：人脸检测、关键点、分割、轻量超分、滤镜风格迁移、预处理与后处理。&lt;/li&gt;
&lt;li&gt;云端：大参扩散模型、复杂修复、高分辨率生成、批量任务。&lt;/li&gt;
&lt;li&gt;端侧还承担隐私敏感数据的本地处理，减少原始图像上传。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. 模型压缩与加速
&lt;/h3&gt;

&lt;p&gt;端侧模型需要经过剪枝、蒸馏、量化。INT8 量化是常见起点，部分算子用 FP16 保持画质。针对移动 GPU/NPU，还要做算子融合、内存复用、动态 shape 支持。推理框架可选 NCNN、MNN、TNN、ONNX Runtime Mobile，iOS 侧可走 Core ML 和 Metal Performance Shaders。模型包按设备能力分级：高端机预置大模型，中低端机懒加载小模型，甚至只保留云端兜底。&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 热更新与灰度
&lt;/h3&gt;

&lt;p&gt;模型不应绑定客户端版本。&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;可以通过配置中心下发模型版本、阈值和开关，结合用户分群做灰度。新模型先在小流量验证 PSNR、LPIPS、耗时、崩溃率，再全量。端侧缓存模型分片，支持断点续传，避免每次&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;更新都重新拉全量包。&lt;/p&gt;

&lt;h2&gt;
  
  
  三、实时滤镜：16 毫秒内的渲染管线
&lt;/h2&gt;

&lt;p&gt;实时滤镜是&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;的体验基本盘。相机预览通常要求 30fps 或 60fps，单帧预算约 33ms 或 16ms。渲染管线一般抽象为 DAG：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;纹理上传：相机 YUV 转 RGBA，使用 SurfaceTexture、CVPixelBuffer 或 Vulkan 外部纹理。&lt;/li&gt;
&lt;li&gt;基础调整：曝光、对比度、饱和度、色温，用 3D LUT 或矩阵运算。&lt;/li&gt;
&lt;li&gt;人脸驱动：检测关键点，生成网格，做局部变形、瘦脸、大眼。&lt;/li&gt;
&lt;li&gt;美颜磨皮：双边滤波、导向滤波、高反差保留，兼顾磨皮与质感。&lt;/li&gt;
&lt;li&gt;AI 滤镜：轻量风格化模型输出纹理，再与原始帧混合。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;性能关键点：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;全程 GPU，避免 CPU 与 GPU 频繁同步。&lt;/li&gt;
&lt;li&gt;FBO 双缓冲、纹理池、命令缓冲复用。&lt;/li&gt;
&lt;li&gt;Shader 合并，减少 render pass。&lt;/li&gt;
&lt;li&gt;根据设备分级降级：低端机减少 LUT 精度、关闭部分 AI 节点。&lt;/li&gt;
&lt;li&gt;丢帧时优先保预览流畅，后台线程补处理。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  四、亿级图像架构：上传、处理、分发
&lt;/h2&gt;

&lt;p&gt;当&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;日活达到亿级，图像架构要同时面对高并发上传、异步处理、低延迟分发。&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 上传与存储
&lt;/h3&gt;

&lt;p&gt;客户端上传前做压缩、旋转矫正、EXIF 清理。大图分片上传，支持断点续传和秒传。对象存储作为原图与结果图底座，元数据写入 MySQL/TiDB，热点元数据缓存到 Redis。冷热分层：近期活跃图片放标准存储，历史图片转低频或归档。&lt;/p&gt;

&lt;h3&gt;
  
  
  2. 异步处理
&lt;/h3&gt;

&lt;p&gt;上传完成后发消息到 Kafka，任务调度器消费并生成不同规格：缩略图、水印图、WebP/HEIF/AVIF、AI 处理图。GPU 推理集群以队列方式消费 AIGC 任务，按优先级和成本调度。失败任务重试，死信队列告警。&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 分发与边缘
&lt;/h3&gt;

&lt;p&gt;结果图通过 CDN 分发，边缘节点缓存热门图片。客户端根据网络、设备、屏幕密度请求合适尺寸与格式。签名 URL 控制访问，防盗链。对于 AI 生成结果，可先返回低清预览，再异步推送高清图，提升感知速度。&lt;/p&gt;

&lt;h2&gt;
  
  
  五、AIGC 工程化：从模型到产品
&lt;/h2&gt;

&lt;p&gt;AIGC 不是单模型，而是工作流：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompt/参数模板化，避免散落在客户端。&lt;/li&gt;
&lt;li&gt;工作流 DAG：检测、分割、修复、超分、融合，节点可插拔。&lt;/li&gt;
&lt;li&gt;模型服务化：Triton、TFServing 或自研推理服务，支持动态批处理、自动扩缩容。&lt;/li&gt;
&lt;li&gt;质量评估：离线指标加在线 A/B，关注生成成功率、耗时、留存、分享率。&lt;/li&gt;
&lt;li&gt;成本优化：Spot 实例、模型缓存、结果缓存、按需降级。&lt;/li&gt;
&lt;li&gt;安全合规：内容审核、隐私保护、数据加密、权限隔离。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  六、总结
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;的 AIGC 工程化，本质是端侧模型、实时渲染、云侧弹性架构和产品体验之间的平衡。端侧负责快与隐私，云端负责强与复杂，CDN 与存储负责规模化分发。用户从&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;了解能力，完成&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;后，感受到的是顺畅的滤镜、自然的 AI 修复和稳定的生成结果。这背后，是一整套面向亿级图像的工程系统在支撑。&lt;/p&gt;

</description>
      <category>aigcengineering</category>
      <category>ondeviceai</category>
      <category>realtimerendering</category>
      <category>largescaleimagearchitecture</category>
    </item>
    <item>
      <title>千万 DAU 下的端侧 AIGC：美图秀秀如何把图像大模型塞进手机并跑出极致性能？</title>
      <dc:creator>Zhang Zhemin</dc:creator>
      <pubDate>Tue, 15 Sep 2026 20:15:05 +0000</pubDate>
      <link>https://dev.to/zhang_zhemin_22ab34ce2f74/qian-mo-dau-xia-de-duan-ce-aigcmei-tu-xiu-xiu-ru-he-ba-tu-xiang-da-mo-xing-sai-jin-shou-ji-bing-pao-chu-ji-zhi-xing-neng--59on</link>
      <guid>https://dev.to/zhang_zhemin_22ab34ce2f74/qian-mo-dau-xia-de-duan-ce-aigcmei-tu-xiu-xiu-ru-he-ba-tu-xiang-da-mo-xing-sai-jin-shou-ji-bing-pao-chu-ji-zhi-xing-neng--59on</guid>
      <description>&lt;h1&gt;
  
  
  千万 DAU 下的端侧 AIGC：&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;如何把图像大模型塞进手机并跑出极致性能？
&lt;/h1&gt;

&lt;h2&gt;
  
  
  一、问题背景：千万 DAU 与端侧 AIGC 的碰撞
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;作为千万 DAU 级别的影像应用，用户对 AI 生成、AI 修图、AI 扩图、AI 写真等能力的需求持续增长。若全部依赖云端推理，带宽、算力成本和首屏延迟都会成为瓶颈；而端侧推理能带来隐私保护、离线可用、低延迟和更低的云端成本。用户通过&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;或应用商店完成&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;后，期待在手机上获得接近云端的生成质量。这要求工程团队把图像大模型塞进手机，并在碎片化硬件上跑出极致性能。&lt;/p&gt;

&lt;h2&gt;
  
  
  二、总体架构：端侧 AIGC 推理管线
&lt;/h2&gt;

&lt;p&gt;管线通常分为：输入预处理、条件编码、扩散/生成主干、后处理与显示。预处理包括人脸检测、分割、关键点、图像对齐；条件编码可能使用轻量文本编码器或图像编码器；生成主干采用 Latent Diffusion、GAN 或轻量 Transformer；后处理包括 VAE 解码、超分、色彩校正。端侧引擎需要管理模型仓库、硬件抽象层、调度器和内存池。针对不同设备，引擎会动态选择 CPU、GPU、NPU 或异构组合。&lt;/p&gt;

&lt;h2&gt;
  
  
  三、模型压缩：把大模型塞进手机
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;结构轻量化：使用 Latent Diffusion 降低分辨率，蒸馏 UNet，剪枝注意力头与通道，低秩分解卷积。对于人像、风格化等垂直场景，采用专用小模型替代通用大模型。&lt;/li&gt;
&lt;li&gt;步数蒸馏：通过 LCM、Turbo、一致性模型把采样步数从 50 步降到 4 到 8 步，显著降低计算量。&lt;/li&gt;
&lt;li&gt;量化：训练后量化与量化感知训练结合，权重 INT8/INT4，激活 INT8，敏感层保留 FP16。逐通道量化、混合精度、异常值裁剪，保证画质。&lt;/li&gt;
&lt;li&gt;权重压缩与分片：模型权重按需加载，使用 mmap 与差分更新，减少&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;包体积和内存占用。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  四、推理引擎：算子、内存与异构调度
&lt;/h2&gt;

&lt;p&gt;移动端推理引擎需要做图优化：常量折叠、算子融合、死代码消除、内存复用。卷积使用 Winograd、FFT、im2col+GEMM；注意力使用 FlashAttention 思路，分块计算 softmax，减少显存访问。内存方面，采用内存池、激活重计算、分阶段加载，避免 UNet 与 VAE 同时驻留。异构调度上，CPU 负责预处理与轻量算子，GPU/NPU 负责大矩阵乘与卷积，通过 Vulkan、Metal、OpenCL、NNAPI、Core ML 等后端接入。异步流水线与多队列可以隐藏数据传输开销。&lt;/p&gt;

&lt;h2&gt;
  
  
  五、性能极致优化：从首帧到温控
&lt;/h2&gt;

&lt;p&gt;首帧延迟和生成耗时是核心指标。优化手段包括：多线程绑核、算子级 profiling、动态分辨率、自适应步数、缓存常用中间特征。温控与功耗墙下，引擎会动态降频、降低分辨率或切换更小模型，保证不崩溃、不过热。端云协同也是策略：端侧快速预览，云端精修；或者低端机走云端，高端机走端侧。&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;版本迭代时，会通过灰度发布和 AB 实验验证不同机型的策略。&lt;/p&gt;

&lt;h2&gt;
  
  
  六、工程化与数据闭环
&lt;/h2&gt;

&lt;p&gt;千万 DAU 意味着设备分布极广。团队需要建立设备分级：高端 NPU、中端 GPU、低端 CPU。监控指标包括耗时、内存峰值、温度、崩溃率、生成成功率。模型热更新与差分下载降低&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;成本。隐私合规方面，端侧处理减少原始图像上传。数据闭环则通过脱敏反馈与人工评估持续优化模型和调度策略。&lt;/p&gt;

&lt;h2&gt;
  
  
  七、挑战与展望
&lt;/h2&gt;

&lt;p&gt;端侧 AIGC 仍面临内存墙、功耗墙、硬件碎片化和模型快速迭代等挑战。未来，随着 NPU 算力提升、量化与蒸馏技术成熟，手机端有望跑出更高质量的图像大模型。&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;这类千万 DAU 应用，将在&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;、&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;和端侧引擎之间形成完整技术闭环，把极致性能带给更多用户。&lt;/p&gt;

&lt;h2&gt;
  
  
  结语
&lt;/h2&gt;

&lt;p&gt;把图像大模型塞进手机，不是简单裁剪模型，而是模型、引擎、调度、功耗、体验的系统工程。&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;的实践表明，端侧 AIGC 可以在千万 DAU 下兼顾质量、速度与成本，成为移动影像的重要基础设施。&lt;/p&gt;

</description>
      <category>ondeviceai</category>
      <category>aigc</category>
      <category>modelcompression</category>
      <category>inferenceoptimization</category>
    </item>
    <item>
      <title>从 JS 宏到 AI Agent：软件工程师的 WPS 自动化实战指南</title>
      <dc:creator>Zhang Zhemin</dc:creator>
      <pubDate>Tue, 15 Sep 2026 09:15:21 +0000</pubDate>
      <link>https://dev.to/zhang_zhemin_22ab34ce2f74/cong-js-hong-dao-ai-agentruan-jian-gong-cheng-shi-de-wps-zi-dong-hua-shi-zhan-zhi-nan-20e7</link>
      <guid>https://dev.to/zhang_zhemin_22ab34ce2f74/cong-js-hong-dao-ai-agentruan-jian-gong-cheng-shi-de-wps-zi-dong-hua-shi-zhan-zhi-nan-20e7</guid>
      <description>&lt;h1&gt;
  
  
  从 JS 宏到 AI Agent：软件工程师的 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 自动化实战指南
&lt;/h1&gt;

&lt;h2&gt;
  
  
  为什么是 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 不只是办公套件，它的 JS 宏让前端/Node 工程师可以用熟悉的 JavaScript 做自动化。你可以从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 了解最新版，通过 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt; 安装。&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; JS 宏基础
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; JS 宏使用与 VBA 类似的对象模型，但语法是 JavaScript。下面示例把当前工作表数据读成二维数组：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ActiveSheet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;used&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UsedRange&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;used&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;used&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;used&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;这段代码把 UI 操作变成可复用逻辑，是自动化的第一步。&lt;/p&gt;

&lt;h2&gt;
  
  
  2. 从宏到自动化流水线
&lt;/h2&gt;

&lt;p&gt;一个可落地的流程通常分四层：触发层（按钮、定时、文件事件）、数据层（Range、CSV、API）、逻辑层（清洗、校验、汇总）、Agent 层（AI 决策与工具调用）。工程化建议：宏代码用 Git 管理；配置与代码分离；外部调用加超时、重试、幂等；批量处理时分批执行，避免阻塞 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; UI。&lt;/p&gt;

&lt;h2&gt;
  
  
  3. 接入 AI Agent 的模式
&lt;/h2&gt;

&lt;p&gt;常见有三种：宏内直连 LLM（快但密钥风险高）；宏调用本地 Agent 服务（推荐）；宏推送任务到队列，由 Agent 集群消费（适合大规模）。推荐模式中，&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 只负责采集和展示，Agent 负责鉴权、提示词、工具编排。下面是一个 Node.js Agent 服务示例：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/agent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;请分析表格并给出清洗建议：&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// 省略真实 LLM 调用&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;删除空行，统一日期格式&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Agent 已启动&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 宏可以通过 XMLHttpRequest 调用它：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;callAgent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ActiveSheet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;used&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UsedRange&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;used&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;used&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;used&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xhr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;XMLHttpRequest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:3000/agent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setRequestHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseText&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Agent 调用失败：&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;生产环境建议改为异步或外部进程，避免同步 XHR 卡住界面。&lt;/p&gt;

&lt;h2&gt;
  
  
  4. 安全与稳定性清单
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;不要在前端宏硬编码 API Key。&lt;/li&gt;
&lt;li&gt;从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 获取正版，通过 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt; 安装并保持更新。&lt;/li&gt;
&lt;li&gt;对 Agent 返回做 schema 校验，不直接执行未验证命令。&lt;/li&gt;
&lt;li&gt;设置超时、重试、熔断和审计日志。&lt;/li&gt;
&lt;li&gt;批量写入先备份，失败可回滚。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. 常见坑
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; JS 宏不是浏览器环境，没有 DOM；不同 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 版本 API 有差异；路径、编码、日期格式易出错；提示词要固定输出结构，减少解析失败。&lt;/p&gt;

&lt;h2&gt;
  
  
  总结
&lt;/h2&gt;

&lt;p&gt;从 JS 宏到 AI Agent，&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 可以成为自动化工作台。先用宏把重复操作数据化，再用 Agent 把数据变成决策和动作。建议从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt; 了解能力，通过 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt; 安装最新版，从读取表格、调用本地 Agent、写回结果这个小闭环开始。&lt;/p&gt;

</description>
      <category>wps</category>
      <category>javascript</category>
      <category>agents</category>
      <category>automation</category>
    </item>
    <item>
      <title>从美颜到 AIGC：美图秀秀端侧推理、GPU 渲染与亿级图像架构拆解</title>
      <dc:creator>Zhang Zhemin</dc:creator>
      <pubDate>Tue, 15 Sep 2026 06:35:22 +0000</pubDate>
      <link>https://dev.to/zhang_zhemin_22ab34ce2f74/cong-mei-yan-dao-aigcmei-tu-xiu-xiu-duan-ce-tui-li-gpu-xuan-ran-yu-yi-ji-tu-xiang-jia-gou-chai-jie-a30</link>
      <guid>https://dev.to/zhang_zhemin_22ab34ce2f74/cong-mei-yan-dao-aigcmei-tu-xiu-xiu-duan-ce-tui-li-gpu-xuan-ran-yu-yi-ji-tu-xiang-jia-gou-chai-jie-a30</guid>
      <description>&lt;h1&gt;
  
  
  从美颜到 AIGC：&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;端侧推理、GPU 渲染与亿级图像架构拆解
&lt;/h1&gt;

&lt;p&gt;从一键磨皮、滤镜到 AI 写真、文生图，&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;的产品形态经历了从图像处理工具到 AIGC 创作平台的跃迁。对高级软件工程师而言，这背后不是单点算法，而是端侧推理、GPU 渲染、云边协同、亿级图像存储与分发共同组成的系统工程。本文尝试从架构视角拆解&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;在美颜与 AIGC 场景下的关键技术取舍。若想了解版本能力与更新说明，可通过&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;查看；普通用户也可在官方渠道进行&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;，避免第三方包风险。&lt;/p&gt;

&lt;h2&gt;
  
  
  一、总体架构：端、边、云三层协同
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;的典型链路可以抽象为三层：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;端侧：相机采集、预览、编辑、端侧模型、GPU 渲染、编码与上传。&lt;/li&gt;
&lt;li&gt;边缘：CDN、边缘函数、图片压缩、鉴权、就近处理。&lt;/li&gt;
&lt;li&gt;云侧：对象存储、元数据、任务编排、AIGC 推理集群、审核与推荐。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;一条用户点击「AI 写真」的请求，通常包含：本地人脸检测 -&amp;gt; 质量校验 -&amp;gt; 图片上传 -&amp;gt; 云端任务入队 -&amp;gt; Diffusion 推理 -&amp;gt; 后处理 -&amp;gt; 回传 -&amp;gt; 端侧合成。预览阶段强调低延迟，成片阶段强调质量与一致性，因此端云协同是核心。&lt;/p&gt;

&lt;h2&gt;
  
  
  二、端侧推理：把模型塞进手机
&lt;/h2&gt;

&lt;p&gt;端侧推理的动机很直接：降低延迟、保护隐私、节省带宽、减少云 GPU 成本。&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;大量美颜能力必须在 16ms 到 33ms 内完成，否则预览会卡顿。&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 推理引擎抽象
&lt;/h3&gt;

&lt;p&gt;iOS 侧通常使用 Core ML、Metal Performance Shaders、BNNS；Android 侧使用 NNAPI、GPU Delegate、Vulkan Compute。为了跨端一致，常引入 MNN、NCNN、TNN、ONNX Runtime 等推理框架，并做统一算子注册与后端调度。&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 模型优化
&lt;/h3&gt;

&lt;p&gt;常见手段包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FP16/INT8 量化，配合校准集降低精度损失；&lt;/li&gt;
&lt;li&gt;通道剪枝与结构化稀疏；&lt;/li&gt;
&lt;li&gt;知识蒸馏，用大模型指导小模型；&lt;/li&gt;
&lt;li&gt;算子融合，减少 kernel launch 与显存读写；&lt;/li&gt;
&lt;li&gt;动态 shape 与内存池复用，降低峰值占用；&lt;/li&gt;
&lt;li&gt;首帧预热与缓存，避免用户首次进入卡顿。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.3 美颜模型组合
&lt;/h3&gt;

&lt;p&gt;美颜不是单个模型，而是流水线：人脸检测、关键点、姿态、皮肤分割、头发分割、牙齿分割、光照估计、风格判别。每个模型都要控制输入分辨率，例如检测用 320x320，分割用 256x256，关键点用 128x128，再通过 ROI 裁剪提升有效像素。&lt;/p&gt;

&lt;h3&gt;
  
  
  2.4 AIGC 端侧探索
&lt;/h3&gt;

&lt;p&gt;端侧 Diffusion 仍受算力与内存限制，但 LCM、Turbo、SDXL-Turbo 等少步采样让实时预览成为可能。常见策略是端侧跑低分辨率 latent 预览，云端跑高分辨率精修。LoRA 与 ControlNet 可按需下载，放入本地模型仓库，通过版本号与签名校验保证安全。&lt;/p&gt;

&lt;h2&gt;
  
  
  三、GPU 渲染：实时美颜的视觉管线
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;的预览体验高度依赖 GPU 渲染。典型管线为：相机纹理 -&amp;gt; 人脸网格 -&amp;gt; 美颜 Pass -&amp;gt; 滤镜 LUT -&amp;gt; 贴纸/文字 -&amp;gt; 合成输出。&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 多 Pass 渲染
&lt;/h3&gt;

&lt;p&gt;磨皮常用频率分离：低频层做平滑，高频层保留纹理。双边滤波、导向滤波、表面模糊都可在 fragment shader 中实现。为了性能，通常降分辨率处理低频，再与全分辨率高频合成。&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 颜色与 LUT
&lt;/h3&gt;

&lt;p&gt;滤镜常使用 3D LUT 纹理，在 shader 中做三线性插值。颜色空间要统一：采集可能是 sRGB，显示可能是 Display P3，离线导出可能是线性空间。错误的空间转换会导致肤色偏灰或过饱和。&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 与推理共享纹理
&lt;/h3&gt;

&lt;p&gt;在 iOS 上可用 Metal 纹理与 Core ML 共享，在 Android 上可用 EGL 图像与 GPU Delegate 互操作。共享纹理能避免 CPU 来回拷贝，显著降低延迟与功耗。&lt;/p&gt;

&lt;h3&gt;
  
  
  3.4 性能策略
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;动态分辨率：滑动时降分辨率，停止后升分辨率；&lt;/li&gt;
&lt;li&gt;按需渲染：静态画面降低帧率；&lt;/li&gt;
&lt;li&gt;三重缓冲与命令缓冲复用；&lt;/li&gt;
&lt;li&gt;离屏渲染缓存，避免重复计算；&lt;/li&gt;
&lt;li&gt;功耗监控，温度过高时降级效果。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  四、亿级图像架构：存储、处理与分发
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;面对的是亿级用户与海量图像，架构必须兼顾成本、弹性与稳定性。&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 上传与存储
&lt;/h3&gt;

&lt;p&gt;上传采用分片、断点续传、秒传与 MD5 校验。存储使用对象存储，多副本或纠删码，按冷热分层。原图、中间图、成片、缩略图分开存储，生命周期策略自动清理临时文件。&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 元数据与任务编排
&lt;/h3&gt;

&lt;p&gt;元数据包括用户 ID、设备、时间、地理位置、人脸聚类、标签、审核状态。任务编排常用 Kafka、RabbitMQ 或云消息队列，配合 DAG 工作流与 K8s 弹性伸缩。每个任务要有幂等键、重试策略、死信队列与限流。&lt;/p&gt;

&lt;h3&gt;
  
  
  4.3 编解码与 CDN
&lt;/h3&gt;

&lt;p&gt;端侧上传前可转 HEIF/AVIF/WebP，云端按需转码。缩略图采用渐进式 JPEG 或 WebP，首屏先模糊后清晰。CDN 通过边缘缓存、签名 URL、防盗链、动态加速降低源站压力。&lt;/p&gt;

&lt;h3&gt;
  
  
  4.4 内容审核与合规
&lt;/h3&gt;

&lt;p&gt;AIGC 与用户上传都必须经过多模态审核：图像分类、OCR、人脸比对、NSFW 检测。审核异步化，风险内容进入人工队列。隐私方面，端侧处理优先，云端数据加密，访问最小化。&lt;/p&gt;

&lt;h2&gt;
  
  
  五、AIGC 云侧推理：从模型到服务
&lt;/h2&gt;

&lt;p&gt;云侧 Diffusion 服务是重资产：GPU 池化、模型版本、LoRA 管理、ControlNet 插件、任务队列与配额。&lt;/p&gt;

&lt;h3&gt;
  
  
  5.1 推理优化
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;TensorRT、xFormers、FlashAttention 加速；&lt;/li&gt;
&lt;li&gt;FP16/INT8 量化与编译缓存；&lt;/li&gt;
&lt;li&gt;动态 batch 与连续 batching；&lt;/li&gt;
&lt;li&gt;显存池化与模型热切换；&lt;/li&gt;
&lt;li&gt;采样器优化，减少步数。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5.2 端云协同
&lt;/h3&gt;

&lt;p&gt;端侧负责 prompt 辅助、人脸安全、局部 mask 生成；云端负责高分辨率生成、inpainting、outpainting、风格迁移。回传后，端侧再用 GPU 渲染做融合与调色，保证所见即所得。&lt;/p&gt;

&lt;h2&gt;
  
  
  六、工程实践与稳定性
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;监控：端侧埋点采集推理耗时、GPU 耗时、内存峰值、崩溃率；云侧监控 QPS、P99、GPU 利用率、队列深度。&lt;/li&gt;
&lt;li&gt;灰度与 A/B：模型、滤镜、AIGC 模板都需灰度发布，支持快速回滚。&lt;/li&gt;
&lt;li&gt;降级：GPU 不可用时切换 CPU 或云端；云端排队过长时提示稍后重试。&lt;/li&gt;
&lt;li&gt;一致性：同一滤镜在 iOS、Android、Web 上需要颜色一致，通常通过 LUT 与色彩管理校准。&lt;/li&gt;
&lt;li&gt;安全：模型文件签名、HTTPS、证书绑定、代码混淆、风控。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  七、总结与展望
&lt;/h2&gt;

&lt;p&gt;从美颜到 AIGC，&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;的技术栈可以概括为：端侧推理保证实时与隐私，GPU 渲染保证视觉质量，云边协同保证弹性与规模，亿级图像架构保证成本与稳定。未来，随着神经渲染、3D 生成、实时 Diffusion 的发展，端侧与云侧的边界会继续变化。对工程师而言，核心仍是三个问题：延迟能否更低，画质能否更好，成本能否更优。想体验最新能力，建议通过&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;了解版本，并从官方渠道完成&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;。&lt;/p&gt;

</description>
      <category>ondeviceinference</category>
      <category>gpurendering</category>
      <category>aigc</category>
      <category>largescaleimagesystems</category>
    </item>
    <item>
      <title>WPS AI 插件开发实战：软件工程师如何从零接入大模型打造办公助手</title>
      <dc:creator>Zhang Zhemin</dc:creator>
      <pubDate>Tue, 15 Sep 2026 06:25:27 +0000</pubDate>
      <link>https://dev.to/zhang_zhemin_22ab34ce2f74/wps-ai-cha-jian-kai-fa-shi-zhan-ruan-jian-gong-cheng-shi-ru-he-cong-ling-jie-ru-da-mo-xing-da-zao-ban-gong-zhu-shou-326b</link>
      <guid>https://dev.to/zhang_zhemin_22ab34ce2f74/wps-ai-cha-jian-kai-fa-shi-zhan-ruan-jian-gong-cheng-shi-ru-he-cong-ling-jie-ru-da-mo-xing-da-zao-ban-gong-zhu-shou-326b</guid>
      <description>&lt;h1&gt;
  
  
  &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; AI 插件开发实战：软件工程师如何从零接入大模型打造办公助手
&lt;/h1&gt;

&lt;h2&gt;
  
  
  一、背景：为什么要做 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; AI 插件
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; Office 是国内使用最广泛的办公套件之一。很多团队每天在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 中写文档、做表格、整理 PPT。如果能让 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 直接调用大模型，就能实现摘要、润色、翻译、生成表格公式、自动写周报等能力。本文从软件工程师视角，带你从零开发一个 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; AI 插件。&lt;/p&gt;

&lt;p&gt;开始前，建议从 &lt;strong&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt;&lt;/strong&gt; 了解 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放平台与加载项文档，并通过 &lt;strong&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt;&lt;/strong&gt; 安装最新版 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; Office。开发插件需要 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 支持 JS 加载项。&lt;/p&gt;

&lt;h2&gt;
  
  
  二、整体架构
&lt;/h2&gt;

&lt;p&gt;一个典型的 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; AI 插件分为三层：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 加载项前端&lt;/strong&gt;：运行在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 任务窗格中，使用 HTML/CSS/JS，调用 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; JS API 读写文档。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;后端代理服务&lt;/strong&gt;：Node.js/Express 或 Serverless，负责保存大模型 API Key、转发请求、处理流式响应。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;大模型服务&lt;/strong&gt;：OpenAI、DeepSeek、通义千问、智谱等，提供 Chat Completions 接口。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;架构图：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+----------------+      +----------------+      +----------------+
| [WPS](https://www.wps.com/) 加载项前端 | ---&amp;gt; | 后端代理服务   | ---&amp;gt; | 大模型 API     |
| (任务窗格)     |      | (API Key 安全) |      | (LLM)          |
+----------------+      +----------------+      +----------------+
        |                        |
        v                        v
   [WPS](https://www.wps.com/) 文档读写              SSE 流式输出
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  三、环境准备
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;从 &lt;strong&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt;&lt;/strong&gt; 下载并安装 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; Office，或使用 &lt;strong&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt;&lt;/strong&gt; 获取最新版本。&lt;/li&gt;
&lt;li&gt;Node.js 18+&lt;/li&gt;
&lt;li&gt;npm 或 pnpm&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 加载项开发工具：&lt;code&gt;wpsjs&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;安装脚手架：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; wpsjs
wpsjs create wps-ai-assistant
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;目录结构大致如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wps-ai-assistant/
  ├── manifest.xml
  ├── index.html
  ├── main.js
  ├── style.css
  └── package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  四、配置 manifest.xml
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 加载项通过 &lt;code&gt;manifest.xml&lt;/code&gt; 描述插件信息、权限和入口地址。示例：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version='1.0' encoding='UTF-8'?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;OfficeApp&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;'http://schemas.microsoft.com/office/appforoffice/1.1'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Id&amp;gt;&lt;/span&gt;your-guid-here&lt;span class="nt"&gt;&amp;lt;/Id&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Version&amp;gt;&lt;/span&gt;1.0.0&lt;span class="nt"&gt;&amp;lt;/Version&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ProviderName&amp;gt;&lt;/span&gt;[WPS](https://www.wps.com/) AI Assistant&lt;span class="nt"&gt;&amp;lt;/ProviderName&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;DefaultLocale&amp;gt;&lt;/span&gt;zh-CN&lt;span class="nt"&gt;&amp;lt;/DefaultLocale&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;DisplayName&lt;/span&gt; &lt;span class="na"&gt;DefaultValue=&lt;/span&gt;&lt;span class="s"&gt;'[WPS](https://www.wps.com/) AI 助手'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Description&lt;/span&gt; &lt;span class="na"&gt;DefaultValue=&lt;/span&gt;&lt;span class="s"&gt;'在 [WPS](https://www.wps.com/) 中调用大模型完成写作、翻译、总结'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Hosts&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Host&lt;/span&gt; &lt;span class="na"&gt;Name=&lt;/span&gt;&lt;span class="s"&gt;'Document'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Host&lt;/span&gt; &lt;span class="na"&gt;Name=&lt;/span&gt;&lt;span class="s"&gt;'Workbook'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Host&lt;/span&gt; &lt;span class="na"&gt;Name=&lt;/span&gt;&lt;span class="s"&gt;'Presentation'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Hosts&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;DefaultSettings&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;SourceLocation&lt;/span&gt; &lt;span class="na"&gt;DefaultValue=&lt;/span&gt;&lt;span class="s"&gt;'http://localhost:3000/index.html'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/DefaultSettings&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Permissions&amp;gt;&lt;/span&gt;ReadWriteDocument&lt;span class="nt"&gt;&amp;lt;/Permissions&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/OfficeApp&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;注意：&lt;code&gt;SourceLocation&lt;/code&gt; 开发阶段可以指向本地服务，发布时改为 HTTPS 地址。&lt;/p&gt;

&lt;h2&gt;
  
  
  五、前端：读取 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 文档并调用大模型
&lt;/h2&gt;

&lt;p&gt;在 &lt;code&gt;index.html&lt;/code&gt; 中放置一个简单界面：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;'app'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;'summarize'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;总结选区&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;'polish'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;润色选区&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;'result'&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;'AI 输出...'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;'main.js'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;在 &lt;code&gt;main.js&lt;/code&gt; 中获取 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 文档选区。&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; JS API 与 Office JS 类似：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getSelectedText&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;wps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Selection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;replaceSelectedText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;wps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Selection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;绑定按钮事件：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;summarize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getSelectedText&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;callLLM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;请总结以下内容：&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;polish&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getSelectedText&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;callLLM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;请润色以下内容：&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;replaceSelectedText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  六、后端：安全接入大模型
&lt;/h2&gt;

&lt;p&gt;不要把 API Key 写在前端。推荐用 Node.js 代理：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/chat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.deepseek.com/chat/completions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LLM_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;deepseek-chat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
      &lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/event-stream&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[WPS](https://www.wps.com/) AI proxy running on 3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;前端调用：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;callLLM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000/api/chat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;如果要流式输出，可以使用 &lt;code&gt;EventSource&lt;/code&gt; 或 &lt;code&gt;fetch&lt;/code&gt; + &lt;code&gt;ReadableStream&lt;/code&gt;。&lt;/p&gt;

&lt;h2&gt;
  
  
  七、调试与发布
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;启动本地服务：&lt;code&gt;npm run dev&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 中打开开发工具，加载 &lt;code&gt;manifest.xml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 文档中选中文本，点击插件按钮测试&lt;/li&gt;
&lt;li&gt;发布前，将后端部署到 HTTPS 域名，并把 &lt;code&gt;SourceLocation&lt;/code&gt; 改为线上地址&lt;/li&gt;
&lt;li&gt;提交到 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放平台审核&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;如果你还没安装 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt;，可以前往 &lt;strong&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt;&lt;/strong&gt; 或通过 &lt;strong&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt;&lt;/strong&gt; 获取最新版 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; Office。&lt;/p&gt;

&lt;h2&gt;
  
  
  八、最佳实践与踩坑
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API Key 安全&lt;/strong&gt;：只放后端，使用环境变量。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;超时与重试&lt;/strong&gt;：大模型响应可能较慢，前端需要 loading 和超时提示。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;权限最小化&lt;/strong&gt;：只申请必要的 &lt;code&gt;ReadWriteDocument&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;流式体验&lt;/strong&gt;：长文本生成时使用 SSE，避免用户等待焦虑。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;文档兼容&lt;/strong&gt;：&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 文字、表格、演示的 API 有差异，需要分别测试。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;隐私合规&lt;/strong&gt;：不要将敏感文档内容上传到不可信模型，必要时做脱敏。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  九、总结
&lt;/h2&gt;

&lt;p&gt;通过 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 加载项 + 后端代理 + 大模型 API，软件工程师可以快速打造一个办公助手。它既能利用 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 的文档能力，又能发挥大模型的语义理解能力。建议从一个小场景开始，比如“总结选区”，再逐步扩展到润色、翻译、表格公式生成、PPT 大纲生成。开发前记得从 &lt;strong&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt;&lt;/strong&gt; 查阅最新文档，并通过 &lt;strong&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt;&lt;/strong&gt; 保持 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 版本更新。&lt;/p&gt;

&lt;p&gt;这样，你就完成了一个从零到一的 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; AI 插件。&lt;/p&gt;

</description>
      <category>wps</category>
      <category>aiplugin</category>
      <category>llm</category>
      <category>officeautomation</category>
    </item>
    <item>
      <title>WPS 开放平台实战：软件工程师如何用 JS 插件 + AI API 打造下一代办公自动化</title>
      <dc:creator>Zhang Zhemin</dc:creator>
      <pubDate>Tue, 15 Sep 2026 01:05:17 +0000</pubDate>
      <link>https://dev.to/zhang_zhemin_22ab34ce2f74/wps-kai-fang-ping-tai-shi-zhan-ruan-jian-gong-cheng-shi-ru-he-yong-js-cha-jian-ai-api-da-zao-xia-dai-ban-gong-zi-dong-hua-5c6a</link>
      <guid>https://dev.to/zhang_zhemin_22ab34ce2f74/wps-kai-fang-ping-tai-shi-zhan-ruan-jian-gong-cheng-shi-ru-he-yong-js-cha-jian-ai-api-da-zao-xia-dai-ban-gong-zi-dong-hua-5c6a</guid>
      <description>&lt;h1&gt;
  
  
  &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放平台实战：软件工程师如何用 JS 插件 + AI API 打造下一代办公自动化
&lt;/h1&gt;

&lt;p&gt;在生成式 AI 与办公套件深度融合的今天，软件工程师面对的不再只是 CRUD 和接口联调，而是如何把文档、表格、演示等高频场景变成可编程的自动化流水线。&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放平台提供了 JS 插件能力，结合 AI API，可以快速构建下一代办公自动化工具。本文从架构、开发、集成、安全与发布五个角度，给出一套可落地的实战方案。&lt;/p&gt;

&lt;h2&gt;
  
  
  一、为什么选择 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放平台
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; Office 拥有庞大的用户基础，&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 官网 提供了完整的开放平台文档、SDK 和插件调试工具。用户可以通过 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt; 获取最新客户端，开发者则可以在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 官网 申请开发者账号并创建插件项目。&lt;/p&gt;

&lt;p&gt;相比传统 VSTO 或 COM 加载项，&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; JS 插件具备跨平台、前端技术栈友好、迭代快等优势。你不需要深入 Win32 消息循环，也不需要维护复杂的 C++ 工程，只要熟悉 JavaScript、HTML、CSS，就能让插件运行在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 文字、表格、演示等组件中。&lt;/p&gt;

&lt;h2&gt;
  
  
  二、整体技术架构
&lt;/h2&gt;

&lt;p&gt;一套典型的 AI 办公自动化插件可以分为四层：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;交互层：&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 任务窗格、ribbon 按钮、右键菜单。&lt;/li&gt;
&lt;li&gt;文档层：通过 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; JS API 读取选区、段落、表格、工作表、幻灯片。&lt;/li&gt;
&lt;li&gt;AI 层：调用大模型 API，完成润色、总结、翻译、分类、抽取、生成。&lt;/li&gt;
&lt;li&gt;服务层：可选的后端代理，用于密钥管理、审计、缓存、限流。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;核心链路可以概括为：用户触发 -&amp;gt; 插件捕获上下文 -&amp;gt; 调用 AI API -&amp;gt; 解析结果 -&amp;gt; 回写 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 文档。&lt;/p&gt;

&lt;h2&gt;
  
  
  三、环境准备与插件初始化
&lt;/h2&gt;

&lt;p&gt;首先从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 官网 或可信渠道完成 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt;，安装最新版 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; Office。然后在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 官网 进入开放平台，创建 JS 插件项目，获取 App ID 和调试权限。&lt;/p&gt;

&lt;p&gt;如果使用官方脚手架，可以执行：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; wpsjs
wpsjs create ai-office-assistant
&lt;span class="nb"&gt;cd &lt;/span&gt;ai-office-assistant
wpsjs debug
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;插件清单通常放在 manifest 中。为了便于理解，这里用 JS 对象表示：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;manifest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ai-office-assistant&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wps&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;document.read&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;document.write&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;selection.read&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;权限原则是最小化申请。只读场景不要申请写入权限，避免审核受阻和用户顾虑。&lt;/p&gt;

&lt;h2&gt;
  
  
  四、&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; JS API 基础操作
&lt;/h2&gt;

&lt;p&gt;在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 文字中获取当前文档和选区：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;wps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;WpsApplication&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ActiveDocument&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Selection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectedText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;向文档插入内容：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;这里是 AI 生成的内容&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 表格中读取单元格：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ActiveSheet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Value2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 演示中遍历幻灯片：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;slides&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ActivePresentation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Slides&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;slides&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;slide&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;slides&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slide&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;这些 API 让插件可以精准获取办公上下文，而不是让用户复制粘贴。上下文越完整，AI 输出质量越高。&lt;/p&gt;

&lt;h2&gt;
  
  
  五、接入 AI API：润色、总结与结构化抽取
&lt;/h2&gt;

&lt;p&gt;下面实现一个选中文本润色函数。它通过后端代理调用大模型，避免在前端暴露 API Key：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;polishText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://your-proxy.example.com/ai/polish&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;如果直接在插件内调用模型 API，也要注意不要把密钥写入源码。更推荐的做法是：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;插件请求你的后端；&lt;/li&gt;
&lt;li&gt;后端完成鉴权、限流、日志和密钥注入；&lt;/li&gt;
&lt;li&gt;后端调用 AI API 并返回结构化结果。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;对于合同审查、周报生成、会议纪要等场景，可以设计统一的 prompt 模板：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promptTemplates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;polish&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;请润色以下文本，保持原意，输出中文。&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;请总结以下内容，输出三条要点。&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;请抽取人名、公司、金额、日期，返回 JSON。&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;拿到结果后，通过 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; JS API 回写：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;runPolish&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;wps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;WpsApplication&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Selection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;polished&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;polishText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;polished&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  六、典型自动化场景
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;智能合同审查：读取 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 文字中的条款，调用 AI 识别风险点，并用批注或高亮回写。&lt;/li&gt;
&lt;li&gt;周报自动生成：从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 表格中读取任务数据，生成周报草稿，再写入 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 文字。&lt;/li&gt;
&lt;li&gt;表格数据清洗：对地址、手机号、金额进行规范化，AI 负责模糊匹配，JS API 负责批量写入。&lt;/li&gt;
&lt;li&gt;PPT 大纲生成：根据文档内容生成幻灯片标题和要点，再通过演示 API 创建页面。&lt;/li&gt;
&lt;li&gt;多语言办公：选中段落一键翻译，保留术语表和格式。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这些场景的共同点是：&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 负责文档载体和用户入口，JS 插件负责上下文与操作，AI API 负责认知与生成。&lt;/p&gt;

&lt;h2&gt;
  
  
  七、安全、性能与工程化
&lt;/h2&gt;

&lt;p&gt;安全方面，务必遵循以下原则：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;不硬编码密钥，使用后端代理或临时令牌。&lt;/li&gt;
&lt;li&gt;对用户文档内容做脱敏和权限校验。&lt;/li&gt;
&lt;li&gt;为 AI 请求增加超时、重试和降级策略。&lt;/li&gt;
&lt;li&gt;记录审计日志，但避免记录敏感原文。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;性能方面，可以采用：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;批量读取选区，减少 API 往返。&lt;/li&gt;
&lt;li&gt;对长文档分段处理，使用流式响应或进度提示。&lt;/li&gt;
&lt;li&gt;对重复请求做缓存，例如相同段落不重复调用模型。&lt;/li&gt;
&lt;li&gt;将复杂逻辑放入 Web Worker，避免阻塞任务窗格。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;工程化方面，建议使用 TypeScript、ESLint、单元测试和 CI。发布前在多个 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 版本上回归，特别是 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 官网 提供的最新版和用户通过 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt; 安装的稳定版。&lt;/p&gt;

&lt;h2&gt;
  
  
  八、发布与分发
&lt;/h2&gt;

&lt;p&gt;完成开发和调试后，在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放平台提交插件审核。审核通过后，用户可以在 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 官网 的插件市场或应用中心安装。对于企业内部分发，也可以打包成私有插件，通过内部渠道让员工在完成 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt; 后一键安装。&lt;/p&gt;

&lt;p&gt;发布时注意：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;清晰描述插件权限和用途。&lt;/li&gt;
&lt;li&gt;提供隐私政策，说明文档内容如何处理。&lt;/li&gt;
&lt;li&gt;为 AI 调用失败提供友好提示和手动操作入口。&lt;/li&gt;
&lt;li&gt;保留版本升级和灰度发布能力。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  九、总结
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 开放平台让软件工程师可以用熟悉的 JS 技术栈进入办公自动化领域。通过 JS 插件捕获文档上下文，再结合 AI API 完成理解、生成和结构化处理，可以构建出润色、总结、审查、翻译、数据清洗等下一代办公自动化工具。建议从 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt; 官网 获取最新文档，通过 &lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt; 安装最新客户端，然后从一个最小可用插件开始，逐步迭代成完整的 AI 办公助手。&lt;/p&gt;

&lt;p&gt;关键词已覆盖：&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS&lt;/a&gt;、&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS下载&lt;/a&gt;、&lt;a href="https://www.wps.com/" rel="noopener noreferrer"&gt;WPS官网&lt;/a&gt;。&lt;/p&gt;

</description>
      <category>wps</category>
      <category>javascript</category>
      <category>ai</category>
      <category>officeautomation</category>
    </item>
    <item>
      <title>从一键美颜到端侧大模型：拆解美图秀秀的 AIGC 图像工程与亿级架构</title>
      <dc:creator>Zhang Zhemin</dc:creator>
      <pubDate>Mon, 14 Sep 2026 22:25:14 +0000</pubDate>
      <link>https://dev.to/zhang_zhemin_22ab34ce2f74/cong-jian-mei-yan-dao-duan-ce-da-mo-xing-chai-jie-mei-tu-xiu-xiu-de-aigc-tu-xiang-gong-cheng-yu-yi-ji-jia-gou-771</link>
      <guid>https://dev.to/zhang_zhemin_22ab34ce2f74/cong-jian-mei-yan-dao-duan-ce-da-mo-xing-chai-jie-mei-tu-xiu-xiu-de-aigc-tu-xiang-gong-cheng-yu-yi-ji-jia-gou-771</guid>
      <description>&lt;h1&gt;
  
  
  从一键美颜到端侧大模型：拆解&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;的 AIGC 图像工程与亿级架构
&lt;/h1&gt;

&lt;h2&gt;
  
  
  引言
&lt;/h2&gt;

&lt;p&gt;在移动影像赛道里，&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;是一个典型样本。用户从&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;了解版本能力，完成&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;后，第一眼看到的是“一键美颜”，但幕后已经演化为端侧大模型、云侧扩散模型、实时渲染和亿级服务治理的组合工程。本文从客户端管线、AIGC 推理、端侧部署和全球架构四个层面拆解。&lt;/p&gt;

&lt;h2&gt;
  
  
  一、一键美颜：实时图像管线
&lt;/h2&gt;

&lt;p&gt;一键美颜不是单一滤镜，而是一条低延迟流水线：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;采集层：Camera2/AVFoundation 输出 YUV 或纹理，按机型选择 30/60fps。&lt;/li&gt;
&lt;li&gt;检测层：人脸检测、关键点、语义分割、肤质区域。&lt;/li&gt;
&lt;li&gt;处理层：GPU Shader 做磨皮、祛痘、美白、瘦脸、大眼，CPU 做轻量逻辑。&lt;/li&gt;
&lt;li&gt;渲染层：离屏纹理、双缓冲、色彩管理，输出前做锐化与降噪。&lt;/li&gt;
&lt;li&gt;编码层：H.264/H.265 硬编，图片侧 WebP/HEIF/AVIF。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;工程重点是延迟与功耗。典型目标：预览 &amp;lt; 50ms，导出 &amp;lt; 2s，中低端机自动降级。&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;通过设备分级、能力探测、GPU/NPU 后端选择，把效果和性能做成可配置策略。&lt;/p&gt;

&lt;h2&gt;
  
  
  二、AIGC 图像工程：从滤镜到生成式编辑
&lt;/h2&gt;

&lt;p&gt;AIGC 能力包括 AI 消除、AI 扩图、AI 写真、文生图、图生图、局部重绘、风格化。链路一般分为：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;输入理解：人脸/人体/场景分割，深度、法线、边缘等控制条件。&lt;/li&gt;
&lt;li&gt;条件构造：Prompt、参考图、Mask、ControlNet、LoRA。&lt;/li&gt;
&lt;li&gt;安全审核：文本与图像审核，敏感内容拦截，版权与水印。&lt;/li&gt;
&lt;li&gt;模型路由：端侧轻量模型优先，云侧大模型兜底，按任务 SLA 路由。&lt;/li&gt;
&lt;li&gt;推理执行：Diffusion UNet + VAE，采样器与步数根据场景选择。&lt;/li&gt;
&lt;li&gt;后处理：超分、色彩对齐、融合、压缩与回传。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;云侧推理平台通常基于 Kubernetes + GPU 池化，推理引擎可选 TensorRT、ONNX Runtime、PyTorch。优化手段包括 FP16/INT8 量化、动态批、显存池、LoRA 热插拔、模型分片和请求排队。对亿级用户，冷启动和长尾模型必须做镜像预热与多级缓存。&lt;/p&gt;

&lt;h2&gt;
  
  
  三、端侧大模型：把生成能力放进手机
&lt;/h2&gt;

&lt;p&gt;端侧优势是隐私、延迟和离线可用。挑战是内存、算力、功耗。常见做法：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;模型压缩：剪枝、蒸馏、低秩分解，INT8/INT4 量化，混合精度。&lt;/li&gt;
&lt;li&gt;运行时：Core ML、NNAPI、Metal、Vulkan、MNN、TNN、ncnn。&lt;/li&gt;
&lt;li&gt;扩散加速：LCM、Turbo、少步采样、潜空间解码，轻量 UNet 与 VAE。&lt;/li&gt;
&lt;li&gt;内存治理：权重分页、算子融合、KV/特征缓存复用、峰值显存控制。&lt;/li&gt;
&lt;li&gt;热更新：按机型下发模型包，灰度验证，失败回滚。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;端侧大模型不会取代云侧，而是形成端云协同：人脸、分割、超分、风格化在端上完成；高分辨率生成、复杂 ControlNet 和大参数模型在云上完成。&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;的体验目标是在同一入口下，让用户无感切换。&lt;/p&gt;

&lt;h2&gt;
  
  
  四、亿级架构：云边端协同的底座
&lt;/h2&gt;

&lt;p&gt;面向亿级用户，架构需要同时处理高并发读、异步重任务和模型推理。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;接入层：CDN、边缘节点、API 网关、长连接、移动端重试。&lt;/li&gt;
&lt;li&gt;应用层：用户、素材、任务、社区、支付等微服务，按域拆分。&lt;/li&gt;
&lt;li&gt;异步层：Kafka/RocketMQ 解耦，任务状态机，Redis 记录进度。&lt;/li&gt;
&lt;li&gt;存储层：对象存储存原图与结果，CDN 回源，冷热分层，生命周期管理。&lt;/li&gt;
&lt;li&gt;推理层：GPU 队列、优先级、配额、弹性伸缩、模型仓库。&lt;/li&gt;
&lt;li&gt;可观测：Metrics、Tracing、Logging、告警、混沌工程与容量压测。&lt;/li&gt;
&lt;li&gt;安全：鉴权、限流、防刷、内容安全、水印与审计。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;对于图片上传下载，分片上传、断点续传、秒传和边缘压缩很关键。用户从&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;获取新版并完成&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;后，弱网下的首屏、素材加载和导出成功率直接影响留存。&lt;/p&gt;

&lt;h2&gt;
  
  
  五、性能、成本与体验平衡
&lt;/h2&gt;

&lt;p&gt;AIGC 图像工程是效果、延迟、成本的不可能三角。策略包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;端侧优先，云侧兜底；&lt;/li&gt;
&lt;li&gt;小图预览、大图导出，分级分辨率；&lt;/li&gt;
&lt;li&gt;模型缓存、结果缓存、素材缓存；&lt;/li&gt;
&lt;li&gt;动态批与错峰调度，闲时预计算；&lt;/li&gt;
&lt;li&gt;A/B 实验与质量打分，数据闭环迭代。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  六、结语
&lt;/h2&gt;

&lt;p&gt;从一键美颜到端侧大模型，&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;的演进是移动影像工程化的缩影。前端是用户从&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;了解能力、完成&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;后的即时体验，后端则是 AIGC 推理、端云协同和亿级架构的长期投入。未来，端侧多模态、个性化 LoRA 和 Agent 化编辑会继续推动这条管线进化。&lt;/p&gt;

</description>
      <category>aigc</category>
      <category>ondeviceai</category>
      <category>imageengineering</category>
      <category>billionscalearchitecture</category>
    </item>
    <item>
      <title>拆解美图秀秀：从端侧AI消除到实时GPU渲染，亿级图像应用如何扛住性能与体验</title>
      <dc:creator>Zhang Zhemin</dc:creator>
      <pubDate>Mon, 14 Sep 2026 18:25:22 +0000</pubDate>
      <link>https://dev.to/zhang_zhemin_22ab34ce2f74/chai-jie-mei-tu-xiu-xiu-cong-duan-ce-aixiao-chu-dao-shi-shi-gpuxuan-ran-yi-ji-tu-xiang-ying-yong-ru-he-kang-zhu-xing-neng-yu-ti-yan-8a9</link>
      <guid>https://dev.to/zhang_zhemin_22ab34ce2f74/chai-jie-mei-tu-xiu-xiu-cong-duan-ce-aixiao-chu-dao-shi-shi-gpuxuan-ran-yi-ji-tu-xiang-ying-yong-ru-he-kang-zhu-xing-neng-yu-ti-yan-8a9</guid>
      <description>&lt;h1&gt;
  
  
  拆解&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;：从端侧AI消除到实时GPU渲染，亿级图像应用如何扛住性能与体验
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;关键词：&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;、&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;、&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;、端侧 AI、GPU 渲染、性能优化&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  1. 亿级图像应用的技术底座
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;这类亿级图像应用，表面上是滤镜、美颜、消除、拼图等功能的集合，背后却是一套跨平台、端侧优先、实时渲染与 AI 推理并存的工程体系。用户从&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;安装包到打开相机预览，再到点击保存，每一个环节都在和性能、功耗、内存、发热做博弈。&lt;/p&gt;

&lt;p&gt;核心挑战可以概括为：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;设备碎片化&lt;/strong&gt;：Android 从低端到旗舰，芯片、GPU、NPU、系统版本差异巨大。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;实时性&lt;/strong&gt;：预览、美颜、AR 贴纸要求 30/60 FPS，端侧 AI 消除要求秒级返回。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;内存与功耗&lt;/strong&gt;：大图、多图层、模型常驻会快速推高内存和温度。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;隐私与合规&lt;/strong&gt;：人脸、照片属于敏感数据，端侧处理优先。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;体验一致性&lt;/strong&gt;：&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;提供的功能，在不同设备上要有可接受的效果差异。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. 端侧 AI 消除：从算法到落地
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1 任务定义
&lt;/h3&gt;

&lt;p&gt;AI 消除通常指用户涂抹或框选区域后，算法补全背景。技术上是 mask 引导的图像修复（inpainting）或对象移除（object removal）。输入是原图 + mask，输出是补全后的图像。&lt;/p&gt;

&lt;p&gt;难点在于：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;大图分辨率高，端侧内存有限。&lt;/li&gt;
&lt;li&gt;边缘融合要自然，不能有明显接缝。&lt;/li&gt;
&lt;li&gt;不同场景（人像、风景、文字）需要不同策略。&lt;/li&gt;
&lt;li&gt;低端机不能长时间阻塞 UI。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.2 模型选择与压缩
&lt;/h3&gt;

&lt;p&gt;端侧模型不能直接照搬服务端大模型。常见做法：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;轻量 backbone&lt;/strong&gt;：U-Net、MobileNet、ShuffleNet 等作为编码器。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;量化&lt;/strong&gt;：FP16 或 INT8，减少模型体积和内存带宽。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;剪枝&lt;/strong&gt;：去掉冗余通道，配合稀疏推理。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;知识蒸馏&lt;/strong&gt;：用大模型指导小模型，保留修复质量。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;分块推理&lt;/strong&gt;：将大图切成 tile，重叠区域做羽化融合。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.3 推理引擎与硬件加速
&lt;/h3&gt;

&lt;p&gt;跨平台推理框架可以选择 MNN、NCNN、ONNX Runtime、TFLite 等。Android 侧可接入 NNAPI、Vulkan、OpenCL；iOS 侧可接入 Core ML、Metal Performance Shaders。关键是把模型调度到最合适的后端：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 伪代码：端侧 AI 消除&lt;/span&gt;
&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;loadModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;inpaint_int8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mnn&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Tensor&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;preprocess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Tensor&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Image&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;postprocess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;工程上还要做：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;预处理和后处理 GPU 化，避免 CPU 与 GPU 频繁拷贝。&lt;/li&gt;
&lt;li&gt;模型预热，避免首次点击卡顿。&lt;/li&gt;
&lt;li&gt;失败降级：NPU 不可用时切 GPU，GPU 不可用时切 CPU 小模型。&lt;/li&gt;
&lt;li&gt;通过&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;或应用内更新下发模型，不影响主包体积。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.4 大图内存治理
&lt;/h3&gt;

&lt;p&gt;一张 4000x3000 的 ARGB 图片接近 48 MB，多图层后迅速破百 MB。优化手段包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;使用 RGBA8888 还是 RGB565，按场景降级。&lt;/li&gt;
&lt;li&gt;Bitmap 复用池，避免频繁分配。&lt;/li&gt;
&lt;li&gt;Native 内存管理，减少 Java 堆压力。&lt;/li&gt;
&lt;li&gt;分块加载，只保留当前视口和推理 tile。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. 实时 GPU 渲染：预览即所得
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1 渲染管线
&lt;/h3&gt;

&lt;p&gt;典型相机预览管线：&lt;/p&gt;

&lt;p&gt;相机采集 -&amp;gt; SurfaceTexture -&amp;gt; OES 纹理 -&amp;gt; 美颜 shader -&amp;gt; 滤镜 shader -&amp;gt; FBO -&amp;gt; 屏幕显示 / 编码保存&lt;/p&gt;

&lt;p&gt;Android 上常用 OpenGL ES 或 Vulkan，iOS 上用 Metal。核心原则是尽量让数据留在 GPU，减少 CPU 回读。&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 美颜、滤镜与形变
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;磨皮&lt;/strong&gt;：双边滤波、导向滤波或高反差保留，在 GPU 上做近似。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;肤色调整&lt;/strong&gt;：YCbCr 空间阈值 + 曲线映射。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;瘦脸大眼&lt;/strong&gt;：网格形变，顶点着色器或计算着色器完成。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;滤镜&lt;/strong&gt;：3D LUT 纹理，一次采样完成风格化。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;贴纸与 AR&lt;/strong&gt;：人脸关键点驱动，纹理绑定到网格。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.3 性能优化清单
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;优化项&lt;/th&gt;
&lt;th&gt;收益&lt;/th&gt;
&lt;th&gt;代价&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;降低预览分辨率&lt;/td&gt;
&lt;td&gt;显著降低 GPU 和带宽&lt;/td&gt;
&lt;td&gt;预览清晰度下降&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;可分离卷积&lt;/td&gt;
&lt;td&gt;高斯模糊从 O(n^2) 到 O(n)&lt;/td&gt;
&lt;td&gt;需要两次 pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FBO 复用&lt;/td&gt;
&lt;td&gt;减少分配和切换&lt;/td&gt;
&lt;td&gt;管理复杂度上升&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;纹理池&lt;/td&gt;
&lt;td&gt;减少 glGenTextures 抖动&lt;/td&gt;
&lt;td&gt;内存占用可控&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;动态帧率&lt;/td&gt;
&lt;td&gt;降低功耗和发热&lt;/td&gt;
&lt;td&gt;需要体验平衡&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;异步 PBO&lt;/td&gt;
&lt;td&gt;减少上传阻塞&lt;/td&gt;
&lt;td&gt;兼容性处理&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  4. 亿级应用的工程化架构
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1 分层与插件化
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;UI 层&lt;/strong&gt;：Android/iOS 原生，负责交互和系统能力。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;业务层&lt;/strong&gt;：编辑、相机、社区、保存等模块。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;引擎层&lt;/strong&gt;：C++ 跨平台图像引擎、AI 推理引擎、GPU 渲染引擎。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;基础层&lt;/strong&gt;：网络、存储、监控、日志、配置。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;插件化让&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;可以按需加载滤镜、贴纸、AI 能力，降低安装包体积，也方便通过&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;后的热更新。&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 线程模型
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;渲染线程：独占 GL 上下文，负责预览和导出。&lt;/li&gt;
&lt;li&gt;AI 线程：模型推理，避免阻塞渲染。&lt;/li&gt;
&lt;li&gt;IO 线程：图片解码、编码、文件读写。&lt;/li&gt;
&lt;li&gt;主线程：只做 UI 和状态同步。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;线程间通过任务队列和纹理共享同步，避免锁竞争。&lt;/p&gt;

&lt;h3&gt;
  
  
  4.3 监控与灰度
&lt;/h3&gt;

&lt;p&gt;亿级应用不能靠感觉优化。需要采集：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;帧率、掉帧率、首帧耗时。&lt;/li&gt;
&lt;li&gt;AI 推理耗时、成功率、内存峰值。&lt;/li&gt;
&lt;li&gt;崩溃、ANR、OOM。&lt;/li&gt;
&lt;li&gt;设备温度、功耗等级。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;通过 AB 实验和灰度发布，验证新模型、新 shader 对低端机的影响。&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;和官方渠道的版本更新，也需要配套的模型和素材分发策略。&lt;/p&gt;

&lt;h2&gt;
  
  
  5. 体验设计：从打开到保存
&lt;/h2&gt;

&lt;p&gt;用户对&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;的感知集中在几个瞬间：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;冷启动&lt;/strong&gt;：能否快速进入相机。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;首帧&lt;/strong&gt;：预览是否秒开。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;实时编辑&lt;/strong&gt;：滑动滤镜是否跟手。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI 消除&lt;/strong&gt;：点击后等待是否可接受。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;导出保存&lt;/strong&gt;：大图是否快速且不崩溃。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;对应策略：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;启动阶段延迟加载非必要模块。&lt;/li&gt;
&lt;li&gt;首帧使用低分辨率预览，稳定后提升。&lt;/li&gt;
&lt;li&gt;AI 消除显示进度和可取消。&lt;/li&gt;
&lt;li&gt;导出使用 GPU 编码和分块处理。&lt;/li&gt;
&lt;li&gt;低端机自动降级，高端机开启高画质。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. 未来：端侧生成式 AI 与神经渲染
&lt;/h2&gt;

&lt;p&gt;随着 NPU 算力提升，端侧 diffusion、Transformer 修复、神经渲染会逐渐进入&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;这类应用。挑战依然存在：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;模型更大，内存和功耗更敏感。&lt;/li&gt;
&lt;li&gt;实时性要求更高，需要算子融合和硬件定制。&lt;/li&gt;
&lt;li&gt;端云协同成为常态，简单任务端侧，复杂任务云侧兜底。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  结语
&lt;/h2&gt;

&lt;p&gt;拆解&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;，可以看到一个亿级图像应用的典型技术路径：端侧 AI 消除解决隐私和实时问题，GPU 渲染保证预览体验，工程化架构扛住设备碎片化和海量用户。对于开发者而言，无论是做&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;后的性能分析，还是参考&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;的能力设计，核心都是围绕性能、体验与成本做持续平衡。&lt;/p&gt;

</description>
      <category>ondeviceai</category>
      <category>gpurendering</category>
      <category>imageinpainting</category>
      <category>performanceoptimization</category>
    </item>
    <item>
      <title>软件工程师视角：美图秀秀如何把 AIGC 塞进手机——端侧推理、GPU 渲染与性能优化实战</title>
      <dc:creator>Zhang Zhemin</dc:creator>
      <pubDate>Mon, 14 Sep 2026 10:05:09 +0000</pubDate>
      <link>https://dev.to/zhang_zhemin_22ab34ce2f74/ruan-jian-gong-cheng-shi-shi-jiao-mei-tu-xiu-xiu-ru-he-ba-aigc-sai-jin-shou-ji-duan-ce-tui-li-gpu-xuan-ran-yu-xing-neng-you-hua-shi-zhan-4kll</link>
      <guid>https://dev.to/zhang_zhemin_22ab34ce2f74/ruan-jian-gong-cheng-shi-shi-jiao-mei-tu-xiu-xiu-ru-he-ba-aigc-sai-jin-shou-ji-duan-ce-tui-li-gpu-xuan-ran-yu-xing-neng-you-hua-shi-zhan-4kll</guid>
      <description>&lt;h1&gt;
  
  
  软件工程师视角：&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;如何把 AIGC 塞进手机——端侧推理、GPU 渲染与性能优化实战
&lt;/h1&gt;

&lt;p&gt;在移动端做 AIGC，难点从来不是“把模型跑起来”，而是“在用户可接受的延迟、发热和内存占用内稳定跑起来”。&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;作为一款高频影像应用，需要把 AI 消除、AI 扩图、AI 绘画、画质修复、智能抠图等能力塞进手机。用户看到的是点击后几秒内出图，工程师面对的却是模型体积、算子兼容、GPU 带宽、系统调度和功耗墙。本文以软件工程师视角，拆解端侧推理、GPU 渲染与性能优化的实战路径。若想了解版本与功能更新，可通过&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;查看说明，或在应用商店完成&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;。&lt;/p&gt;

&lt;h2&gt;
  
  
  1. 先定边界：哪些 AIGC 适合端侧
&lt;/h2&gt;

&lt;p&gt;端侧 AIGC 的第一原则是分层。不是所有任务都适合手机本地完成。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;强隐私、低延迟、轻量模型：智能抠图、人像修复、滤镜生成、局部消除，适合端侧。&lt;/li&gt;
&lt;li&gt;重生成、高分辨率、多步扩散：AI 绘画、AI 扩图、AI 写真，适合端云协同。&lt;/li&gt;
&lt;li&gt;交互式预览：端侧做低分辨率草稿，云端做最终精修。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;的工程策略通常是端侧优先、云端兜底：端侧负责实时反馈和隐私敏感数据，云端负责大模型重计算。这样既保证体验，也控制手机发热。&lt;/p&gt;

&lt;h2&gt;
  
  
  2. 端侧推理：把扩散模型压进手机
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1 模型小型化
&lt;/h3&gt;

&lt;p&gt;移动端不可能直接跑完整 Stable Diffusion。常见手段包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;剪枝：移除冗余通道和注意力头，降低 UNet 参数量。&lt;/li&gt;
&lt;li&gt;蒸馏：用大模型指导小模型，保留生成质量。&lt;/li&gt;
&lt;li&gt;量化：FP16 起步，进一步 INT8 分组量化，权重量化结合激活校准。&lt;/li&gt;
&lt;li&gt;少步采样：LCM、Turbo、DMD 等蒸馏采样，把 20 到 50 步压到 4 到 8 步。&lt;/li&gt;
&lt;li&gt;模块拆分：Text Encoder、UNet、VAE 分阶段加载，避免峰值内存叠加。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;对&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;这类应用，模型不是越小越好，而是要在目标机型上达到质量、速度、包体大小的平衡。&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 推理运行时选型
&lt;/h3&gt;

&lt;p&gt;iOS 侧通常组合 Core ML、Metal、MPSGraph 和 MPS。Core ML 负责图调度，Metal 负责自定义算子和后处理。Android 侧更碎片化，需要 NNAPI、Vulkan、OpenCL 以及芯片厂商 SDK 多路适配。&lt;/p&gt;

&lt;p&gt;关键设计：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;统一中间表示：将模型转换为内部 IR，再按设备能力下发。&lt;/li&gt;
&lt;li&gt;算子回退：NPU 不支持的算子回退到 GPU，GPU 不支持的回退到 CPU。&lt;/li&gt;
&lt;li&gt;异构调度：Text Encoder 跑 CPU/NPU，UNet 跑 GPU/NPU，VAE 解码跑 GPU。&lt;/li&gt;
&lt;li&gt;精度策略：优先 FP16，关键层保留 FP32，量化层单独校准。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.3 内存与算子优化
&lt;/h3&gt;

&lt;p&gt;手机内存带宽是稀缺资源。端侧推理常见优化：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;算子融合：Conv+BN+ReLU、Attention 中的 QKV 合并。&lt;/li&gt;
&lt;li&gt;内存池：预分配张量，复用中间激活，减少 malloc/free。&lt;/li&gt;
&lt;li&gt;分块推理：把大图切成 tile，降低单次显存峰值。&lt;/li&gt;
&lt;li&gt;KV Cache 与 Embedding 缓存：文本编码结果可复用，减少重复计算。&lt;/li&gt;
&lt;li&gt;动态 Shape：按输入分辨率选择不同计算图，避免固定大 Shape 浪费。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. GPU 渲染：生成结果如何实时上屏
&lt;/h2&gt;

&lt;p&gt;AIGC 不只是推理，渲染链路同样决定体验。&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;的 GPU 渲染通常覆盖：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;图像解码与颜色空间转换：YUV 到 RGBA，sRGB 与线性空间转换。&lt;/li&gt;
&lt;li&gt;纹理压缩：ASTC、ETC2，降低显存占用和带宽。&lt;/li&gt;
&lt;li&gt;Compute Shader：把超分、降噪、锐化、色彩映射放到 GPU。&lt;/li&gt;
&lt;li&gt;零拷贝：iOS 统一内存，Android 使用 HardwareBuffer、AHardwareBuffer、EGLImage。&lt;/li&gt;
&lt;li&gt;双缓冲/三缓冲：推理结果写入纹理，渲染线程异步消费，避免卡顿。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Metal 下可以用 MPSImage、MPSGraph 做卷积和后处理；Vulkan 下用 Compute Pipeline 和 Descriptor Set 管理纹理。核心是让推理和渲染流水线重叠，而不是串行等待。&lt;/p&gt;

&lt;h2&gt;
  
  
  4. 性能优化实战：从秒级到可接受
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1 时间线拆解
&lt;/h3&gt;

&lt;p&gt;一次端侧 AIGC 任务可以拆成：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;输入预处理：解码、裁剪、归一化。&lt;/li&gt;
&lt;li&gt;文本编码：Prompt 转 Embedding。&lt;/li&gt;
&lt;li&gt;扩散采样：多步 UNet 推理。&lt;/li&gt;
&lt;li&gt;VAE 解码：Latent 转像素。&lt;/li&gt;
&lt;li&gt;后处理：超分、美颜、合成。&lt;/li&gt;
&lt;li&gt;上屏：纹理渲染与合成。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;优化时要先测量，再优化。Perfetto、Xcode Instruments、Android GPU Inspector、Snapdragon Profiler 都是常用工具。&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 关键手段
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;缓存：Prompt Embedding、人脸特征、背景分割结果缓存。&lt;/li&gt;
&lt;li&gt;动态分辨率：预览低分辨率，导出高分辨率。&lt;/li&gt;
&lt;li&gt;分阶段执行：先出低清结果，再异步精修。&lt;/li&gt;
&lt;li&gt;线程模型：推理线程、渲染线程、IO 线程分离，使用无锁队列。&lt;/li&gt;
&lt;li&gt;热管理：监听温度与电量，动态降步数或降分辨率。&lt;/li&gt;
&lt;li&gt;功耗控制：限制 GPU 峰值频率，避免长时间满载。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.3 端云协同
&lt;/h3&gt;

&lt;p&gt;端侧负责低延迟和隐私，云端负责高质量生成。模型下发、灰度发布、AB 测试、失败降级都要工程化。&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;通常承担版本说明与能力介绍，&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;则来自官方渠道或应用商店，安装后可根据机型能力动态启用端侧 AIGC。&lt;/p&gt;

&lt;h2&gt;
  
  
  5. 工程化落地建议
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;设备分级：按芯片、内存、GPU 能力分档，不同档位使用不同模型。&lt;/li&gt;
&lt;li&gt;模型热更新：端侧模型可独立下发，避免频繁发版。&lt;/li&gt;
&lt;li&gt;质量监控：埋点采集耗时、失败率、发热、内存峰值。&lt;/li&gt;
&lt;li&gt;隐私合规：端侧处理敏感图像，云端传输需脱敏与授权。&lt;/li&gt;
&lt;li&gt;降级策略：端侧失败自动切云端，云端失败返回基础滤镜。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. 总结
&lt;/h2&gt;

&lt;p&gt;把 AIGC 塞进手机，本质是把一个大模型系统拆成可调度、可量化、可渲染、可降级的工程管线。&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀&lt;/a&gt;这类产品的竞争力，不只在于模型效果，更在于端侧推理运行时、GPU 渲染管线和性能优化细节。对软件工程师来说，端侧 AIGC 是一个横跨算法、框架、图形和系统调度的综合战场。想体验最新能力，可以通过&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀官网&lt;/a&gt;了解版本，再完成&lt;a href="https://pc.meitu.com/" rel="noopener noreferrer"&gt;美图秀秀下载&lt;/a&gt;。&lt;/p&gt;

</description>
      <category>mobileaigc</category>
      <category>ondeviceinference</category>
      <category>gpurendering</category>
      <category>performanceoptimization</category>
    </item>
  </channel>
</rss>
