LCEL পরিচিতি
LCEL (LangChain Expression Language) হল একটি শক্তিশালী ওয়ার্কফ্লো সংরচনা টুল, যা আপনাকে বেসিক কোম্পোনেন্ট থেকে জটিল কাজ চেইন তৈরি করতে দেয় এবং স্ট্রিমিং প্রসেসিং, সমলিং প্রসেসিং, এবং লগিং সহ আউট-অফ-দি-বক্স ফিচার সমর্থন করে।
মৌলিক উদাহরণ: প্রম্পট + মডেল + আউটপুট পার্সার
এই উদাহরণে, আমরা দেখাবো কীভাবে LCEL (LangChain Expression Language) ব্যবহার করে তিনটি কম্পোনেন্ট - প্রম্পট টেমপ্লেট, মডেল, এবং আউটপুট পার্সার - একত্রিত করে "জোক" বলার কাজের জন্য একটি সম্পূর্ণ ওয়ার্কফ্লো তৈরি করতে পারি। কোডটি দেখায় কীভাবে চেইন তৈরি করতে হয়, পাইপ সিম্বল |
ব্যবহার করে বিভিন্ন কম্পোনেন্ট যুক্ত করতে হয়, এবং প্রতিটি কম্পোনেন্টের ভূমিকা এবং আউটপুট ফলাফল প্রস্তুত করা হয়।
প্রথমে, আসুন দেখি কীভাবে প্রম্পট টেমপ্লেট এবং মডেল যুক্ত করে একটি বিশেষ বিষয়ের উপর জোক তৈরি করতে হয়:
Dependencies ইনস্টল করুন
%pip install --upgrade --quiet langchain-core langchain-community langchain-openai
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
prompt = ChatPromptTemplate.from_template("{topic} সম্পর্কে আমাকে একটি জোক বলুন")
model = ChatOpenAI(model="gpt-4")
output_parser = StrOutputParser()
chain = prompt | model | output_parser
chain.invoke({"topic": "আইসক্রিম"})
আউটপুট
"কেনো পার্টিতে আইসক্রিমকে পৌনা করা হয়না? কারণ এটি গরম হলে গলিয়ে পড়ে!"
এই কোডে, আমরা LCEL ব্যবহার করে বিভিন্ন কম্পোনেন্টগুলি চেইনে যোগ করেছি:
chain = prompt | model | output_parser
এখানে |
সিম্বলটি উদাহরণটি একইভাবে Unix পাইপ অপারেটরের মতো, যা বিভিন্ন কম্পোনেন্টগুলি যোগ করে এবং একটি কম্পোনেন্টের আউটপুটকে পরবর্তী কম্পোনেন্টের ইনপুট হিসাবে পাঠায়।
এই চেইনে, ব্যবহারকারী ইনপুটটি প্রথমে প্রম্পট টেমপ্লেটে পাঠায়, তারপরে প্রম্পট টেমপ্লেটের আউটপুটটি মডেলে পাঠায়, এবং চেষ্টা করে আমাদের মডেল এর আউটপুটটি আউটপুট পার্সারে পাঠায়। অনুগ্রহ করে পৃথকভাবে কীভাবে প্রতিটি কম্পোনেন্টগুলির সাথে যোগাযোগ করা হয়েছে এটা বেশি স্পষ্ট করার জন্য।
1. প্রম্পট
prompt
হল BasePromptTemplate
, যা একটি টেমপ্লেট ভ্যারিয়েবল ডিকশনারি গ্রহণ করে এবং PromptValue
তৈরি করে। PromptValue
হল একটি প্রম্পট ধারণ করা Wrapped object
, যা LLM
(স্ট্রিং ফর্মে ইনপুট হিসাবে) বা ChatModel
(মেসেজ সিকোয়েন্স হিসাবে ইনপুট হিসাবে) এর সাথে ব্যবহার করা যেতে পারে। এটি যেকোনো ধরনের ভাষার মডেল এর সাথে ব্যবহার করা যেতে পারে, কারণ এটি BaseMessage
তৈরি এবং স্ট্রিং তৈরির লজিক উল্লেখ করে।
prompt_value = prompt.invoke({"topic": "আইসক্রিম"})
prompt_value
আউটপুট
ChatPromptValue(messages=[HumanMessage(content='আমাকে একটি জোক বলুন আইসক্রিমের বিষয়ে')])
নীচে, আমরা প্রম্পট ফরম্যাট করা ফলাফলটি চ্যাট মডেলগুলি দ্বারা ব্যবহার করা ফরম্যাটে রূপান্তর করেছি:
prompt_value.to_messages()
আউটপুট
[HumanMessage(content='আমাকে একটি জোক বলুন আইসক্রিমের বিষয়ে')]
এটি সরাসরি স্ট্রিং এবং রূপান্তর করা
prompt_value.to_string()
আউটপুট
'মানুষ: আমাকে একটি জোক বলুন আইসক্রিমের বিষয়ে।'
2. মডেল
পরবর্তী, PromptValue
টি মডেল করুন। এই উদাহরণে, আমাদের model
একটি ChatModel
, যার মানে হল এটি একটি BaseMessage
আউটপুট করবে।
আমরা প্রথমে model
কে সরাসরি কল করে দেখতে পারি:
message = model.invoke(prompt_value)
message
ফেরত আসে:
AIMessage(content="কেনো পার্টিতে আইসক্রিমকে পৌনা করা হয়না? কারণ এটি গরম হলে গলিয়ে পড়ে!")
আমাদের model
যদি LLM
ধরনে নির্ধারিত করা হয়, তাহলে এটি একটি স্ট্রিং আউটপুট করবে।
from langchain_openai.llms import OpenAI
llm = OpenAI(model="gpt-3.5-turbo-instruct")
llm.invoke(prompt_value)
মডেল ফেরত দেয়:
'\n\nবট: কেনো আইসক্রিম ট্রাক বিগড়ে গেছে? কারণ এটা শীতল রাখার জন্য মেল্ট হয়ে গেছে!'
3. আউটপুট পার্সার
আমাদের মডেল থেকে সরাসরি আউটপুট টি আউটপুট পার্সারে পাঠানো হয়, যা একটি BaseOutputParser
, অর্থাৎ এটি স্ট্রিং বা BaseMessage
কে ইনপুট হিসাবে গ্রহণ করে। StrOutputParser
নির্দিষ্টভাবে যে কোন ইনপুটকে একটি সাধারণ স্ট্রিংতে রূপান্তর করে।
output_parser.invoke(message)
কেনো আইসক্রিম ট্রাক বিগড়ে গেছে? কারণ এটা শীতল রাখার জন্য মেল্ট হয়ে গেছে!
৪. সম্পূর্ণ প্রক্রিয়া
বিচারণার প্রক্রিয়া নিম্নলিখিত:
-
chain.invoke({"topic": "ice cream"})
কল করুন, যা আমরা সংজ্ঞায়িত ওয়ার্কফ্লো আরম্ভ করে এবং "আইসক্রিম" সম্পর্কিত জোকের জন্য প্যারামিটার{"topic": "ice cream"}
পাস করে। - প্রথম চেইনের কল প্যারামিটার
{"topic": "ice cream"}
পাস করা,prompt
, যা প্রম্পট টেম্পলেট বিন্যাস করে "আইসক্রিম" সম্পর্কিত প্রম্পটTell me a little joke about ice cream
পেতে। - প্রম্পট
Tell me a little joke about ice cream
কেmodel
(gpt4 মডেল) এ পাস করুন। -
model
দ্বারা প্রাপ্ত ফলাফলকেoutput_parser
আউটপুট পার্সারে পাস করুন, যা মডেলের ফলাফল বিন্যাস করে এবং চেষ্টা প্রশ্নটি পাস করে।
যদি আপনি কোনও কোম্পোনেন্টের আউটপুট-এ আগ্রহী হন, তবে আপনি সাধারণভাবে চেইনের ছোট সাইজের একটি টেস্ট করতে পারেন, উদাহরণস্বরূপ prompt
অথবা prompt | model
, যাতে আপনি মধ্যমিক ফলাফলগুলি দেখতে পান:
input = {"topic": "ice cream"}
prompt.invoke(input)
(prompt | model).invoke(input)
RAG খোঁজার উদাহরণ
পরবর্তী, আসুন একটি বেশি জটিল LCEL উদাহরণ স্পষ্ট করি। আমরা জিজ্ঞাসা উত্তর দেওয়ার সময় কিছু প্রাথমিক তথ্য যোগ করার জন্য মজবুত পুনর্নিয়েন চালু করতে নির্দেশিত রিট্রিভাল একজনের উদাহরণ দিব।
from langchain_community.vectorstores import DocArrayInMemorySearch
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_openai.chat_models import ChatOpenAI
from langchain_openai.embeddings import OpenAIEmbeddings
vectorstore = DocArrayInMemorySearch.from_texts(
["harrison worked at kensho", "bears like to eat honey"],
embedding=OpenAIEmbeddings(),
)
retriever = vectorstore.as_retriever()
template = """Answer the question based only on the following context:
{context}
Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
model = ChatOpenAI()
output_parser = StrOutputParser()
setup_and_retrieval = RunnableParallel(
{"context": retriever, "question": RunnablePassthrough()}
)
chain = setup_and_retrieval | prompt | model | output_parser
chain.invoke("where did harrison work?")
এই মামলায়, বিচারণার সংযোজিত চেইন হল:
chain = setup_and_retrieval | prompt | model | output_parser
সাধারণভাবে, উপরের প্রম্পট টেমপ্লেটটি context
এবং question
মান গ্রহণ করার জন্য। প্রম্পট টেম্পলেটটি গড়ে নেয় এবং প্রম্পট তৈরি করতে সংশ্লিষ্ট নথির ডকুমেন্টগুলি পাওয়ার জন্য আমরা আগের দিকে সম্পর্কিত ডকুমেন্ট প্রাপ্তের জন্য DocArrayInMemorySearch
ব্যবহার করতে চাই। এটা একটি চেইনযোগ্য রানাবল কম্পোনেন্ট, তবে আপনি এটি আলাদা করে চালিয়ে যেতে পারেন:
retriever.invoke("where did harrison work?")
তারপর, আমরা প্রম্পটের জন্য ইনপুট প্রস্তুত করার জন্য RunnableParallel
ব্যবহার করি, রিট্রিভার ব্যবহার করে ডকুমেন্ট সন্ধান করে, এবং RunnablePassthrough
ব্যবহার করে ব্যবহারকারীর প্রশ্ন পাস করে:
setup_and_retrieval = RunnableParallel(
{"context": retriever, "question": RunnablePassthrough()}
)
সংক্ষেপণ করা যায়:
setup_and_retrieval = RunnableParallel(
{"context": retriever, "question": RunnablePassthrough()}
)
chain = setup_and_retrieval | prompt | model | output_parser
প্রক্রিয়াটি এমনঃ
- প্রথমে, একটি
RunnableParallel
অবজেক্ট তৈরি করুন যা দুটি এন্ট্রি বিশিষ্ট করেছে। প্রথম এন্ট্রিমilূ
কে 'retriever' দ্বারা নিয়োজিত ডকুমেন্টের ফল প্রস্তুত করে। দ্বিতীয় এন্ট্রিquestion
ব্যবহারকারীর মূল প্রশ্ন ধরে। প্রশ্নটি পাঠাতে আমরা এই এন্ট্রিকে অনুমতি প্রদান করতে হবেRunnablePassthrough
ব্যবহার করে। - প্রায়: আমাদেরাত্র
prompt
কম্পোনেন্টের জন্য পূর্বের পদক্ষেপ থেকে ডিকশনারি প্রেরণ করুন। এটি ইউজার ইনপুট গ্রহণ (অর্থাৎ,question
) সহ প্রাপ্ত ডকুমেন্টগুলি (অর্থাৎ,context
) গ্রহণ করতে প্রথিত হয়, প্রম্পট গড়ে নেয় এবংprompt_value
আউটপুট করে। -
model
কম্পোনেন্ট গড়ে নেওয়া প্রম্পট নেওয়া এবং ওপেনএআই এর LLM মডেলে মূল্যায়নের জন্য মুহূর্তের প্রম্পট পাঠায়। মডেল দ্বারা পোষ্যমান আউটপুট মনাবে। - শেষে,
output_parser
কম্পোনেন্ট একটিChatMessage
নেয়, এটি Python স্ট্রিং এ রূপান্তরে আন এবং তা থেকেinvoke
মেথড বাদ দেয়।