> ## 文章索引
> 在这里获取全部文章的索引：https://lrd.im/blog/llms.txt
> 这是 lrd.im 的个人博客，记录设计、技术与思考。

# 记录一次 AIGC Hackathon 参赛经历和收获

![封面图](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2023-05-28/01.png 'AIGC Hackathon 主题海报，由公司品牌设计师陶老师和 Stable Diffusion 的共同创作')

公司在 5 月上旬的时候举办了一场 AIGC Hackathon 比赛，鼓励内部员工基于公司相关业务，利用 AI 技术进行创作，重塑生产力。

这么有意思的活动我当然也要掺一脚，在同事的怂恿和牵线之下，召集到了另一位设计师，以及一位研发大佬。所以加上我总共是 3 个人，2 个设计，1 个研发。但是严格来说应该是 1.5 个设计，1.5 个研发。因为我会参与到前端界面的实现，这也是我想参与这次活动的其中一个主要原因。

先放上我们开发的小工具的最终效果，其实是通过提前录入 SQL 语句规则，然后用自然语言询问 AI，让 AI 帮忙生成一个可用的 SQL 语句：

<video alt="演示了使用 SQL-Helper 的流程。过程是进入 ONES 系统之后，点击右下角经过设计的以蓝色为主色的小图标，打开了一个悬浮窗。在悬浮窗内输入并发送一段文本，稍等片刻后 AI 回复了一段文本，将其关键内容复制并粘贴到 SQL 规则表单当中，点击“应用”，此时界面展示出与该 SQL 规则相对应的数据。" src="https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2023-05-28/12.mp4">

## 过程

#### 想法

因为当前我们公司的业务是研发管理平台，所以我想到能通过 AI 帮助我们的主要是提高效率，减少出错，诸如此类的方向。

尤其是我在刚来到公司的时候有一段时间给我学习体验公司产品。中途就看到有个地方生成图表的话，可以选择各种筛选条件，也能用 SQL 来快速筛选，当时我就觉得如果用 SQL 来筛选会比手动一个个条件添加来的快，但我又不会写 SQL 语句，所以就想到一个主题：「输入自然语言，通过 AI 生成一段 SQL 语句」，产品名称就被定为「SQL-Helper」。

最开始我们讨论到有几种实现方式：

1. 产品原生：在公司的产品中搭建一个开发环境，在里面进行对话交互功能的设计和开发。
1. 外部网页：搭建一个网页，在网页里实现对话。
2. 谷歌插件（Popup）：在浏览器右上角上添加一个 Popup 入口，点击后打开一个浏览器提供的容器，在上面进行对话交互。
3. 谷歌插件（嵌入网页）：在公司的产品当中嵌入一个小卡片，在上面实现对话和配置等，会遮盖部分网页内容。

![技术架构选型思维导图：三条路径中，基于标品本地开发和 SSR Vercel 部署均因协作难或体验差被弃用；Chrome 插件中 Popup 体验不佳被弃用，最终选定 Contents Script 方案。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2023-05-28/02.png '')

最终选择了 **谷歌插件（嵌入网页）** 的方式，因为这样算是能比较融入到产品当中去，不需要来回切换网页这么麻烦，毕竟是一个对话的产品。而且 Popup 有一个致命问题是，如果鼠标点击到了网页的任何地方，Popup 就会收起，这种体验不适合用在聊天式的产品当中。而直接基于公司产品的开发环境中进行开发，这种做法成本比较大而且难以协作，毕竟团队中只有一个正经的研发。

#### 团队合作

得益于大佬的用爱发电，他花了一个休息日的时间把架子搭起来了，技术栈是：

- React
- Ant Design Manifest V3（支持 Chrome 96）
- Stylus 样式结构支持

最初搭建好的框架。是能够在网页中嵌入一个按钮，点击后打开一个弹窗：

![最初搭建好的框架。图片展示了一个浏览器右下角有一个橙色的沙漏图标，点击后会打开一个出现在屏幕中央的弹窗。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2023-05-28/03.png '')

这两个地方就是我们作品的主要载体。我们希望点击悬浮窗之后能打开一个聊天小窗口，能在里面填入 SQL 语句相关的 Key 和 Value，然后填入用户的 API Key，并实现与 AI 实时对话。

所以很快，在第一天的时候我们就有了一个大概的原型，中途通过每日下班前的简短碰面来一起决定增加/减少哪些内容。

![最开始的原型。在 Figma 中进行的，由方框和简单文案组成的原型图。分为消息模块和配置模块，每个模块的原型图下方列举了一些必做的功能清单。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2023-05-28/04.png '')

然后也确定了我们三人小组的分工：

- 我：前期负责设计界面、实现静态界面。后期参与 Prompt 调试。
- 另一个设计师：负责界面设计、图标设计、PPT 制作/包装。
- 研发大佬：负责功能实现，比如表单提交，发送和接收消息，接口调试等。

然后我们就各司其职，我这边按照大佬给的流程，每天把自己做好的部分提交 Pull requests，并标记清楚完成了哪部分，哪部分的功能需要研发大佬来实现等等。

![Github 仓库的 Pull requests 截图。展示了 SQL-Helper 仓库中部分 Pull requests 记录，并且用带有圆角的绿色方框高亮由我提交的部分 Pull requests。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2023-05-28/05.png '')

整体的时间表如下图（只有五个工作日，时间紧迫。）：

![项目时间安排表：5 月 6 日至 12 日，共 5 天工作日。三名成员分工明确：研发负责接口封装与调试，我负责插件 UI 与聊天界面，另一名设计师负责界面设计、画饼 PPT 与 Logo 制作，最终 DDL 为 5 月 12 日。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2023-05-28/06.png '')

## 一些细节

### 初试 Ant Design 的感受

平常在设计稿中使用基于 Ant Design 组件的经验有很多，但是自己亲自在代码里使用该组件还是第一次。

一个强烈的感受是，Ant Design 组件库确实很丰富，很多常用的组件都有封装好，主题色更改的功能也很强大。但是想要基于 Ant Design 组件库来做一些客制化的改动，实在是太费劲了（也可能是因为我太菜...）。

比如当时我想实现一个 `TextArea` 根据容器高度来自动填满高度的话，我的样式代码是如此之多：

![VS Code 编辑器截图，展示为使 TextArea 组件自适应容器高度所需的大量 CSS 代码，包括对 textarea 及多层嵌套的 Ant Design 表单类（.ant-form-item-row、.ant-form-item-control 等）逐级设置 height: 100%。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2023-05-28/07.png '')

另一个坑是我们的聊天窗口是嵌入到网站当中的，而且原本我们公司的产品也是基于 Ant Design 组件库搭建的，所以会出现很多样式的冲突。

比如我在自己的界面中使用了 Button 组件，而被嵌入的网站中如果也用了 Button 组件，那么样式将会被原本网页覆盖掉。

如果在这种情况下想要自定义样式，需要在 CSS 中通过多种手段来提升样式的优先级。这里是我比较频繁用到的两个提高优先级的方法：

- 使用选择器提高 Class 的优先级
- 使用 `!important`

![VS Code 中的 Stylus 样式代码截图，展示两种提升 CSS 优先级的方法：使用 `div.P-configuration, div.P-chat` 选择器提升优先级，以及在 `padding: basePadding` 后添加 `!important` 强制提升优先级。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2023-05-28/08.png '')

> CSS 选择器的优先级相关内容可以参考张鑫旭大神的名著[《CSS选择器世界》](https://www.zhangxinxu.com/wordpress/2019/10/book-css-selector-world/)，写得特别详细。

所以后面回想起来，我在改造 Ant Design 组件库花的时间还是太多了。这个组件库可能在做复杂后台的时候好用，但在做这种小应用，发挥创意的地方，我觉得还限制还是太多了。我觉得我们最开始应该选择使用有更高扩展性的组件库，比如前段时间看到的 [Radix UI](https://www.radix-ui.com/)。

从文档来看，Radix UI 会组件里面每个 DOM 都提前命名好相关的 ClassName，那么用户在想自定义样式的时候，就方便很多了。

![Radix UI 组件库的截图。展示了 Alert Dialog 组件的代码，并且用带有圆角的绿色方框高亮了代码中的四处 className。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2023-05-28/09.png '')

对比起 Ant Design，引用一个组件进来后，会生成巨多个没有打标记的 DOM。每个 DOM 的样式巨难选择，想要改组件内某个元素的样式，没有熟练的 CSS 选择器功夫还真搞不定。

但还是得具体试一试才知道 Radix UI 是不是真的好用，或许也会暗藏某些坑。或许我应该拿自己的个人网站来试一试 🤔。

### 改造弹窗：拖拽和操作

由于这是一个嵌入在网页当中的对话窗口，本着提高一个易用性的初心，我觉得需要对弹窗组件进行**魔改**，支持以下两种特点：

- 支持拖拽：允许用户拖拽弹窗标题区域，改变弹窗的位置，以免挡住原本页面中的元素。
- 移除遮罩：不展示弹窗背后的黑色遮罩，并且弹窗出现的时候，不影响用户操作原本的网页。

仅仅是改造弹窗这块，足足花了我一天。严重影响了我调试 Prompt 的时间，所以感觉很有必要把它记录下来，即便我的做法绝非最佳实践。

#### 拖拽

拖拽这块我是用了一个名为 [DragM](https://www.npmjs.com/package/dragm) 的开源库来实现了，因为看到示例里面效果很不错，所以直接用上了。效果确实也很不错，强烈推荐。

过程有点丢人，就不详细描述了。大概是我参照示例代码，花了很多时间和尝试，做到了弹窗能够实现拖拽的效果。但弹窗的关闭按钮却失效了，后面还是得靠研发大佬来修复。

#### 允许操作背景

这个特点的实现简直是噩梦。Ant Design 文档是提供了一个 API 是能够允许我们隐藏掉黑色的遮罩。

![Ant Design Modal 组件的 API 截图。用带有圆角的绿色边框高亮 Ant Design Modal的 API。该 API 控制是否展示 Mask，默认是展示的。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2023-05-28/10.png '')

但是这只是让我们看不见遮罩，打开弹窗时，原本页面的元素仍然是无法点击的。所以我试了一些方法，比如说将每一个疑似是遮罩的 DOM 设置为 `display: none;`，然而并不奏效。

最后生效的方法是用 CSS 选择器选中遮罩层，并将其调整为跟弹窗一样大。那么实际上遮罩还是存在的，但已经被修改为和弹窗一样大，并且叠在弹窗的后面，其实谁都感知不到这个透明遮罩的存在。

所以对于弹窗尺寸以外的部分，是没有被遮罩所覆盖的，自然能够正常响应鼠标操作。

<video alt="鼠标点击后面的元素示意图。展示了打开 SQL-Helper 之后，仍然能在原本页面中操作原有控件。比如：打开弹窗或者打开下拉菜单）。" src="https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2023-05-28/11.mp4">

这种做法无法适应弹窗高度会动态变化的情况，但我们这次设计的产品中，弹窗的宽高是固定的，所以即便做法比较不成熟，但确实是达到效果了。

## 结果

比赛最终有点遗憾，距离拿奖仅一步之遥。获得我们组目标奖项的是一个单人成组的高手。

很可惜的是我们就差一点点，因为最后颁奖的时候大佬也提到了我们的作品，说是如果能更好用一些，比如将生成的 SQL 语句自动填进输入框，或者自动应用然后直接生成图表，就有更大的机会获奖了🤦。

确实我们在演示的时候没有将这个这个产品最强大的功能发挥出来。因为本身产品也有些缺陷，限制了我们的演示范围。

最开始我们设想是演示的时候用自然语言多问几个问题，然后 AI 每次回复都很准确，凸显了自然语言生成 SQL 语句的便利性，而且还想演示输入了几个错别字，AI 仍然能够正确地识别我们的意图，回复正确的 SQL 语句。

但实际上我们最终的产品还是有一个明显的 BUG，在连续聊天时，消息队列不正常，AI有时候会回复我问的上上一个问题，而不是紧接着我的提问来进行回答。

这使得我们演示的时候只能问一个问题，简单带过，没有办法将自然语言带来的便捷性完全地展现出来，实属遗憾。

## 收获

虽然没能获奖，但参与这次公司内部的 AIGC Hackathon 比赛对我来说有三个特别重要的收获。

### 参赛经验

简单来说就是产品设计和功能开发的边界，需要根据演示需要来进行规划。

之前我在样式实现中花了太多时间（职业病🤦），比如输入框的聚焦效果，聊天气泡出现的动画，发送消息加载中的动画等等，而实际上在演示的时候，这些可能只展示了 1～2 秒，甚至更少。

因为这些内容大概率不会是评委所在意的东西，反而在过程中怎么调试 Prompt，调试过程中遇到什么挑战，怎么解决，怎么选择模型等等，显得团队很沉浸于与 AI 接口进行交互，通过这个项目积累了挺多经验，可能这些才是大佬们有兴趣了解的地方。

我应该早点完成产品界面还原，然后尽快投入到调试 Prompt 当中的。如果之后再次参与类似的活动，我觉得我的所有工作都会围绕最后一天的演示来进行，其他东西能减就减。

### 首次参与代码 PR，并且与真正的研发同事合作

这次是我第一次将代码 PR 到其他成员的仓库当中，并且解决代码冲突，编写改动点，同步最新代码等等。这种团队协作的感觉，让作为设计师的我感觉很新鲜和奇妙。

而且各司其职，每个人都做出了超出自己以往经历的内容，然后每天短会同步下今天的进度、明天的工作内容。尤其是路演前一天晚上一起调试 Prompt，然后把最佳表现录屏，录屏中还出现了几次滑稽的意外...这种协作的经历让我感觉很充实，富有激情。

而且我每天都会遗留一两个事项给峰哥来解决，比如：
- 我做完了一个表单填写框和提交按钮，我就告诉峰哥让他来做表单提交的功能；
- 我做完了聊天气泡（由AI、用户、系统发出的消息）的三种样式，也是一样让峰哥来做相关的展示逻辑...

真正参与产品代码贡献对我来说是一直想去做的事情，因为我一直觉得如果能由做界面/交互设计的人，来亲手将其创作内容实现出来，是一件很酷的事情，也能够减少很多沟通成本。

### 参与到 AI 的浪潮之中

我最开始是在去年年底的时候，用 ChatGPT 来帮我解决我重构个人网站时的一些实现问题，中途因为好奇心驱使，也问了很多奇奇怪怪的问题。然后最近也在高频使用 ChatGPT，来作为我学习英语的助手。

而这次比赛不仅给了我一个机会去参与创造一个跟 AI 相关的产品（包括代码也有不少是 ChatGPT 参与的），还给了我推强大的动力去了解 AI 在商业中的场应用景。除了在比赛中看到其他参赛者的创意之外，现在还了解到比如 Atlassian 已经有相关的功能前瞻了。

<video alt="Atalssian AI 的宣传视频，以蓝色科技风格为调性。展示了多个功能，包括在文档中给一个主题让 AI 扩写内容、智能客服、SQL 语句生成。" src="https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2023-05-28/13.mp4">

从 Atlassian 在 5 月 4 日发布的[股东信](https://www.atlassian.com/blog/announcements/shareholder-letter-q3fy23)当中，也透露到该公司已经在用 AI 来来为客户提供服务了。

> "Now that generative AI has reached consumer-grade maturity with LLMs, we can create magical new experiences for our customers."
> 现在，随着大型语言模型（LLMs）带领生成型人工智能达到了消费级的成熟，我们可以为我们的客户创造魔术般的新体验。

除了 Atlassian，另一个互联网巨头：[Shopify](https://www.shopify.com/blog/ai-product-descriptions) 也将 AI 能力应用到其产品当中。比如在商品详情页的编辑界面当中，我们可以输入几个关键字，让 AI 帮忙生成一段商品介绍的文本，还能够调整文本的风格。

![Shopify Magic 商品描述生成界面截图：左侧输入商品关键词并选择「Playful」文风，右侧 AI 即时生成一段强调户外露营与浪漫晚餐场景的英文商品文案。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2023-05-28/14.png '')

Shopify 将同样也是利用 LLM 来实现的生成文本能力，这被官方称为「[Shopify Magic](https://www.shopify.com/blog/ai-product-descriptions)」。除了在商品详情页生成商品描述，也能在邮件当中根据活动类型或产品关键字生成邮件标题，或者在主题编辑器中根据要求来生成标题等等。

[微软](https://www.microsoft.com/en-us/ai)就不必多说了，也已经在 Microsoft 的办公软件上集成了很多 AI 功能。

## 代码仓库

这里放上我们产品的代码仓库吧，记录这段热血时光：

[SQL-Helper · Github](https://github.com/Pudge1996/Sql-helper)

最后，通过这次 AIGC Hackathon 活动，我真正参与到了产品的代码贡献，同时也看到了许多 AI 能力的应用场景。听说公司有产品在研究 AI 能力在业务中的应用，希望之后自己也有机会在商业项目上进行更多相关的实践吧！

---

## 近况

太久没发博客了，记录下我最近的状态吧。应该没有人想知道，但若干年后的我可能会想知道。

1. 近沉迷于学习英文，所以会导致网站、博客的更新会比之前慢一些。
    1. 发现英文还挺有意思的，但在学生时代是看见英文就想睡觉。以前的我应该是比较喜欢数学和历史。
    2. 小目标是今年内能出一篇全英文的博客。全程用英文书写，然后在发布之前先给 ChatGPT 帮忙检查和润色一下。
2. 个人网站 [LRD.IM](https://lrd.im) 正在开发支持切换语言至「英语」的功能。
3. 有一个前端相关的分享会正在准备进行，是面向部门内产品、本地化运营和设计同事的。
4. 在手机上开通了 ChatGPT Plus。直观感受是 GPT-4 的回答比 GPT-3.5 靠谱很多很多，应该会持续订阅。
5. 正在尝试一种新的作息，再多体会一段时间后，可能也会在博客上记录。