當前,各種大語言模型(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": "[email protected]",
"idcode": "110101199003077777",
"name": "張三",
"phone": "13800000000",
"sex": "男"
}
多層嵌套結構是比較複雜的數據結構,如例子所示,在 address 的第一層級下,嵌套了第二層級的 city、area、road 和 detail 字段。在真實業務場景中,數據結構體往往是多層嵌套,字段多,嵌套關係也比較複雜,因此該類數據結構體生成的難度比較大,容易出現一些紕漏導致數據解析不正確而報錯。
{
"address": {
"city": "北京市",
"area": "朝陽區",
"road": "XXX路",
"detail": "XXX號"
},
"date": "2023-06-25",
"email": {
"common": "[email protected]",
"backup": "[email protected]"
},
"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 --upgrade
pip 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 typing
import List
from llm2json.prompts.schema
import 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 JSONParser
from pprint import pprint
# 將用戶輸入替換模型變量
template = t.invoke(topic="文心一言用戶反饋", num="10")
# 將Prompt模版提交給ErnieBot
ernieResult = 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 等系統,快速賦能企業已有業務,實現辦公智能化升級;或從零開始高效開發大模型原生應用,不再擔心數據結構解析出錯等災難性問題,爲用戶提供更好的服務體驗。