写点什么

文心一言赋能问卷生成,打造高效问卷调研工具

  • 2024-03-18
    北京
  • 本文字数:3275 字

    阅读完需:约 11 分钟

文心一言赋能问卷生成,打造高效问卷调研工具


当前,各种大语言模型(LLM,Large Language Model)井喷式发展,基于 LLM 的应用也不断涌现。但是,当开发者基于 LLM 开发下游应用时,LLM 直接生成的结果在格式、内容等方面都存在许多不确定因素,难以与其他业务逻辑代码做数据交互,导致开发者需要多次生成并对输出结果做大量的规则判断处理工作,使得大模型原生应用的开发门槛抬高、难度加大。


为此,本文以问卷页面生成任务为例,手把手教大家控制 ERNIE SDK 输出 JSON 格式的生成结果并与前端交互,实现通过 ERNIE SDK 生成问卷网页的目的。通过本文,你将学习到:


  • 前后端交互的桥梁——JSON

  • 用 LLM2Json 控制文心大模型 4.0 的输出格式

  • 基于文心大模型的原生应用开发流程

JSON 数据结构

本文任务的核心是生成交互数据,前后端的交互数据常用格式有 JSON 和 XML。由于 JSON 格式结构简单,容易被各大常用开发语言解析和生成,因此目前绝大多数 Web 应用使用 JSON 格式进行交互。


JSON 数据根据结构的复杂度可简单可分成两种,单层结构和多层嵌套结构。

单层结构

单层数据结构是类似于 {key1: value1, key2: value2, …} 这样只有一层键值对关系的结构,相对来说比较简单,生成可控度高,不容易出错。比如:


{    "address": "北京市朝阳区XXX路XXX号",    "date": "2023-06-25",    "email": "zhangsan@example.com",    "idcode": "110101199003077777",    "name": "张三",    "phone": "13800000000",    "sex": "男"}
复制代码

多层嵌套结构

多层嵌套结构是比较复杂的数据结构,如例子所示,在 address 的第一层级下,嵌套了第二层级的 city、area、road 和 detail 字段。在真实业务场景中,数据结构体往往是多层嵌套,字段多,嵌套关系也比较复杂,因此该类数据结构体生成的难度比较大,容易出现一些纰漏导致数据解析不正确而报错。


{    "address": {        "city": "北京市",        "area": "朝阳区",        "road": "XXX路",        "detail": "XXX号"    },    "date": "2023-06-25",    "email": {        "common": "zhangsan@example.com",        "backup": "zhangsan@example1.com"    },    "idcode": "110101199003077777",    "name": "张三",    "phone": "13800000000",    "sex": "男"}
复制代码


本文的问卷网页生成任务,本质上就是生成一个多层嵌套结构的数据,并与前端交互渲染形成可视化网页,下面开始给大家演示和解析代码。

动手开发

安装依赖

本项目需要主要依赖 erniebot 和 llm2json 两个包。ERNIE SDK 用于调用文心一言的文本生成能力,目前支持 ernie-3.5、ernie-turbo、ernie-4.0、ernie-longtext 等多个版本等模型直接调用。LLM2Json 是一个易于使用的格式化大语言模型输出工具包,它的主要设计思想和部分实现代码参考 LangChain。它可以通过自动构建 prompts 引导大语言模型输出符合 JSON 语法的返回数据,解决了大语言模型格式化输出、数据交互、前端开发等遇到的数据格式相关问题,使下游的应用程序、GPTs、Agents 等开发更加方便快捷。


pip install erniebot --upgradepip install llm2json
复制代码

配置 ERNIE SDK

对 ERNIE SDK 进行简单的封装,以便后面代码快速调用。请注意将 access_token 换成你的 aistudio 账户对应的 token,同时保证 token 余额充足。另外,本项目演示使用 ernie-4.0 版本,在测试环境中 4.0 版本的表现最优,开发者可根据自己的成本和推理速度需求更换为 ernie-3.5、ernie-turbo 等版本。


import erniebot
erniebot.api_type = "aistudio"erniebot.access_token = "xxxxxxxxxxxxxxxxxxx"
def ernieChat(content): response = erniebot.ChatCompletion.create(model = "ernie-4.0", messages = [{ "role": "user", "content": content }]) return response.get_result()
复制代码

定义数据结构

一份问卷的生成结构至少有两层。第一层是 title(问卷标题)、description(问卷描述)和最核心的 data(问题列表)结构体。第二层是对 data 嵌套数据的定义。在 data 下面有若干个问题和选项,并且问题类型有单选题、多选题、填空题,因此,这里需要针对问题定义一个新的对象 Question,第一个键是 types,用于确定问题类型,它是整数型的数据(1 为单选,2 为多选,3 为填空);第二个是 question,定义问题;第三个是 choices 问题对应的选项内容,数据类型是列表 list。


from typingimport Listfrom llm2json.prompts.schemaimport BaseModel, Field
class Question(BaseModel): types: int = Field(description = "问题类型,1为单选,2为多选,3为填空") question: str = Field(description = "问题内容") choices: List[str] = Field(description = "选项内容")
class WenJuan(BaseModel): title: str = Field(description = "问卷标题") description: str = Field(description = "问卷描述") data: List[Question] = Field(description = "问题列表")
复制代码

定义正例

因为多层嵌套的数据结构体比较复杂,因此建议开发者最好给模型输入一个正确示例,让模型生成的输出结果更加完美和稳定。


correct_example = ''' {    "title": "问卷标题",    "description": "问卷描述",    "data": [{            "types": 1,            "question": "问题(单选)"            "choices": ["选项1", "选项2", "选项3"]        },        {            "types": 2,            "question": "问题(多选)"            "choices": ["选项1", "选项2", "选项3"]        },        {            "types": 3,            "question": "问题(填空)"        },    ]}'''
复制代码

定义 Prompt 任务模板

Prompt 任务模版主要是告诉大语言模型需要生成的内容,以及定义用户输入变量。在本案例中,我们的目的是生成问卷,用户输入的变量是问卷的主题(topic)和问题的数量(num),并将 3、4 中定义好的数据结构和正例传入。


from llm2json.prompts import Templates
t = Templates(prompt="""请你根据主题<{topic}>,设计一份问卷。问卷描述需要简单说明该问卷调研的目的。问卷题型需包含单选、多选和填空题,对应types分别为1、2、3。如果题目类型为填空题,该题不需要返回choices字段。出题题型顺序请随机生成。题目总数为{num}道题。""", field=WenJuan,correct_example=correct_example)
复制代码

测试生成

以文心一言用户反馈作为问卷的主题,生成一份包含 10 道题的问卷。


from llm2json.output import JSONParserfrom pprint import pprint
# 将用户输入替换模型变量template = t.invoke(topic="文心一言用户反馈", num="10")# 将Prompt模版提交给ErnieBoternieResult = ernieChat(template)
# 解析生成结果parser = JSONParser()result = parser.to_dict(ernieResult)pprint(result)
复制代码


运行后,会得到如下图所示的数据:


前端绑定渲染

获得生成后的 JSON 格式数据,就可以与前端代码结合,解析数据结构体、绑定字段并渲染。前端的核心代码主要是对问卷类型的判断,然后根据问卷类型,也就是 types 的值匹配不同的表单组件。(此处只展示前端核心代码部分,完整前端代码请通过文章最后的项目链接获取)


<div class="choices"><!--单选题--><div v-if="item.types==1"><a-radio-group v-model:value="item.choices.keys"><a-radio v-for="choice in item.choices" :value="choice">{{ choice }}</a-radio></a-radio-group></div>
<!--多选题--><div v-else-if="item.types==2"><a-checkbox-group :options="item.choices" /></div>
<!--填空题--><div v-else-if="item.types==3"><a-input style="max-width:300px"/></div></div>
复制代码

前端渲染结果:

快速体验

本项目以问卷网页生成任务为案例,为大家介绍了控制大语言模型格式化输出 JSON 多层嵌套结构数据并与前端字段绑定做数据交互的流程。通过利用 JSON 数据结构进行前后端的链接交互,开发者可以将大语言模型的能力轻松集成到现有 OA、ERP 和 CRM 等系统,快速赋能企业已有业务,实现办公智能化升级;或从零开始高效开发大模型原生应用,不再担心数据结构解析出错等灾难性问题,为用户提供更好的服务体验。

用户头像

还未添加个人签名 2022-12-26 加入

还未添加个人简介

评论

发布
暂无评论
文心一言赋能问卷生成,打造高效问卷调研工具_json_飞桨PaddlePaddle_InfoQ写作社区