ความคิดหลักของ LangChain Agent คือการใช้ LLM เป็นสมองในการคิดโดยอัตโนมัติ ตัดสินการตัดสินใจ และดำเนินการต่าง ๆ เพื่อสำเร็จภารกิจเป้าหมายของเรา
เกร็ดคำแนะนำ: จากมุมมองการพัฒนา นี่หมายความว่าเราจะพัฒนา API ต่าง ๆ ล่วงหน้า แล้วทำให้เอเจนต์เป็นเหมือนคน โดยที่ LLM จะวิเคราะห์ว่าต้องเรียกใช้ API ไหนเพื่อทำภารกิจ
เพื่อที่จะเข้าใจปัญหาที่ LangChain Agent มีเป้าหมายที่จะแก้, เรามาพิจารณาตัวอย่างกัน
ตัวอย่าง:
ถ้าเราต้องการวิจัยว่า "Docker สามารถใช้เป็นโซลูชันการถ่ายโอนข้อมูลในการใช้งานจริงหรือไม่" เราจะค้นหา "ข้อความนำเสนอ Docker" ใน Baidu และดูผลการค้นหา และจากนั้นค้นหา "ข้อดีและข้อเสียของการใช้ Docker ในการถ่ายโอนข้อมูล" และดูผลการค้นหาเพิ่มเติม และอีกหลายอย่าง จนกระทั่งเราตรวจสอบว่าถึงข้อสรุป
LangChain Agent มีเป้าหมายที่จะจำลองกระบวนการนี้ ฉันสามารถเตรียมชุดเครื่องมือ (เช่น การค้นหาใน Baidu, เครื่องมือแตกต่างสำหรับการสกัดเนื้อหา URL) แล้วให้เอเจนต์เป้าหมาย "Docker สามารถใช้เป็นโซลูชันการถ่ายโอนข้อมูลในการใช้งานจริงหรือไม่?" เจนต์จะสร้างข้อความให้เรียกใช้ LLM โดยเพื่อที่จะทำภารกิจนี้ขั้นต่อไปคือดำเนินการใด (เช่นเรียกใช้เครื่องมือใด) จากระบบจะส่งเครื่องมือที่จะเรียกใช้ออกมา โค้ดจะดำเนินการเครื่องมือนี้และส่งผลการดำเนินการของเครื่องมือกลับไปที่ระบบ และขอคำสั่งการดำเนินการต่อไปของเครื่องมือใด การทำซ้ำกระบวนการนี้จะสำเร็จภารกิจที่กล่าวถึงไว้มีที่สุด
เกร็ดคำแนะนำ: ตั้งแต่การปล่อยมาแบบ GPT นี้เป็นคุณสมบัติที่ดีมาก ทำให้ LLM ทำหน้าที่เป็นสมอง คิดเองและเรียกใช้ API ต่าง ๆ ที่เราพัฒนาไว้ ซึ่งทำให้เสริมความสามารถของ LLM อย่างมาก ปัจจุบันคุณลักษณะนี้อยู่ในช่วงทดลองและจะเรียกใช้ LLM บ่อยครั้ง ดังนั้นจะใช้โทเคนเป็นจำนวนมากในเวลาไม่กี่นาที หากต้องการประหยัดเงิน แนะนำให้ทำให้ LLM ทำงานให้เพียงการตัดสินใจตามตรรกะที่ง่ายง่ายเท่านั้น
หลักการหลัก
ขอนำเสนอว่าง่ายดายคอนเซ็ปต์และองค์บริษัทที่เกี่ยวข้อง
เอเจนต์
เอเจนต์สามารถเข้าใจได้ว่าเป็นผู้ช่วยของเรา ทำงานแทนเราในการตัดสินการตัดสินใจ ในการดำเนินการที่อย่ในระดับล่างของ LangChain Agent, LLM คือบันทึกการตัดสินการตัดสินใจของ AI ผู้ที่สนใจสามารถศึกษาได้ต่อไป
LangChain จะมีการให้บริการเอเจนต์ที่หลากหลายประเภทสำหรับกรณีการใช้งานที่แตกต่างกัน
เครื่องมือ
คิดว่าเครื่องมือนั้นเป็น APIs ที่ถูกเตรียมไว้ก่อนแล้ว มีหลายฟังกชันที่ถูกออกแบบไว้เพื่อขยายความสามารถของ LLM ขณะนี้ LLM กำหนดสิ่อการเรียกใช้ API ที่จะทำภารกิจ
ชุดเครื่องมือ
ชุดเครื่องมือจะให้ LLM มีอย่างน้อย ๆ เครื่องมือไม่ใช่หรือสองเพื่อให้ LLM มีเลือกทำภารกิตมากขึ้นเมื่ทำภารกิจ
ผู้ดำเนินเอเจนต์
ผู้ดำเนินเอเจนต์แทนตัวทำหน้าที่ทำงานในการปฏิบัติตามเครื่องมือ (API) ที่ถูกเลือกโดย LLM โค้ดประสบการณ์การทำงานหาเจนต์คือต่อไป
next_action = agent.get_action(...)
while next_action != AgentFinish:
observation = run(next_action)
next_action = agent.get_action(..., next_action, observation)
return next_action
แม้กระบวนการดำเนินการไม่ใช้ยุ่งยาก แต่ผู้ดำเนินหมุนโฟกัสในประกอบปัญหาที่มีรายละเอียดมากๆ โดยที่เป็นที่สำคัญก็มีด้วย:
- การจัดการโดยที่เอเจนต์เลือกเครื่องมือที่ไม่อยู่ในท้อง
- การจัดการกับสถานการณ์ข้อผิดพลาดของเครื่องมือ
- การจัดการกับสถานการณ์ข้อผิดพลาดของเอเจนต์ที่สร้างผลลัพธ์ที่ไม่สามารถแก้ไขเป็นการเรียกใช้เครื่องมือ
- ปัญหาที่เกิดในช่วงการแก้ปัญหา
การเริ่มต้นการว่างด้วย
ส่วนนี้จะนำเสนอการใช้งานขั้นต้นของเอเจนต์ของ LangChain
1. โหลด LLM
ก่อนอื่นเราจะโหลดภาษาแบบจำลอง (LLM) ที่เราจะใช้ควบคุมเอเจนต์
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
2. กำหนดเครื่องมือ
ต่อมาเราจะกำหนดเครื่องมือบางอย่างเพื่อให้เอเจนต์เรียกใช้ โดยเราจะเขียนฟังก์ชันไพธอนที่ง่ายมาเพื่อคำนวณความยาวของคำที่รับเข้ามา
from langchain.agents import tool
@tool
def get_word_length(word: str) -> int:
"""Returns the length of the word."""
return len(word)
get_word_length.invoke("abc")
หมายเหตุ: คำอธิบายฟังก์ชันเป็นสิ่งที่สำคัญมาก มันบอกให้ LLM รู้ว่ามันสามารถคำนวณความยาวของคำ ซึ่งฟังก์ชัน
get_word_length
บอก LLM ว่ามันสามารถคำนวณคุณค่าของคำ
3
กำหนดชุดเครื่องมือ
tools = [get_word_length]
3. สร้างโปรมป์โปรด
ตอนนี้เรามาสร้างโปรมป์ค่ะ โดยเนื่องจาก OpenAI Function Calling ได้รับการปรับปรุงให้เหมาะสมกับการใช้เครื่องมือมากขึ้น เราไม่จำเป็นต้องมีคำแนะนำเกี่ยวกับการคิดหรือรูปแบบเอ้าท์พุตเลย เรามีเพียงตัวแปรอินพุต 2 ตัว: input
แทนคำถามที่ผู้ใช้ป้อนเข้ามา และ agency_scratchpad
คือตัวยึดยอดสำหรับคำสั่งการเรียกของเอเจนต์ ซึ่งจะถูกแทรกระหว่างโปรมป์ตัวแบบเมื่อรันคำสั่งเรียกเครื่องมือนะคะ
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"You are a very powerful assistant but do not understand the current situation.",
),
("user", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
]
)
4. ผูกเครื่องมือกับ LLM
เอเจนต์ทรงประสิทธิภาพอย่างไรที่จะทราบว่ามีเครื่องมือใดที่สามารถใช้ได้?
นั่นอยู่ที่การเรียกใช้เครื่องมือ OpenAI (แบบโมเดลมากมายรองรับคุณลักษณะที่เหมือนกัน) เราเพียงจำเป็นที่จะต้องบอกโมเดลรูปแบบการเรียกใช้ของเครื่องมือที่ได้กำหนดไว้เท่านั้นค่ะ
llm_with_tools = llm.bind_tools(tools)
5. สร้างเอเจนต์
ตอนนี้ที่เราได้นำเนื้อหาก่อนหน้านี้ผสมเข้าด้วยกันแล้ว เราจึงสามารถดำเนินการสร้างโปรแกรมพร็อกซีตัวแทนได้เลยนะคะ เราจะนำฟังก์ชันยูทิลิตีของสองฟังก์ชันเช่นกันมาใช้: ฟังก์ชันหนึ่งสำหรับจัดรูปแบบขั้นตอนกลาง (การกระทำพร็อกซี, เอ้าท์พุตของเครื่องมือ) เข้าไปในข้อความอินพุตที่สามารถส่งถึงโมเดลได้ และอีกอันสำหรับการแปลงข้อความเอ้าท์พุตให้เป็นการกระทำพร็อกซี/สิ้นสุดของเพร็กซี
from langchain.agents.format_scratchpad.openai_tools import format_to_openai_tool_messages
from langchain.agents.output_parsers.openai_tools import OpenAIToolsAgentOutputParser
agent = (
{
"input": lambda x: x["input"],
"agent_scratchpad": lambda x: format_to_openai_tool_messages(x["intermediate_steps"]),
}
| prompt
| llm_with_tools
| OpenAIToolsAgentOutputParser()
)
กำหนดตัวประมวลผลเอเจนต์
from langchain.agents import AgentExecutor
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
เรามาสาธิตการดำเนินการของโปรแกรมพร็อกซีเลยค่ะ:
list(agent_executor.stream({"input": "How many letters are there in the word 'eudca'?"}))
ตัวอย่างบันทึกเอ้าท์พุตของเอเจนต์
> เข้าสู่โซนปฏิบัติการของอีเจนต์ใหม่...
การเรียกใช้: กำลังรัน `get_word_length` โดยใช้พารามิเตอร์ `{'word': 'educa'}`
คำว่า "educa" มี 5 ตัวอักษรค่ะ
> สิ้นสุดโซนปฏิบัติการ
ผ่านตัวอย่างนี้เราได้อธิบายกระบวนการทั้งหมดของโปรแกรมพร็อกซีเป็นที่เรียบร้อยแล้วนะคะ
เพิ่มความสามารถในการจดจำให้กับเอเจนต์
หากเราต้องการให้เอเจนต์จำข้อความที่สนทนาไปก่อนหน้านี้ เราสามารถทำได้ง่ายๆเพียงที่เพิ่มเนื้อหาที่ AI ส่งออกมาไปใส่ในโปรมป์ และส่งต่อไปยัง AI พร้อมๆกัน
การปรับเปลี่ยนแม่แบบโปรมป์
ด้านล่างเป็นการปรับเปลี่ยนแม่แบบโปรมป์เพื่อรวมเทมเพลทประวัติการสนทนาด้วยค่ะ
from langchain.prompts import MessagesPlaceholder
MEMORY_KEY = "chat_history"
prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"You are a great assistant, but not good at calculating the length of words.",
),
MessagesPlaceholder(variable_name=MEMORY_KEY),
("user", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
]
)
การปรับเปลี่ยนการนิยามกระบวนการเอเจนต์
ปรับเปลี่ยนการนิยามกระบวนการของเอเจนต์เพื่อให้สามารถให้ข้อมูลประวัติการสนทนาสำหรับเทมเพลทโปรมป์ ดังโค้ดด้านล่างค่ะ การเตรียม chat_history
parameter handling เข้าไป
agent = (
{
"input": lambda x: x["input"],
"agent_scratchpad": lambda x: format_to_openai_tool_messages(
x["intermediate_steps"]
),
"chat_history": lambda x: x["chat_history"],
}
| prompt
| llm_with_tools
| OpenAIToolsAgentOutputParser()
)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
chat_history = []
input1 = "How many letters are there in the word 'educa'?"
result = agent_executor.invoke({"input": input1, "chat_history": chat_history})
chat_history.extend(
[
HumanMessage(content=input1),
AIMessage(content=result["output"]),
]
)
agent_executor.invoke({"input": "Does this word really exist?", "chat_history": chat_history})
ในกรณีธุรกิจจริง ๆ คุณสามารถบันทึกประวัติการสนทนาไปยังฐานข้อมูล และแทรกข้อมูลลงในโพรมป์ตามต้องการของธุรกิจ
เคล็ดลับ: ฟังก์ชันการจดจำของโมเดลขนาดใหญ่ (LLM) ในปัจจุบันมักปฏิบัติโดยการแทรกเนื้อหาการสนทนาประวัติเก่าลงในโพรมป์ และส่งข้อมูลไปยัง LLM ได้อย่างง่ายดาย แต่ LangChain ยังมีการห่อหุ้มบางส่วน คุณสามารถเลือกที่จะไม่ใช้หรือเชื่อมต่อประวัติการสนทนาอย่างด้วยตัวและเชื่อมต่อโดยตนเองเข้ากับแม่แบบโพรม ณ คราวนั้น