Update
many chore
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# LLM Agent之结构化输出
|
||||
# LLM Agent 之结构化输出
|
||||
|
||||
author:Marlene
|
||||
|
||||
@@ -6,33 +6,33 @@ author:Marlene
|
||||
|
||||
## 引言
|
||||
|
||||
自去年年底以来,GPT的迅速发展诞生了一系列大模型。出现了更新、更大、更强的GPT-4。OpenAI不断推出GPT-4,ChatGPT Plugins,代码解释器,Function calling,图片处理等等。7月的WAIC上,笔者也有幸见到了国内一众企业相继展示自家的大模型。在这段时间里,LLM从最初的PE工程走向智能体交互。而笔者从最开始考虑LLM能不能多人协作,思考”一个专家完成所有任务好还是很多人分工完成好“,到各种论文层出不穷,到如今火热的LLM Agent开发模式。可以说,如果你从大学里随便问某个人都知道GPT,甚至大部分都用过。
|
||||
自去年年底以来,GPT 的迅速发展诞生了一系列大模型。出现了更新、更大、更强的 GPT-4。OpenAI 不断推出 GPT-4,ChatGPT Plugins,代码解释器,Function calling,图片处理等等。7 月的 WAIC 上,笔者也有幸见到了国内一众企业相继展示自家的大模型。在这段时间里,LLM 从最初的 PE 工程走向智能体交互。而笔者从最开始考虑 LLM 能不能多人协作,思考”一个专家完成所有任务好还是很多人分工完成好“,到各种论文层出不穷,到如今火热的 LLM Agent 开发模式。可以说,如果你从大学里随便问某个人都知道 GPT,甚至大部分都用过。
|
||||
|
||||
好了,前言少叙。进入正题。众所周知,Agent 基本= LLM(大型语言模型)+ 记忆 + 规划技能 + 工具使用。
|
||||
|
||||
想要使用工具,让GPT掌握如何使用工具,常见的方法是告知GPT工具(通常是一个可以调用的函数)的参数,让GPT生成这些参数即可。那么如何让GPT可靠的生成这些规定的参数呢?换一种说法,如何让GPT输出结构化的数据信息呢?
|
||||
想要使用工具,让 GPT 掌握如何使用工具,常见的方法是告知 GPT 工具(通常是一个可以调用的函数)的参数,让 GPT 生成这些参数即可。那么如何让 GPT 可靠的生成这些规定的参数呢?换一种说法,如何让 GPT 输出结构化的数据信息呢?
|
||||
|
||||
## 原理及相关框架
|
||||
|
||||
现如今大部分的结构化输出工具的原理都是:告诉GPT要输出一个怎么样的结构即可。没错~当然,为什么会出现这么多开发工具都用来解决这个问题,明明是一个简单的原理呢?
|
||||
现如今大部分的结构化输出工具的原理都是:告诉 GPT 要输出一个怎么样的结构即可。没错~当然,为什么会出现这么多开发工具都用来解决这个问题,明明是一个简单的原理呢?
|
||||
|
||||
```
|
||||
```txt
|
||||
1. 通过 prompt 告知 LLM 我们所需要的返回格式,并进行生成。
|
||||
2. 通过一些规则来检查返回结果,如果不符合格式,生成相关错误信息。
|
||||
3. 将上一次的生成内容和检查的错误信息告知 LLM,进行下一次的修正生成。
|
||||
4. 重复 2-3 步骤,直到生成的内容完全符合我们的要求。
|
||||
```
|
||||
|
||||
首先,关于怎样描述这样一个结构的prompt模板,众口难调。有些人认为结构就应该用自然语言描述,这样足够简单,上手难度足够低,方便快速迭代开发。有些人认为结构描述?JSON Schema不就够了?有些人觉得YAML也可以。有些人觉得上面这些对于我的需求还是够不着啊,于是自己造了一个伪代码描述。
|
||||
首先,关于怎样描述这样一个结构的 prompt 模板,众口难调。有些人认为结构就应该用自然语言描述,这样足够简单,上手难度足够低,方便快速迭代开发。有些人认为结构描述?JSON Schema 不就够了?有些人觉得 YAML 也可以。有些人觉得上面这些对于我的需求还是够不着啊,于是自己造了一个伪代码描述。
|
||||
其次,自动处理修正机制也可以做很多文章。还有许多对性能和开销的优化。
|
||||
下文就是关于一众框架的简单分析。希望会对选择困难症的你有所帮助。
|
||||
|
||||
### **guardrails**
|
||||
|
||||
guardrails这个项目,就是将上述的步骤做了进一步的抽象与封装,提供更加 high level 的配置与 API 来完成整个过程。
|
||||
guardrails 这个项目,就是将上述的步骤做了进一步的抽象与封装,提供更加 high level 的配置与 API 来完成整个过程。
|
||||
优点:
|
||||
|
||||
1. 定义了一套RAIL spec
|
||||
1. 定义了一套 RAIL spec
|
||||
2. 更聚焦于错误信息
|
||||
|
||||
```markdown
|
||||
@@ -78,7 +78,7 @@ Given the following doctor's notes about a patient, please extract a dictionary
|
||||
</rail>
|
||||
```
|
||||
|
||||
可以看到,guardrails定义了一套类似xml的语言用于结构化输出,又结合了自然语言的prompt。虽然比起常见的模板语言要更加“繁琐”,但可以包含的内容也可以更加完善。比如可以提供字段的描述信息,检查规范,一定程度上也能帮助 LLM 更好地理解需求,生成预期的结果。
|
||||
可以看到,guardrails 定义了一套类似 xml 的语言用于结构化输出,又结合了自然语言的 prompt。虽然比起常见的模板语言要更加“繁琐”,但可以包含的内容也可以更加完善。比如可以提供字段的描述信息,检查规范,一定程度上也能帮助 LLM 更好地理解需求,生成预期的结果。
|
||||
|
||||
```markdown
|
||||
I was given the following JSON response, which had problems due to incorrect values.
|
||||
@@ -127,11 +127,11 @@ define bot inform capabilities
|
||||
"I am an AI assistant which helps answer questions based on a given knowledge base. For this interaction, I can answer question based on the job report published by US Bureau of Labor Statistics."
|
||||
```
|
||||
|
||||
从代码可以看出其结合了python和自然语言,方便相似度检索。
|
||||
从代码可以看出其结合了 python 和自然语言,方便相似度检索。
|
||||
其整体的运作流程如下:
|
||||
|
||||
1. 根据用户输入识别用户意图。在这一步,系统会将用户的输入在 flow 定义的各种用户回复文本中做相似性查找,也就是上面文件中“What can you do?”这一连串内容。这些检索到的预设用户意图内容,结合其它信息如对话样例,最近聊天记录等,形成整体的 prompt,发给 LLM 来生成回复。最终再从回复中提取用户意图。
|
||||
2. 根据意图,判断下一步操作动作。这一步有两种做法,一是当前的状态能够匹配上预定义的 flow。例如用户就是提了一个 bot 能力的问题,那么就会匹配上面定义的user ask capabilities,下一步动作自然就是bot inform capabilities。如果没有匹配上,就要由 LLM 自己来决定下一步动作,这时候也会跟生成用户意图一样,对于 flow 定义做一个相似性查找,将相关信息发给 LLM 来做生成。
|
||||
2. 根据意图,判断下一步操作动作。这一步有两种做法,一是当前的状态能够匹配上预定义的 flow。例如用户就是提了一个 bot 能力的问题,那么就会匹配上面定义的 user ask capabilities,下一步动作自然就是 bot inform capabilities。如果没有匹配上,就要由 LLM 自己来决定下一步动作,这时候也会跟生成用户意图一样,对于 flow 定义做一个相似性查找,将相关信息发给 LLM 来做生成。
|
||||
3. 生成 bot 回复。如果上一步生成的 bot 回复意图已经有明确定义了(例如上面的 bot 能力的回复),那么就直接用预定义的回复内容来回复用户。如果没有,就跟生成用户意图一样,做意图的相似性查找,将相关信息给 LLM 来生成回复。注意到很多动态的问题例如 QA 场景,是很难预先定义好回复内容的,这里也支持对接知识库,同样是做 vector search 之后,将相关 context 信息发给 LLM 来生成具体回复。
|
||||
|
||||
### guidance
|
||||
@@ -174,7 +174,7 @@ program(description="A quick and nimble fighter.", valid_weapons=valid_weapons)
|
||||
1. 生成的 json 结构是保证合法且可控的,不会出现语法错误或者缺失/错误字段等。
|
||||
2. 通过 LLM 生成的 token 数量减少了,理论上可以提升生成速度。
|
||||
|
||||
除了prompt模板,它还提供了:
|
||||
除了 prompt 模板,它还提供了:
|
||||
|
||||
- 支持 hidden block,例如 LLM 的一些推理过程可能并不需要暴露给最终用户,就可以灵活利用这个特性来生成一些中间结果。
|
||||
- Generation caching,自动把已经生成过的结果缓存起来,提升速度。
|
||||
@@ -186,7 +186,7 @@ program(description="A quick and nimble fighter.", valid_weapons=valid_weapons)
|
||||
|
||||
### lmql
|
||||
|
||||
在 guidance 的基础上,lmql这个项目进一步把“prompt 模板”这个概念推进到了一种新的编程语言。从官网能看到给出的一系列示例。语法结构看起来有点像 SQL,但函数与缩进都是 Python 的风格。
|
||||
在 guidance 的基础上,lmql 这个项目进一步把“prompt 模板”这个概念推进到了一种新的编程语言。从官网能看到给出的一系列示例。语法结构看起来有点像 SQL,但函数与缩进都是 Python 的风格。
|
||||

|
||||
从支持的功能来看,相比 guidance 毫不逊色。例如各种限制条件,代码调用,各种 caching 加速,工具集成等基本都具备。这个框架的格式化输出是其次,其各种可控的输出及语言本身或许更值得关注。
|
||||
|
||||
@@ -194,17 +194,17 @@ program(description="A quick and nimble fighter.", valid_weapons=valid_weapons)
|
||||
|
||||
TypeChat 将 prompt 工程替换为 schema 工程:无需编写非结构化的自然语言 prompt 来描述所需输出的格式,而是编写 TS 类型定义。TypeChat 可以帮助 LLM 以 JSON 的形式响应,并且响应结果非常合理:例如用户要求将这句话「我可以要一份蓝莓松饼和一杯特级拿铁咖啡吗?」转化成 JSON 格式,TypeChat 响应结果如下:
|
||||

|
||||
其本质原理是把interface之类的ts代码作为prompt模板。因此它不仅可以对输出结果进行ts校验,甚至能够输入注释描述,不可谓非常方便js开发者。不过,近日typechat爆火,很多开发者企图尝试将typechat移植到python,笔者认为这是缘木求鱼,因为其校验本身依赖的是ts。笔者在开发过程中,将typechat融合到自己的库中,效果不错。但是它本身自带的prompt和笔者输入的prompt还是存在冲突,还是需要扣扣源码。
|
||||
其本质原理是把 interface 之类的 ts 代码作为 prompt 模板。因此它不仅可以对输出结果进行 ts 校验,甚至能够输入注释描述,不可谓非常方便 js 开发者。不过,近日 typechat 爆火,很多开发者企图尝试将 typechat 移植到 python,笔者认为这是缘木求鱼,因为其校验本身依赖的是 ts。笔者在开发过程中,将 typechat 融合到自己的库中,效果不错。但是它本身自带的 prompt 和笔者输入的 prompt 还是存在冲突,还是需要扣扣源码。
|
||||
|
||||
### Langchain
|
||||
|
||||
如果你关注了过去几个月中人工智能的爆炸式发展,那你大概率听说过 LangChain。简单来说,LangChain 是一个 Python 和 JavaScript 库,由 Harrison Chase 开发,用于连接 OpenAI 的 GPT API(后续已扩展到更多模型)以生成人工智能文本。
|
||||
|
||||
langchain具有特别多的结构化输出工具。例如使用yaml定义Schema,输出结构化JSON。使用zodSchema定义Schema,输出结构化JSON。使用FunctionParameters定义Schema,输出结构化JSON。
|
||||
langchain 具有特别多的结构化输出工具。例如使用 yaml 定义 Schema,输出结构化 JSON。使用 zodSchema 定义 Schema,输出结构化 JSON。使用 FunctionParameters 定义 Schema,输出结构化 JSON。
|
||||
|
||||
但是笔者这里不打算介绍langchain。究其原因,是笔者被langchain折磨不堪。明明可以几行代码写清楚的东西,langchain可以各种封装,花了好几十行才写出来。更何况,笔者是用ts开发,开发时甚至偷不了任何懒,甚至其文档丝毫不友好。这几天,《机器之心》发布文章表示放弃langchain。要想让 LangChain 做笔者想让它做的事,就必须花大力气破解它,这将造成大量的技术负担。因为使用人工智能本身就需要花费足够的脑力。LangChain 是为数不多的在大多数常用情况下都会增加开销的软件之一。所以笔者建议非必要,不使用langchain。
|
||||
但是笔者这里不打算介绍 langchain。究其原因,是笔者被 langchain 折磨不堪。明明可以几行代码写清楚的东西,langchain 可以各种封装,花了好几十行才写出来。更何况,笔者是用 ts 开发,开发时甚至偷不了任何懒,甚至其文档丝毫不友好。这几天,《机器之心》发布文章表示放弃 langchain。要想让 LangChain 做笔者想让它做的事,就必须花大力气破解它,这将造成大量的技术负担。因为使用人工智能本身就需要花费足够的脑力。LangChain 是为数不多的在大多数常用情况下都会增加开销的软件之一。所以笔者建议非必要,不使用 langchain。
|
||||
|
||||
## LLM对于结构化信息的理解
|
||||
## LLM 对于结构化信息的理解
|
||||
|
||||
LLM 的可控性、稳定性、事实性、安全性等问题是推进企业级应用中非常关键的问题,上面分享的这些项目都是在这方面做了很多探索,也有很多值得借鉴的地方。总体思路上来说,主要是:
|
||||
|
||||
@@ -216,24 +216,24 @@ LLM 的可控性、稳定性、事实性、安全性等问题是推进企业级
|
||||
|
||||
即使我们不直接使用上述的项目做开发,也可以从中学习到很多有用的思路。当然也非常期待这个领域出现更多有意思的想法与研究,以及 prompt 与编程语言结合能否碰撞出更多的火花。
|
||||
|
||||
同时笔者认为自动处理机制、自己设计的编程语言等等内容,随着时间发展,一定会层出不穷,不断迭代更新。笔者抛去这些时效性较弱的内容,从描述信息和位置信息两方面思考peompt模板该如何设计,当然只是浅浅的抛砖引玉一下。
|
||||
同时笔者认为自动处理机制、自己设计的编程语言等等内容,随着时间发展,一定会层出不穷,不断迭代更新。笔者抛去这些时效性较弱的内容,从描述信息和位置信息两方面思考 peompt 模板该如何设计,当然只是浅浅的抛砖引玉一下。
|
||||
|
||||
### 描述信息
|
||||
|
||||
到底哪种方式更容易于LLM去理解?我们不谈框架的设计,只考虑prompt的设计。上述框架关于这方面有一些参考,例如有些直接拿json作为prompt模板,有些拿xml作为prompt模板,有些拿自己设计的语言作为prompt,有些拿自然语言作为prompt模板。时至今日,选用哪种最适合LLM去理解格式化的信息,输出格式化的内容完全没有盖棺定论。甚至时至今日,格式化输出问题还是没有得到可靠稳定的解决,要不然笔者肯定不会介绍这么多框架实践了。
|
||||
到底哪种方式更容易于 LLM 去理解?我们不谈框架的设计,只考虑 prompt 的设计。上述框架关于这方面有一些参考,例如有些直接拿 json 作为 prompt 模板,有些拿 xml 作为 prompt 模板,有些拿自己设计的语言作为 prompt,有些拿自然语言作为 prompt 模板。时至今日,选用哪种最适合 LLM 去理解格式化的信息,输出格式化的内容完全没有盖棺定论。甚至时至今日,格式化输出问题还是没有得到可靠稳定的解决,要不然笔者肯定不会介绍这么多框架实践了。
|
||||
|
||||
笔者认为不管哪种方式,都可以从两个方面考量:更简单,更结构。如果想要在开发的时候更简单,或者在使用时更简单,选择md、yaml方式描述结构化信息更合适。如果想要更结构化的方式,选择json、xml、ts,输出都能更有结构,甚至之后做结构校验都更方便。
|
||||
笔者认为不管哪种方式,都可以从两个方面考量:更简单,更结构。如果想要在开发的时候更简单,或者在使用时更简单,选择 md、yaml 方式描述结构化信息更合适。如果想要更结构化的方式,选择 json、xml、ts,输出都能更有结构,甚至之后做结构校验都更方便。
|
||||
|
||||
想要LLM结构化输出更加稳定和理想,笔者认为选择prompt模板时必须考虑每个字段是否有足够的辅助信息。例如xml描述时,每个标签都有一个描述属性描述这个标签时什么意思。
|
||||
想要 LLM 结构化输出更加稳定和理想,笔者认为选择 prompt 模板时必须考虑每个字段是否有足够的辅助信息。例如 xml 描述时,每个标签都有一个描述属性描述这个标签时什么意思。
|
||||
|
||||
#### 额外引申
|
||||
|
||||
笔者之前在开发LLM应用时,也曾思考类似的问题。笔者需要将多模态的数据进行结构化的标注,方便LLM去理解。但是标注成什么样却是一个很大的难题。笔者选择的是JSON。但是,关于里面许多内容的标注。笔者在众多方案中徘徊。在细节处深挖,如何设计一种既简单,又能表示各种结构复杂关系,还能够节约token的方案及其的难。
|
||||
> 关于后续如何解决,请容笔者卖个关子sai~
|
||||
笔者之前在开发 LLM 应用时,也曾思考类似的问题。笔者需要将多模态的数据进行结构化的标注,方便 LLM 去理解。但是标注成什么样却是一个很大的难题。笔者选择的是 JSON。但是,关于里面许多内容的标注。笔者在众多方案中徘徊。在细节处深挖,如何设计一种既简单,又能表示各种结构复杂关系,还能够节约 token 的方案及其的难。
|
||||
> 关于后续如何解决,请容笔者卖个关子 sai~
|
||||
|
||||
### 位置信息
|
||||
|
||||
是否有人注意到llm对于关键信息在prompt中的位置会对结果产生影响呢?在设计 prompt 方面,人们通常建议为语言模型提供详尽的任务描述和背景信息。近期的一些语言模型有能力输入较长的上下文,但它究竟能多好地利用更长的上下文?这一点却相对少有人知。近日,有学者研究发现如果上下文太长,语言模型会更关注其中的前后部分,中间部分却几乎被略过不看,导致模型难以找到放在输入上下文中部的相关信息。下文部分是该论文一些核心内容:
|
||||
是否有人注意到 llm 对于关键信息在 prompt 中的位置会对结果产生影响呢?在设计 prompt 方面,人们通常建议为语言模型提供详尽的任务描述和背景信息。近期的一些语言模型有能力输入较长的上下文,但它究竟能多好地利用更长的上下文?这一点却相对少有人知。近日,有学者研究发现如果上下文太长,语言模型会更关注其中的前后部分,中间部分却几乎被略过不看,导致模型难以找到放在输入上下文中部的相关信息。下文部分是该论文一些核心内容:
|
||||

|
||||
这是由其本身训练和结构设计有关的,但却对于我们开发有着莫大的帮助和指导意义。
|
||||

|
||||
@@ -243,18 +243,19 @@ LLM 的可控性、稳定性、事实性、安全性等问题是推进企业级
|
||||
|
||||
## 题外话
|
||||
|
||||
之前,妙鸭相机突然爆火。其只需9.9即可生成同款数字分身,效果拔群。但是很多人发现,其生成的内容极其容易造成肖像权侵犯,这显然是有问题的。更有甚至的是,用户发现妙鸭相机的用户协议存在问题。根据该应用最初版本的用户服务协议,用户需授权妙鸭相机在全世界(包括元宇宙等虚拟空间)范围内享有永久的、不可撤销的、可转让的、可转授权的、免费的和非独家的许可,使得妙鸭相机可以任何形式、任何媒体或技术(无论现在已知或以后开发)使用用户的内容。对于上述内容,妙鸭相机称系“为了使我方能够提供、确保和改进本服务(包括但不限于使用AI生成内容作为再训练数据等)”。
|
||||
之前,妙鸭相机突然爆火。其只需 9.9 即可生成同款数字分身,效果拔群。但是很多人发现,其生成的内容极其容易造成肖像权侵犯,这显然是有问题的。更有甚至的是,用户发现妙鸭相机的用户协议存在问题。根据该应用最初版本的用户服务协议,用户需授权妙鸭相机在全世界(包括元宇宙等虚拟空间)范围内享有永久的、不可撤销的、可转让的、可转授权的、免费的和非独家的许可,使得妙鸭相机可以任何形式、任何媒体或技术(无论现在已知或以后开发)使用用户的内容。对于上述内容,妙鸭相机称系“为了使我方能够提供、确保和改进本服务(包括但不限于使用 AI 生成内容作为再训练数据等)”。
|
||||
|
||||
一句话理解,就是你的肖像它随便用,与你无关。
|
||||
|
||||
这不禁让我联想到一部非常发人深省的剧作:《黑镜》。它的第六季第一集讲述的同样是隐私的问题。该集中,主人公的生活隐私由于同意了用户协议,被无时无刻搜集。然后当天晚上就发现流媒体电视上居然出现了跟她同名的电视剧,内容与它当天的生活一模一样,台词甚至更加夸张。于是她的不方便公之于众的生活变得一塌涂地,但她甚至没有办法打官司,因为肯定会输。更令人深省的是,电视剧的主人公是AI生成的视频,其肖像确是根据现实存在的明星生成的。那位明星也无法对她的肖像有任何权利。这样一个荒诞的故事,但是仔细想想,却又非常可能发生。
|
||||
这不禁让我联想到一部非常发人深省的剧作:《黑镜》。它的第六季第一集讲述的同样是隐私的问题。该集中,主人公的生活隐私由于同意了用户协议,被无时无刻搜集。然后当天晚上就发现流媒体电视上居然出现了跟她同名的电视剧,内容与它当天的生活一模一样,台词甚至更加夸张。于是她的不方便公之于众的生活变得一塌涂地,但她甚至没有办法打官司,因为肯定会输。更令人深省的是,电视剧的主人公是 AI 生成的视频,其肖像确是根据现实存在的明星生成的。那位明星也无法对她的肖像有任何权利。这样一个荒诞的故事,但是仔细想想,却又非常可能发生。
|
||||
|
||||
如今的社会出现了各种大模型。大模型的发展必定需要大数据的支撑。企业为了盈利必定会想方设法的搜集数据,然后肆意使用,转卖。而很多用户对此不自知,更有甚至是非常乐意。例如抖音、B站,当你对其交互时,你希望它推荐更适合你的视频,它也在搜集你的数据,这是明知且主动的。
|
||||
如今的社会出现了各种大模型。大模型的发展必定需要大数据的支撑。企业为了盈利必定会想方设法的搜集数据,然后肆意使用,转卖。而很多用户对此不自知,更有甚至是非常乐意。例如抖音、B 站,当你对其交互时,你希望它推荐更适合你的视频,它也在搜集你的数据,这是明知且主动的。
|
||||
|
||||
隐私的掠夺是无声的。你认为你的一下点击是没啥价值的隐私数据,殊不知这正中了资本家的下怀。几年前,我也是这样的。高中的大门出现了闸机,可以刷脸进校园。我当时以为这需要像手机解锁一样需要扫描人脸ID。结果发现,我可以直接进去,闸机上甚至会出现我的照片。我仔细看了看,发现是我入学的证件照。原来一张照片就能刷脸进校园。原来就连学校也可以不经同学同意,将照片用作其他用途。那更何况其他的呢。
|
||||
隐私的掠夺是无声的。你认为你的一下点击是没啥价值的隐私数据,殊不知这正中了资本家的下怀。几年前,我也是这样的。高中的大门出现了闸机,可以刷脸进校园。我当时以为这需要像手机解锁一样需要扫描人脸 ID。结果发现,我可以直接进去,闸机上甚至会出现我的照片。我仔细看了看,发现是我入学的证件照。原来一张照片就能刷脸进校园。原来就连学校也可以不经同学同意,将照片用作其他用途。那更何况其他的呢。
|
||||
我想,未来,这样的隐私问题会越来越多。
|
||||
|
||||
## 参考
|
||||
|
||||
<https://mp.weixin.qq.com/s?__biz=MzA3MzI4MjgzMw==&mid=2650885029&idx=4&sn=ac01576a8957b41529dd3c877d262d5e&chksm=84e48fdbb39306cd8979a4fa7f7da14a9428dc28ccc47880d668ef6293b1a8b7b0964569ec36&mpshare=1&scene=23&srcid=0725w9FPsVnOOzkPGPB7lH8h&sharer_sharetime=1690303766527&sharer_shareid=d2396b329b12f49d34967e2b183540dd#rd>
|
||||
<https://mp.weixin.qq.com/s/BngY2WgCcpTOlvdyBNJxqA>
|
||||
<https://microsoft.github.io/TypeChat/>
|
||||
|
||||
Reference in New Issue
Block a user