作者:
智能體 AI Agent 作為大模型的衍生應(yīng)用,具有對任務(wù)的理解、規(guī)劃與行動能力。它可以通過將一個復(fù)雜的用戶請求拆分成不同的子任務(wù),并依次調(diào)用外部工具來解決這些任務(wù),并將其中每個任務(wù)步驟的執(zhí)行結(jié)果,按預(yù)先規(guī)劃的邏輯串聯(lián)起來,從而達(dá)成最終的目的。
接下來我們就通過一個例子,演示如何利用 OpenVINO 工具套件在你的電腦上的一步步搭建本地智能體流水線。
1轉(zhuǎn)換壓縮LLM
首先要需要利用 Hugging Face 的 Optimum-intel 命令行工具將原始模型轉(zhuǎn)化為 OpenVINO 的 IR 格式,并對其進(jìn)行 int4 量化壓縮,以實現(xiàn)本地部署的目的。這里我們選擇通義千問團(tuán)隊近期發(fā)布的 Qwen2.5 大語言模型為例,它可以支持多種不同語言。其中最小3B參數(shù)版本的模型便可以對本示例進(jìn)行復(fù)現(xiàn)。
!optimum-cli export openvino --model "Qwen/Qwen2.5-3B-Instruct"--task text-generation-with-past --trust-remote-code --weight-format int4 --group-size 128 --ratio 1.0 --sym “Qwen2.5-3B-Instruct-int4-ov”
其中"Qwen/Qwen2.5-3B-Instruct"為模型的 HuggingFace 的模型 ID,如果在訪問 Hugging Face 模型倉庫時,發(fā)現(xiàn)網(wǎng)絡(luò)限制,也可以通過 ModelScope 將原始模型下載到本地,并將該模型 ID 替換為模型的本地路徑,例如:"./model/Qwen2.5-3B-Instruct"。
2創(chuàng)建LLM任務(wù)
第二步同樣可以利用 Optimum-intel 提供的 OpenVINO API 接口將模型部署在指定的硬件平臺,這里可以通過指定 device=”gpu” 將模型加載到任意一個 Intel 的獨(dú)顯或是集顯上,以最大化模型推理性能。
tokenizer = AutoTokenizer.from_pretrained(llm_model_path, trust_remote_code=True)
ov_config = {hints.performance_mode(): hints.PerformanceMode.LATENCY, streams.num(): "1", props.cache_dir(): ""}
llm = OVModelForCausalLM.from_pretrained(
llm_model_path,
device=llm_device.value,
ov_config=ov_config,
config=AutoConfig.from_pretrained(llm_model_path, trust_remote_code=True),
trust_remote_code=True,
)
除了對模型對象進(jìn)行初始化以外,還需要創(chuàng)建針對模型推理輸出的后處理函數(shù),主要目的是為了實現(xiàn)流式輸出,以及設(shè)置停止字符,讓 LLM 在調(diào)用工具前停止推理任務(wù)。
def text_completion(prompt: str, stop_words) -> str:
im_end = "<|im_end|>"
if im_end not in stop_words:
stop_words = stop_words + [im_end]
streamer = TextStreamer(tokenizer, timeout=60.0, skip_prompt=True, skip_special_tokens=True)
stopping_criteria = StoppingCriteriaList([StopSequenceCriteria(stop_words, tokenizer)])
input_ids = torch.tensor([tokenizer.encode(prompt)])
generate_kwargs = dict(
input_ids=input_ids,
streamer=streamer,
stopping_criteria=stopping_criteria,
)
output = llm.generate(**generate_kwargs)
output = output.tolist()[0]
output = tokenizer.decode(output, errors="ignore")
assert output.startswith(prompt)
output = output[len(prompt) :].replace("<|endoftext|>", "").replace(im_end, "")
for stop_str in stop_words:
idx = output.find(stop_str)
if idx != -1:
output = output[: idx + len(stop_str)]
return output
3定義智能體Prompt模板
這一步也是決定智能體工作模式的關(guān)鍵,通過 Prompt 模板,我們將教會 LLM 一個常規(guī)任務(wù)的解決路徑,以及有哪些類別的外部工具可能幫助它解決特定問題??梢钥吹皆谙旅孢@個典型 ReAct 類 Prompt 模板中,我們定義外部工具的具體信息模板,以及 LLM 在執(zhí)行任務(wù)過程中的輸出模板,其中 “Observation” 后內(nèi)容為外部工具調(diào)用后返回的結(jié)果,并非由 LLM 直接生成。可以看到在該模板中, LLM 可能會被執(zhí)行多次,直到上下文中的信息足夠回答用戶請求。
TOOL_DESC = """{name_for_model}: Call this tool to interact with the {name_for_human} API. What is the {name_for_human} API useful for? {description_for_model} Parameters: {parameters}"""
PROMPT_REACT = """Answer the following questions as best you can. You have access to the following APIs:
{tools_text}
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tools_name_text}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can be repeated zero or more times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question:{query}"""
4輸出過濾與工具定義
由于智能體需要和外部工具頻繁交互,發(fā)出指令并獲取工具反饋結(jié)果,因此我們需要在 LLM 輸出時,判斷哪些關(guān)鍵詞代表模型需要調(diào)用工具,哪些關(guān)鍵詞代表收集工具反饋結(jié)果。在這里例子中,當(dāng) LLM 輸出 “Action:" 后的字符,代表接下來需要調(diào)用的工具函數(shù)名稱,輸出 “Action Input” 后的字符,代表輸入給該工具的輸入?yún)?shù),以及 “Observation” 代表接下來需要直接輸出工具的執(zhí)行結(jié)果,因此它也是終止當(dāng)前 LLM 推理任務(wù)的特殊字符。
def parse_latest_tool_call(text):
tool_name, tool_args = "", ""
i = text.rfind("
Action:")
j = text.rfind("
Action Input:")
k = text.rfind("
Observation:")
if 0 <= i < j: # If the text has `Action` and `Action input`,
if k < j: # but does not contain `Observation`,
# then it is likely that `Observation` is ommited by the LLM,
# because the output text may have discarded the stop word.
text = text.rstrip() + "
Observation:" # Add it back.
k = text.rfind("
Observation:")
tool_name = text[i + len("
Action:") : j].strip()
tool_args = text[j + len("
Action Input:") : k].strip()
text = text[:k]
????return?tool_name,?tool_args,?text
為了告訴 LLM 什么時候該調(diào)用什么工具,以及這些工具的基本輸入和輸入?yún)?shù)格式,我們在完成工具函數(shù)的編寫后,還需要以字典的形式,將這些信息送入先前定義的 Prompt 模板中,參考示例如下:
tools = [
{
"name_for_human": "get weather",
"name_for_model": "get_weather",
"description_for_model": 'Get the current weather in a given city name."',
"parameters": [
{
"name": "city_name",
"description": "City name",
"required": True,
"schema": {"type": "string"},
}
],
},
{
"name_for_human": "image generation",
"name_for_model": "image_gen",
"description_for_model": "AI painting (image generation) service, input text description, and return the image URL drawn based on text information.",
"parameters": [
{
"name": "prompt",
"description": "describe the image",
"required": True,
"schema": {"type": "string"},
}
],
},
]
在這個例子中,我們定義一個天氣查詢工具以及一個文生圖工具,他們分別會調(diào)用響應(yīng)的 API 服務(wù)完成響應(yīng)任務(wù)。
5構(gòu)建智能體
接下來我們需要將以上定義的函數(shù)串聯(lián)起來,構(gòu)建一個簡單的智能體流水線。第一步會將用戶請求經(jīng) Prompt 模板格式化后送入 LLM,接下來解析 LLM 輸出,并判斷是否需要調(diào)用外部工具 “Action” 。如果需要調(diào)用外部工具,則智能體會運(yùn)行該工具函數(shù),獲得運(yùn)行結(jié)果,最后將結(jié)果數(shù)據(jù)合并到下一輪的輸入 Prompt 中,由 LLM 判斷是否還需要再次調(diào)用其他工具,再進(jìn)行一次循環(huán),如果不需要調(diào)用工具,并且當(dāng)前得到的信息已經(jīng)可以滿足用戶請求,那 LLM 將整合并基于這個過程中所有的 “Observation” 信息,輸出最終答案 “Final Answer”。
while True:
output = text_completion(planning_prompt + text, stop_words=["Observation:", "Observation:
"])
action, action_input, output = parse_latest_tool_call(output)
if action:
observation = call_tool(action, action_input)
output += f"
Observation: = {observation}
Thought:"
observation = f"{observation}
Thought:"
print(observation)
text += output
else:
text += output
break
該示例的運(yùn)行效果如下,這里我們讓智能體“根據(jù)當(dāng)前倫敦的天氣,生成一張大本鐘的照片”??梢钥吹街悄荏w按照我們既定的 Prompt 策略,將用戶問題拆分后,分別調(diào)用預(yù)先定義的不同工具,根據(jù)用戶要求得到最終結(jié)果。當(dāng)然你也可以用中文向它發(fā)出請求。
query = "get the weather in London, and create a picture of Big Ben based on the weather information" response,history=llm_with_tool(prompt=query,history=history,list_of_tool_info=tools)
“Thought: First, I need to use the get_weather API to get the current weather in London.
Action: get_weather
Action Input: {"city_name": "London"}
Observation:
{'current_condition': {'temp_C': '11', 'FeelsLikeC': '10', 'humidity': '94', 'weatherDesc': [{'value': 'Overcast'}], 'observation_time': '12:23 AM'}}
Thought:
Now that I have the weather information, I will use the image_gen API to generate an image of Big Ben based on the weather conditions.
Action: image_gen
Action Input: {"prompt": "Big Ben under overcast sky with temperature 11°C and humidity 94%"}
Observation:
{"image_url": "https://image.pollinations.ai/prompt/Big%20Ben%20under%20overcast%20sky%20with%20temperature%2011%C2%B0C%20and%20humidity%2094%25"}
Thought:
The image has been generated successfully.
Final Answer: The current weather in London is overcast with a temperature of 11°C and humidity of 94%. Based on this information, here is the image of Big Ben under an overcast sky: “
6總結(jié)
該示例以 OpenVINO 作為 LLM 的推理后端,一步步構(gòu)建起了一個簡單的智能體流水線,可以看到這個示例中除了 Optimum-intel,沒有其他外部依賴需要安裝,因此它也是一個非?;A(chǔ)的的智能體構(gòu)建過程。除此以外,該示例使用 3B 大小 SLM 便可以實現(xiàn)該智能體的構(gòu)建,同時帶來不錯的性能表現(xiàn),是非常適合在本地構(gòu)建的智能體示例。
-
流水線
+關(guān)注
關(guān)注
0文章
127瀏覽量
27232 -
AI
+關(guān)注
關(guān)注
91文章
39793瀏覽量
301443 -
模型
+關(guān)注
關(guān)注
1文章
3752瀏覽量
52111 -
OpenVINO
+關(guān)注
關(guān)注
0文章
118瀏覽量
768
原文標(biāo)題:從0到1構(gòu)建 OpenVINO? 智能體流水線|開發(fā)者實戰(zhàn)
文章出處:【微信號:英特爾物聯(lián)網(wǎng),微信公眾號:英特爾物聯(lián)網(wǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
流水線基本結(jié)構(gòu)
FPGA中的流水線設(shè)計
周期精確的流水線仿真模型
流水線中的相關(guān)培訓(xùn)教程[1]
流水線中的相關(guān)培訓(xùn)教程[4]
FPGA之流水線練習(xí)(3):設(shè)計思路
FPGA之為什么要進(jìn)行流水線的設(shè)計
如何選擇合適的LED生產(chǎn)流水線輸送方式
嵌入式_流水線
利用OpenVINO搭建本地智能體流水線
評論