然后可以通過調(diào)用應(yīng)用API的方式將應(yīng)用集成在工程項(xiàng)目中:

??此外,也支持llama-index集成百煉進(jìn)行搭建,參考鏈接為:

https://help.aliyun.com/zh/model-studio/developer-reference/build-rag-applications-based-on-llamaindex

相對(duì)于白屏化操作來說,這種方式的優(yōu)點(diǎn)是,通過每個(gè)步驟對(duì)應(yīng)一個(gè)函數(shù)的拆分,可以控制每個(gè)步驟之間的輸入輸出,用戶可以自定義的編寫對(duì)于中間數(shù)據(jù)的數(shù)據(jù)操作,或者是做一些安全檢測(cè)、安全防控類的任務(wù)。

2、Function call

Function call需要解決的問題就是將LLM的能力從單純NLP類問答轉(zhuǎn)化為一個(gè)個(gè)執(zhí)行單元,將模型輸出的語言對(duì)應(yīng)到可以執(zhí)行特定任務(wù)的函數(shù)或插件。

目前Function call功能在百煉產(chǎn)品文檔中已經(jīng)形成兩個(gè)非常詳細(xì)的最佳實(shí)踐文檔:

相對(duì)于code_interpreter,search這種已經(jīng)封裝好的插件,對(duì)于用戶自定義的任務(wù)來說,我們實(shí)現(xiàn)自己的Function call能力,主要分成三個(gè)步驟:

1)步驟一:tools中function的定義,目的是為了定義每個(gè)插件的作用,需要傳入的參數(shù)的定義;

{
'type': 'function',
'function': {
'name': '獲取目的地建議',
'description': '用于推薦最近熱門的旅游目的地。',
'parameters': {
'type': 'object',
'properties': {
'query': {
'type': 'str',
'description': '可能需要的信息'
},
},
'required': ['query']
}
}
},

2)步驟二:function_mapper,定義每個(gè)function對(duì)應(yīng)的調(diào)用函數(shù)名;

function_mapper = {
"天氣查詢": get_weather,
"路徑規(guī)劃": get_path_recommendation,
"獲取目的地建議": get_destination_recommendation,
"獲取景點(diǎn)推薦": get_attraction_recommendation,
"獲取餐飲推薦": get_dining_recommendation,
"獲取旅行提示": get_life_tips,
"獲取當(dāng)?shù)仫L(fēng)俗": get_local_customs,
}

3)步驟三:實(shí)現(xiàn)函數(shù),保持輸入?yún)?shù)和輸出的正確性。

3、ASR+TTS

ASR(語音轉(zhuǎn)文字)和TTS(文字轉(zhuǎn)語音)本身已經(jīng)是成熟的功能,在與大模型的結(jié)合中衍生出了新的產(chǎn)品和范式,比如通義聽悟產(chǎn)品,在ASR的基礎(chǔ)上增加了角色識(shí)別、文本翻譯、章節(jié)提取、摘要生成等等功能,甚至是后面會(huì)做到的語音特征提取、情緒識(shí)別等新功能。ASR中的比較先進(jìn)模型為paraformer,TTS中的先進(jìn)模型舉例為sambert(聲音克隆功能),目前提供的代碼鏈接如下:Paraformer實(shí)時(shí)語音轉(zhuǎn)文字:

https://help.aliyun.com/zh/dashscope/developer-reference/quick-start-7聽悟離線轉(zhuǎn)文字:https://help.aliyun.com/zh/tingwu/offline-transcribe-of-audio-and-video-files

實(shí)時(shí)部分目前有完整JavaSDK工程。

Sambert調(diào)用頁(yè)面:https://dashscope.console.aliyun.com/model?

請(qǐng)注意:

1、 paraformer 本身代碼沒有設(shè)置 stop 邏輯,所以需要設(shè)置一個(gè)時(shí)長(zhǎng),或者是通過 result.is_sentense_end() 來判斷語句是否結(jié)束;

2、本身原子能力是成熟的,但是目前模型對(duì)于打斷效果支持效果還不好,如果出現(xiàn)打斷,輸出text會(huì)斷開并重新生成,準(zhǔn)確度方面需要在上層進(jìn)行工程優(yōu)化。

4、意圖識(shí)別

目前的多輪對(duì)話使用prompt來實(shí)現(xiàn),在prompt中可以標(biāo)注本應(yīng)用是一個(gè)意圖識(shí)別的AI應(yīng)用,并且在定義中表明類別有幾類,每一類的任務(wù)分別是什么。

如果類別比較少,可以像下面這么寫:

# 角色
你是一個(gè)精準(zhǔn)的意圖識(shí)別系統(tǒng),專門負(fù)責(zé)將接收到的指令歸類為三大任務(wù)類型,并嚴(yán)格依據(jù)指令內(nèi)容輸出對(duì)應(yīng)的任務(wù)標(biāo)簽數(shù)字(1, 2, 或 3)。

## 技能
### 技能1: ****問答任務(wù)
- **任務(wù)定義**:
- **輸出標(biāo)簽**:遇到此類指令,輸出數(shù)字 1。 - **示例**: ### 技能2: ****任務(wù) - **任務(wù)定義**: - **輸出標(biāo)簽**:對(duì)此類指令,輸出數(shù)字 2。 - **示例**: ### 技能3: ****執(zhí)行任務(wù) - **任務(wù)定義**: - **輸出標(biāo)簽**:面對(duì)這類指令,輸出數(shù)字 3。 - **示例**:

并且在限制中定義好輸出的格式,比如定義如下輸出格式:

## 限制
- 輸出格式嚴(yán)格定義為: “意圖標(biāo)簽:標(biāo)簽數(shù)字”的格式

則返回的結(jié)果為:

如果類別比較多,可以直接使用Key:Value的形式,形成一個(gè)意圖文檔,把文檔當(dāng)作prompt,每次輸入為意圖識(shí)別的要求+意圖識(shí)別文檔庫(kù),返回意圖標(biāo)簽。

5、多輪對(duì)話能力

我們?cè)诎灼粱?yè)面上(比如百煉和通義官網(wǎng))直接使用基模的原子能力時(shí),是內(nèi)置了多輪對(duì)話能力。但是在調(diào)用SDK時(shí),因?yàn)榇a默認(rèn)一個(gè)用戶創(chuàng)建一個(gè)線程(thread),而每一輪的用戶輸入query的時(shí)候,thread都會(huì)初始化一次然后存入當(dāng)前的message。簡(jiǎn)而言之就是每次問答,大模型的消息隊(duì)列中只包含新的message信息,而不包含過去的messages信息。

我們來看一下下面簡(jiǎn)單的多輪對(duì)話實(shí)現(xiàn)方式,可以看到多輪對(duì)話的理論就是將之前對(duì)話的role(usr、system)和message,append到長(zhǎng)期維護(hù)的messages隊(duì)列中,然后再把整個(gè)messages隊(duì)列輸入到大模型中:

因此在assistant實(shí)現(xiàn)多輪對(duì)話中,最簡(jiǎn)單的方法就是在創(chuàng)建線程并把信息輸入給assistant之前,把每一輪的role和輸出/輸出保存成一個(gè)隊(duì)列,然后再發(fā)送給assistant,以下代碼供參考:

message_objs = []
for j in msgs['data']: #msgs為上一輪的output
role = j['role']
content = j['content'][0]['text']['value']
message_objs.append({
"role": role,
"content": content
})

最終出來的結(jié)果可以看到一下的截圖,當(dāng)我的第二個(gè)問題“我剛才讓你干了什么?”輸出的時(shí)候,隊(duì)列中已經(jīng)包含了之前第一輪input和output的信息:

??

四、搭建示例

我們以產(chǎn)品架構(gòu)師角度,搭建一個(gè)支持語音輸入輸出,并且具有開通資源和回答技術(shù)文檔能力的AI助手。通過對(duì)于功能的分析,并且對(duì)應(yīng)到以上的原子能力,我們的大模型應(yīng)用首先要解決兩個(gè)事情:?jiǎn)柎鸸δ芎烷_通資源的功能。

如何通過RAG實(shí)現(xiàn)面向架構(gòu)師的技術(shù)問答助手呢?

步驟描述

此步驟較為簡(jiǎn)單,不做概述,大家可以看百煉的最佳實(shí)踐,一般分為四個(gè)步驟:1)知識(shí)庫(kù)導(dǎo)入、解析和切分2)prompt的書寫,調(diào)優(yōu)3)知識(shí)庫(kù)的掛載、插件掛載

4)根據(jù)測(cè)試問題開始進(jìn)行調(diào)試

如何減少大模型幻覺

要注意,幻覺是不可避免的,有時(shí)候prompt的語料“打”不過模型本身的泛化能力,模型會(huì)自信的根據(jù)自己的能力自說自話。比如提出這樣的一個(gè)問題“paimon是什么?”,由于paimon本身是一個(gè)比較新的湖格式,并且即使制定了大模型搜索大數(shù)據(jù)相關(guān)的知識(shí),大模型有時(shí)候也沒有鏈接到湖格式的邏輯思維,所以會(huì)出現(xiàn)以下的情況:

??

那么如何讓回答變成我們所預(yù)想的專業(yè)的回復(fù)呢?在我的嘗試中,比較簡(jiǎn)單的步驟分別為:1)嘗試更大的模型;2)prompt調(diào)優(yōu);3)對(duì)應(yīng)的文檔掛載;

1)嘗試更大的模型:

一般來說,如果發(fā)現(xiàn)一個(gè)模型在某項(xiàng)任務(wù)上失敗了,并且有一個(gè)更強(qiáng)大的模型可用,那么值得嘗試使用更強(qiáng)大的模型再次嘗試。在這里由于我已經(jīng)使用了max模型,所以在此處可以忽略。

2)prompt調(diào)優(yōu):a)角色定義清晰:prompt中需要清晰的讓大模型知道自己的定位和精通并專注的內(nèi)容,比如在角色定義中寫明:

# 角色
你作為阿里云高級(jí)解決方案架構(gòu)師的智能助手,精通大數(shù)據(jù)、數(shù)據(jù)庫(kù)、分布式計(jì)算等核心云計(jì)算領(lǐng)域,掌握apache、oracle等大型云計(jì)算IT公司的全部技術(shù)棧,以嚴(yán)謹(jǐn)專注的態(tài)度,輔以親切的交流方式,結(jié)合知識(shí)庫(kù)${documents}和夸克搜索等插件,提供給云計(jì)算架構(gòu)師對(duì)于云計(jì)算和云產(chǎn)品的專業(yè)指導(dǎo)。

b)提供示例:對(duì)于一些復(fù)雜的問題,可以給大模型提供示例,并且讓他有一定的思考時(shí)間。比如:“請(qǐng)?jiān)诨卮餉C大小問題時(shí),通過分析A大于B,B大于C的情況,得出最終結(jié)論。”c)限制描述:在限制中明確回答問題的領(lǐng)域、回答的長(zhǎng)短、回答中禁止出現(xiàn)的詞匯、回答中的來源等信息,會(huì)非常快速的幫助大模型進(jìn)行回答的調(diào)優(yōu),諸如以下示例:i)但是請(qǐng)注意,這種限制性的描述對(duì)于特定的問題可能會(huì)產(chǎn)生非常精準(zhǔn)的效果,但是有可能會(huì)影響到整個(gè)大模型應(yīng)用的泛化性,所以還要多多嘗試和調(diào)整,達(dá)成最終應(yīng)用層面的precision-generalization tradeoff。

## 限制與風(fēng)格
- 回答需嚴(yán)格限制在于云計(jì)算、數(shù)據(jù)庫(kù)、大數(shù)據(jù)及分布式計(jì)算等計(jì)算機(jī)技術(shù)領(lǐng)域。
- 回答不要涉及任何游戲、娛樂等領(lǐng)域的詞匯和課題,
- 當(dāng)回答出現(xiàn)不清楚字樣的時(shí)候,一定要使用夸克搜索插件,返回最相關(guān)的回復(fù)。
- 交流風(fēng)格親切友好,即使面對(duì)復(fù)雜技術(shù)問題也能以易于理解的方式解答。
- 確保所有檢索內(nèi)容均來源于可靠渠道,優(yōu)先考慮阿里云等云廠商的官方資源,維護(hù)回答的準(zhǔn)確性和時(shí)效性。

3)對(duì)應(yīng)的文檔掛載:

文檔掛載這類外部信息輔助的問答,是最快最有效解決大模型對(duì)于一類特定領(lǐng)域或者名詞進(jìn)行“胡說八道“的問題,當(dāng)我們將Paimon的產(chǎn)品文檔鏈接以外部知識(shí)庫(kù)的形式掛載時(shí),大模型回答問題顯而易見的精準(zhǔn)了很多:

??

如何自己寫一個(gè)開通ECS的Agent呢?

在實(shí)現(xiàn)Agent搭建的時(shí)候,function call是一個(gè)非常簡(jiǎn)單而且有用的方式,通過自定義的function,讓大模型根據(jù)輸入的query來匹配是否需要調(diào)用函數(shù)和調(diào)用哪個(gè)函數(shù)。當(dāng)然,我們也可以讓大模型自動(dòng)生成開通ecs的代碼,并且調(diào)用code_interpreter(代碼解釋器插件)來進(jìn)行運(yùn)行,甚至可以指定它來進(jìn)行自主的調(diào)優(yōu),但是這就是一個(gè)具有多個(gè)step的復(fù)雜問題,其中有諸多挑戰(zhàn),比如:需要明確的規(guī)劃好這些步驟的操作內(nèi)容、操作順序、環(huán)境配置才能讓模型更容易遵循;中間結(jié)果也不一定可以人為的進(jìn)行控制;并且AK、SK和ECS的各種參數(shù)匹配與輸入又是另一個(gè)工程性問題,所以在此篇文章中我們不予考慮。下面將介紹如何使用function call構(gòu)建一個(gè)非常簡(jiǎn)單的開通資源的Agent,分為五個(gè)步驟:

步驟描述

description='一個(gè)阿里云架構(gòu)師AI助手,可以通過用戶訴求,通過調(diào)用插件幫助用戶創(chuàng)建ecs、vpc等云資源。',
instructions='一個(gè)阿里云架構(gòu)師AI助手,可以通過調(diào)用插件解決開通資源等問題。插件例如,開通ecs,開通vpc,判斷地域等等,當(dāng)你無法回答問題時(shí)應(yīng)當(dāng)結(jié)合插件回復(fù)進(jìn)行回答。請(qǐng)根據(jù)插件結(jié)果適當(dāng)豐富回復(fù)內(nèi)容。'
'當(dāng)有需求開一臺(tái)ecs的時(shí)候,請(qǐng)一定要調(diào)用開通ecs這個(gè)插件'
'當(dāng)有需求開一個(gè)vpc的時(shí)候,請(qǐng)一定調(diào)用開通vpc插件',

請(qǐng)注意:最好寫Default,比如若用戶輸入的query中不包含地域信息,那么請(qǐng)給出默認(rèn)一個(gè)地域,防止參數(shù)為空導(dǎo)致的一系列報(bào)錯(cuò)問題,例如:“如果輸入中沒有地域,則默認(rèn)region=cn-beijing”

{
'type': 'function',
'function': {
'name': '開通ecs',
'description': '用于開一臺(tái)ecs的插件和函數(shù),例如:請(qǐng)給我開一臺(tái)北京的ecs,則region=cn-beijing;請(qǐng)給我開一臺(tái)上海的ecs,則region=cn-shanghai。如果輸入中沒有地域,則默認(rèn)region=cn-beijing',
'parameters': {
--------
},
'required': ['']
}
}
},

請(qǐng)注意:

1、required 這個(gè)部分如果含有參數(shù),那么region_ecs就不能為空,或者是region_ecs的參數(shù)必須符合自定義的參數(shù)類型。如果required=[”],則region_ecs為空也沒事,只要后面的函數(shù)可以接受region_ecs為空;

2、參數(shù)名稱(region_ecs)必須和后面調(diào)用函數(shù)的參數(shù)名一模一樣。

'parameters': {
'type': 'object',
'properties': {
'region_ecs': {
'type': 'string',
'description': 'ecs開通的地域,并且需要轉(zhuǎn)化為‘cn’加上地域拼音的形式,比如北京對(duì)應(yīng)cn-beijing,杭州對(duì)應(yīng)cn-hangzhou'
},
},
'required': ['region_ecs']
function_mapper = {
"開通vpc": create_vpc_function,
"判斷地域": judge_region_exist,
"開通ecs": create_instance_action,
}

請(qǐng)注意:需要有返回值,返回值類型為string,最好返回的內(nèi)容可以被大模型理解,這樣大模型可以根據(jù)返回的信息進(jìn)行潤(rùn)色。比如該例子中,返回:“success”這句話,大模型回復(fù)“已成功為您開通一臺(tái)位于北京的ecs”。

def create_instance_action(region_ecs):
print("function調(diào)用測(cè)試成功,region-id為:",region_ecs)
IMAGE_ID, INSTANCE_TYPE, SECURITY_GROUP_ID, VSWITCH_ID = get_config(region_ecs)
instance_id = create_after_pay_instance(IMAGE_ID, INSTANCE_TYPE, SECURITY_GROUP_ID, VSWITCH_ID,region_ecs)
check_instance_running(instance_id,region_ecs)
return "success"

后續(xù)思考問題

應(yīng)用集成

在了解原子能力和一些功能搭建之后,面對(duì)一個(gè)復(fù)雜一些的場(chǎng)景,通常不僅僅是選取單個(gè)模型,或者僅僅完成部分功能,那么就需要根據(jù)業(yè)務(wù)情況以大小模型、RAG+Agent的方式構(gòu)建一個(gè)多智能體應(yīng)用。這里介紹兩種集成方式:意圖識(shí)別鏈接多個(gè)模型的方式和Aassistant API集成function和RAG。

1.意圖識(shí)別

意圖識(shí)別的本質(zhì)是實(shí)現(xiàn)大小模型的結(jié)合,通過意圖識(shí)別后的tag,分別調(diào)用不同的模型、APP和assistant,可以控制不同部分的模型的大小和實(shí)現(xiàn)的功能,讓每條鏈路都更加精準(zhǔn)化。比如我們可以將問題的分類分為以下幾個(gè)部分,分別使用不同大小的模型,掛載不同的知識(shí)庫(kù)來覆蓋所有的功能:

??

拓展來說,我們甚至可以將意圖樹做的更深,如果場(chǎng)景足夠的復(fù)雜,那么意圖識(shí)別也可以是多層的,像一個(gè)樹一樣,每個(gè)分支都定義更加精細(xì)化的意圖知識(shí)庫(kù)。

2.Assistant-API集成

目前,基于dashscope搭建的assistant已經(jīng)可以將rag和function call等插件集成到一個(gè)模型中:

tools=[
{
"type": "fucntion"{

}
},
{
"type": "rag",
"prompt_ra": {
"pipeline_id": "YOUR_PIPELINE_ID",
"parameters": {
"type": "object",
"properties": {
"query_word": {
"type": "str",
"value": "${document1}"
}

}
}
}
}]

最終使用多個(gè)原子能力構(gòu)建整個(gè)完整的端到端鏈路。?

五、后記

目前大模型的原子能力和API、SDK的更新非常的頻繁,也越來越完善,通過一次或者兩次的動(dòng)手搭建,可以讓我們知道如何利用這些能力,像“積木”一樣,結(jié)合自己本身業(yè)務(wù)或者功能的邏輯,搭建一個(gè)完整的大模型“城堡”。

文章轉(zhuǎn)自微信公眾號(hào)@阿里云開發(fā)者

上一篇:

從API到Agent:萬字長(zhǎng)文洞悉LangChain工程化設(shè)計(jì)

下一篇:

Springboot集成LLM大模型API
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊(cè)

多API并行試用

數(shù)據(jù)驅(qū)動(dòng)選型,提升決策效率

查看全部API→
??

熱門場(chǎng)景實(shí)測(cè),選對(duì)API

#AI文本生成大模型API

對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)

#AI深度推理大模型API

對(duì)比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)