در هسته آن، LangChain یک چارچوب نوآورانه است که برای ساخت برنامههایی طراحی شده است که از قابلیتهای مدلهای زبانی استفاده میکند. این یک جعبه ابزار است که برای توسعه دهندگان طراحی شده است تا برنامه هایی ایجاد کنند که از زمینه آگاه باشند و قادر به استدلال پیچیده باشند.
این بدان معناست که برنامههای LangChain میتوانند زمینه را درک کنند، مانند دستورالعملهای سریع یا پاسخهای زمینهسازی محتوا و از مدلهای زبان برای کارهای استدلالی پیچیده، مانند تصمیمگیری در مورد نحوه پاسخگویی یا اقداماتی که باید انجام دهند، استفاده کنند. LangChain نشان دهنده یک رویکرد یکپارچه برای توسعه برنامه های کاربردی هوشمند است که سفر از مفهوم تا اجرا را با اجزای متنوع خود ساده می کند.
درک LangChain
LangChain بسیار بیشتر از یک چارچوب است. این یک اکوسیستم تمام عیار است که از چندین بخش جدایی ناپذیر تشکیل شده است.
- در مرحله اول، کتابخانه های LangChain وجود دارد که هم در پایتون و هم در جاوا اسکریپت موجود است. این کتابخانه ها ستون فقرات LangChain هستند و رابط ها و ادغام هایی را برای اجزای مختلف ارائه می دهند. آنها یک زمان اجرا اولیه را برای ترکیب این اجزا در زنجیره ها و عوامل منسجم به همراه پیاده سازی های آماده برای استفاده فوری فراهم می کنند.
- بعد، ما قالب های LangChain را داریم. اینها مجموعه ای از معماری های مرجع قابل استقرار هستند که برای مجموعه وسیعی از وظایف طراحی شده اند. چه در حال ساخت یک چت بات یا یک ابزار تحلیلی پیچیده باشید، این الگوها نقطه شروع محکمی را ارائه می دهند.
- LangServe به عنوان یک کتابخانه همه کاره برای استقرار زنجیره های LangChain به عنوان API های REST وارد عمل می شود. این ابزار برای تبدیل پروژه های LangChain شما به خدمات وب قابل دسترسی و مقیاس پذیر ضروری است.
- در نهایت، LangSmith به عنوان یک پلت فرم توسعه دهنده خدمت می کند. این برای اشکال زدایی، آزمایش، ارزیابی و نظارت بر زنجیره های ساخته شده بر روی هر چارچوب LLM طراحی شده است. ادغام یکپارچه با LangChain آن را به ابزاری ضروری برای توسعه دهندگانی تبدیل می کند که قصد دارند برنامه های خود را اصلاح و کامل کنند.
این مؤلفهها با هم به شما امکان میدهند تا برنامهها را با سهولت توسعه، تولید و به کار ببرید. با LangChain، با نوشتن برنامه های خود با استفاده از کتابخانه ها، ارجاع به الگوها برای راهنمایی شروع می کنید. سپس LangSmith به شما در بازرسی، آزمایش و نظارت بر زنجیرههای خود کمک میکند و اطمینان حاصل میکند که برنامههای شما دائماً بهبود مییابند و آماده استقرار هستند. در نهایت، با LangServe، شما به راحتی می توانید هر زنجیره ای را به یک API تبدیل کنید، و استقرار را آسان کنید.
در بخشهای بعدی، نحوه راهاندازی LangChain و شروع سفر شما در ایجاد برنامههای کاربردی هوشمند و مبتنی بر مدل زبان را عمیقتر خواهیم کرد.
کارها و گردشهای کار دستی را با سازنده گردش کار مبتنی بر هوش مصنوعی، که توسط Nanonets برای شما و تیمهایتان طراحی شده است، خودکار کنید.
نصب و راه اندازی
آیا آماده شیرجه زدن به دنیای LangChain هستید؟ راهاندازی آن ساده است و این راهنما شما را گام به گام این فرآیند را راهنمایی میکند.
اولین قدم در سفر LangChain نصب آن است. با استفاده از پیپ یا کوندا می توانید این کار را به راحتی انجام دهید. دستور زیر را در ترمینال خود اجرا کنید:
pip install langchain
برای کسانی که جدیدترین ویژگی ها را ترجیح می دهند و با کمی ماجراجویی راحت هستند، می توانید LangChain را مستقیماً از منبع نصب کنید. مخزن را کلون کنید و به آن بروید langchain/libs/langchain
فهرست راهنما. سپس اجرا کنید:
pip install -e .
برای ویژگی های آزمایشی، نصب را در نظر بگیرید langchain-experimental
. این بسته حاوی کدهای پیشرفته است و برای اهداف تحقیقاتی و آزمایشی در نظر گرفته شده است. آن را با استفاده از:
pip install langchain-experimental
LangChain CLI یک ابزار مفید برای کار با قالب های LangChain و پروژه های LangServe است. برای نصب LangChain CLI از:
pip install langchain-cli
LangServe برای استقرار زنجیره های LangChain شما به عنوان REST API ضروری است. در کنار LangChain CLI نصب می شود.
LangChain اغلب نیاز به ادغام با ارائه دهندگان مدل، فروشگاه های داده، API ها، و غیره دارد. برای این مثال، ما از API های مدل OpenAI استفاده خواهیم کرد. بسته OpenAI Python را با استفاده از:
pip install openai
برای دسترسی به API، کلید OpenAI API خود را به عنوان یک متغیر محیطی تنظیم کنید:
export OPENAI_API_KEY="your_api_key"
از طرف دیگر، کلید را مستقیماً در محیط پایتون خود ارسال کنید:
import os
os.environ['OPENAI_API_KEY'] = 'your_api_key'
LangChain امکان ایجاد برنامه های کاربردی مدل زبان را از طریق ماژول ها فراهم می کند. این ماژول ها می توانند به تنهایی یا برای موارد استفاده پیچیده ساخته شوند. این ماژول ها عبارتند از -
- مدل ورودی/خروجی: تعامل با مدل های مختلف زبان را تسهیل می کند و ورودی ها و خروجی های آنها را به طور موثر مدیریت می کند.
- بازیابی: دسترسی و تعامل با داده های خاص برنامه را فعال می کند که برای استفاده پویا از داده ها بسیار مهم است.
- عوامل: توانمندسازی برنامهها برای انتخاب ابزارهای مناسب بر اساس دستورالعملهای سطح بالا، افزایش قابلیتهای تصمیمگیری.
- زنجیر: ترکیبات از پیش تعریف شده و قابل استفاده مجدد را ارائه می دهد که به عنوان بلوک های سازنده برای توسعه برنامه عمل می کنند.
- حافظه: وضعیت برنامه را در اجرای چندین زنجیره حفظ می کند، که برای تعاملات آگاه از زمینه ضروری است.
هر ماژول نیازهای توسعه خاصی را هدف قرار می دهد و LangChain را به یک جعبه ابزار جامع برای ایجاد برنامه های کاربردی مدل زبان پیشرفته تبدیل می کند.
در کنار مولفه های فوق نیز داریم زبان بیان LangChain (LCEL)، که یک روش اعلامی برای ترکیب آسان ماژول ها با هم است و این امکان زنجیره بندی مؤلفه ها را با استفاده از یک رابط جهانی Runnable فراهم می کند.
LCEL چیزی شبیه به این است -
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import BaseOutputParser # Example chain
chain = ChatPromptTemplate() | ChatOpenAI() | CustomOutputParser()
اکنون که به اصول اولیه پرداختیم، به موارد زیر ادامه می دهیم:
- هر یک از ماژول های Langchain را با جزئیات بیشتر حفاری کنید.
- یاد بگیرید که چگونه از زبان بیان LangChain استفاده کنید.
- موارد استفاده رایج را کاوش کرده و آنها را اجرا کنید.
- یک برنامه انتها به انتها را با LangServe مستقر کنید.
- LangSmith را برای اشکال زدایی، آزمایش و نظارت بررسی کنید.
بیا شروع کنیم!
ماژول I: مدل I/O
در LangChain، عنصر اصلی هر برنامه کاربردی حول مدل زبان می چرخد. این ماژول بلوک های ساختمان ضروری را برای ارتباط موثر با هر مدل زبانی فراهم می کند و از یکپارچگی و ارتباط یکپارچه اطمینان می دهد.
اجزای اصلی مدل I/O
- مدلهای LLM و چت (به جای هم استفاده میشوند):
- LLMs:
- تعریف: مدل های تکمیل متن خالص.
- ورودی خروجی: یک رشته متن را به عنوان ورودی بگیرید و یک رشته متن را به عنوان خروجی برگردانید.
- مدل های چت
- LLMs:
- تعریف: مدل هایی که از یک مدل زبان به عنوان پایه استفاده می کنند اما در قالب های ورودی و خروجی متفاوت هستند.
- ورودی خروجی: لیستی از پیام های چت را به عنوان ورودی بپذیرید و یک پیام چت را برگردانید.
- اعتراضات: ورودی های مدل را الگوسازی کنید، به صورت پویا انتخاب کنید و مدیریت کنید. امکان ایجاد اعلانهای انعطافپذیر و مختص زمینه را فراهم میکند که پاسخهای مدل زبان را هدایت میکند.
- تجزیه کننده های خروجی: استخراج و قالب بندی اطلاعات از خروجی های مدل. برای تبدیل خروجی خام مدل های زبان به داده های ساختاریافته یا فرمت های خاص مورد نیاز برنامه مفید است.
LLMs
ادغام LangChain با مدلهای زبان بزرگ (LLM) مانند OpenAI، Cohere، و Hugging Face یک جنبه اساسی از عملکرد آن است. LangChain خود میزبان LLM نیست، اما یک رابط یکنواخت برای تعامل با LLM های مختلف ارائه می دهد.
این بخش یک نمای کلی از استفاده از پوشش OpenAI LLM در LangChain را ارائه می دهد که برای سایر انواع LLM نیز قابل استفاده است. ما قبلاً این را در بخش "شروع به کار" نصب کرده ایم. اجازه دهید LLM را مقداردهی اولیه کنیم.
from langchain.llms import OpenAI
llm = OpenAI()
- LLM ها را اجرا می کنند رابط کاربری قابل اجرا، بلوک اصلی ساختمان زبان بیان LangChain (LCEL). یعنی حمایت می کنند
invoke
,ainvoke
,stream
,astream
,batch
,abatch
,astream_log
تماس می گیرد - LLM ها قبول می کنند رشته های به عنوان ورودی ها، یا اشیایی که می توانند به درخواست های رشته ای وادار شوند، از جمله
List[BaseMessage]
وPromptValue
. (در ادامه بیشتر در مورد این موارد)
اجازه دهید به چند نمونه نگاه کنیم.
response = llm.invoke("List the seven wonders of the world.")
print(response)
همچنین میتوانید روش جریان را برای پخش پاسخ متنی فراخوانی کنید.
for chunk in llm.stream("Where were the 2012 Olympics held?"): print(chunk, end="", flush=True)
مدل های چت
ادغام LangChain با مدلهای چت، تنوع تخصصی مدلهای زبان، برای ایجاد برنامههای چت تعاملی ضروری است. در حالی که از مدلهای زبان به صورت داخلی استفاده میکنند، مدلهای چت یک رابط متمایز را ارائه میکنند که حول پیامهای چت به عنوان ورودی و خروجی متمرکز است. این بخش یک نمای کلی از استفاده از مدل چت OpenAI در LangChain ارائه می دهد.
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI()
مدل های چت در LangChain با انواع پیام های مختلف مانند AIMessage
, HumanMessage
, SystemMessage
, FunctionMessage
و ChatMessage
(با یک پارامتر نقش دلخواه). بطور کلی، HumanMessage
, AIMessage
و SystemMessage
بیشترین استفاده را دارند.
مدل های چت در درجه اول قبول می کنند List[BaseMessage]
به عنوان ورودی رشته ها را می توان به HumanMessage
و PromptValue
نیز پشتیبانی می شود.
from langchain.schema.messages import HumanMessage, SystemMessage
messages = [ SystemMessage(content="You are Micheal Jordan."), HumanMessage(content="Which shoe manufacturer are you associated with?"),
]
response = chat.invoke(messages)
print(response.content)
اعتراضات
اعلانها در هدایت مدلهای زبان برای تولید خروجیهای مرتبط و منسجم ضروری هستند. آنها می توانند از دستورالعمل های ساده تا نمونه های پیچیده چند شات را شامل شوند. در LangChain، به لطف چندین کلاس و عملکرد اختصاصی، رسیدگی به درخواستها میتواند یک فرآیند بسیار ساده باشد.
لانگ چین PromptTemplate
class یک ابزار همه کاره برای ایجاد اعلان های رشته ای است. از پایتون استفاده می کند str.format
نحو، اجازه تولید سریع پویا را می دهد. می توانید یک الگو را با متغیرهایی تعریف کنید و در صورت نیاز آنها را با مقادیر خاص پر کنید.
from langchain.prompts import PromptTemplate # Simple prompt with placeholders
prompt_template = PromptTemplate.from_template( "Tell me a {adjective} joke about {content}."
) # Filling placeholders to create a prompt
filled_prompt = prompt_template.format(adjective="funny", content="robots")
print(filled_prompt)
برای مدلهای چت، درخواستها ساختار بیشتری دارند و شامل پیامهایی با نقشهای خاص هستند. LangChain ارائه می دهد ChatPromptTemplate
به این منظور.
from langchain.prompts import ChatPromptTemplate # Defining a chat prompt with various roles
chat_template = ChatPromptTemplate.from_messages( [ ("system", "You are a helpful AI bot. Your name is {name}."), ("human", "Hello, how are you doing?"), ("ai", "I'm doing well, thanks!"), ("human", "{user_input}"), ]
) # Formatting the chat prompt
formatted_messages = chat_template.format_messages(name="Bob", user_input="What is your name?")
for message in formatted_messages: print(message)
این رویکرد امکان ایجاد رباتهای گفتگوی تعاملی و جذاب با پاسخهای پویا را فراهم میکند.
هر دو PromptTemplate
و ChatPromptTemplate
به طور یکپارچه با زبان بیان LangChain (LCEL) یکپارچه شده و آنها را قادر می سازد تا بخشی از گردش کار بزرگتر و پیچیده باشند. بعداً در این مورد بیشتر بحث خواهیم کرد.
الگوهای درخواست سفارشی گاهی اوقات برای کارهایی که نیاز به قالب بندی منحصر به فرد یا دستورالعمل های خاص دارند ضروری هستند. ایجاد یک الگوی درخواست سفارشی شامل تعریف متغیرهای ورودی و یک روش قالب بندی سفارشی است. این انعطافپذیری به LangChain اجازه میدهد تا مجموعه گستردهای از نیازهای خاص برنامه را برآورده کند. اطلاعات بیشتر اینجا کلیک کنید.
LangChain همچنین از چند شات پشتیبانی میکند و مدل را قادر میسازد تا از مثالها یاد بگیرد. این ویژگی برای کارهایی که نیاز به درک متنی یا الگوهای خاص دارند، حیاتی است. الگوهای اعلان چند شات را می توان از مجموعه ای از مثال ها یا با استفاده از یک شی Example Selector ساخت. اطلاعات بیشتر اینجا کلیک کنید.
تجزیه کننده های خروجی
تجزیه کننده های خروجی نقش مهمی در Langchain ایفا می کنند و کاربران را قادر می سازند تا پاسخ های تولید شده توسط مدل های زبان را ساختار دهند. در این بخش، مفهوم تجزیهکنندههای خروجی را بررسی میکنیم و نمونههای کد را با استفاده از PydanticOutputParser، SimpleJsonOutputParser، CommaSeparatedListOutputParser، DatetimeOutputParser و XMLOutputParser Langchain ارائه میکنیم.
PydanticOutputParser
Langchain PydanticOutputParser را برای تجزیه پاسخ ها در ساختارهای داده Pydantic فراهم می کند. در زیر یک مثال گام به گام از نحوه استفاده از آن آورده شده است:
from typing import List
from langchain.llms import OpenAI
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import PromptTemplate
from langchain.pydantic_v1 import BaseModel, Field, validator # Initialize the language model
model = OpenAI(model_name="text-davinci-003", temperature=0.0) # Define your desired data structure using Pydantic
class Joke(BaseModel): setup: str = Field(description="question to set up a joke") punchline: str = Field(description="answer to resolve the joke") @validator("setup") def question_ends_with_question_mark(cls, field): if field[-1] != "?": raise ValueError("Badly formed question!") return field # Set up a PydanticOutputParser
parser = PydanticOutputParser(pydantic_object=Joke) # Create a prompt with format instructions
prompt = PromptTemplate( template="Answer the user query.n{format_instructions}n{query}n", input_variables=["query"], partial_variables={"format_instructions": parser.get_format_instructions()},
) # Define a query to prompt the language model
query = "Tell me a joke." # Combine prompt, model, and parser to get structured output
prompt_and_model = prompt | model
output = prompt_and_model.invoke({"query": query}) # Parse the output using the parser
parsed_result = parser.invoke(output) # The result is a structured object
print(parsed_result)
خروجی خواهد بود:
SimpleJsonOutputParser
SimpleJsonOutputParser Langchain زمانی استفاده می شود که می خواهید خروجی های JSON مانند را تجزیه کنید. در اینجا یک مثال است:
from langchain.output_parsers.json import SimpleJsonOutputParser # Create a JSON prompt
json_prompt = PromptTemplate.from_template( "Return a JSON object with `birthdate` and `birthplace` key that answers the following question: {question}"
) # Initialize the JSON parser
json_parser = SimpleJsonOutputParser() # Create a chain with the prompt, model, and parser
json_chain = json_prompt | model | json_parser # Stream through the results
result_list = list(json_chain.stream({"question": "When and where was Elon Musk born?"})) # The result is a list of JSON-like dictionaries
print(result_list)
CommaSeparatedListOutputParser
CommaSeparatedListOutputParser زمانی مفید است که می خواهید لیست های جدا شده با کاما را از پاسخ های مدل استخراج کنید. در اینجا یک مثال است:
from langchain.output_parsers import CommaSeparatedListOutputParser
from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI # Initialize the parser
output_parser = CommaSeparatedListOutputParser() # Create format instructions
format_instructions = output_parser.get_format_instructions() # Create a prompt to request a list
prompt = PromptTemplate( template="List five {subject}.n{format_instructions}", input_variables=["subject"], partial_variables={"format_instructions": format_instructions}
) # Define a query to prompt the model
query = "English Premier League Teams" # Generate the output
output = model(prompt.format(subject=query)) # Parse the output using the parser
parsed_result = output_parser.parse(output) # The result is a list of items
print(parsed_result)
DatetimeOutputParser
DatetimeOutputParser Langchain برای تجزیه اطلاعات تاریخ طراحی شده است. در اینجا نحوه استفاده از آن آمده است:
from langchain.prompts import PromptTemplate
from langchain.output_parsers import DatetimeOutputParser
from langchain.chains import LLMChain
from langchain.llms import OpenAI # Initialize the DatetimeOutputParser
output_parser = DatetimeOutputParser() # Create a prompt with format instructions
template = """
Answer the user's question:
{question}
{format_instructions} """ prompt = PromptTemplate.from_template( template, partial_variables={"format_instructions": output_parser.get_format_instructions()},
) # Create a chain with the prompt and language model
chain = LLMChain(prompt=prompt, llm=OpenAI()) # Define a query to prompt the model
query = "when did Neil Armstrong land on the moon in terms of GMT?" # Run the chain
output = chain.run(query) # Parse the output using the datetime parser
parsed_result = output_parser.parse(output) # The result is a datetime object
print(parsed_result)
این مثالها نشان میدهند که چگونه میتوان از تجزیهکنندههای خروجی Langchain برای ساختاربندی انواع پاسخهای مدل استفاده کرد و آنها را برای برنامهها و فرمتهای مختلف مناسب میسازد. تجزیه کننده های خروجی ابزار ارزشمندی برای افزایش قابلیت استفاده و تفسیر پذیری خروجی های مدل زبان در Langchain هستند.
کارها و گردشهای کار دستی را با سازنده گردش کار مبتنی بر هوش مصنوعی، که توسط Nanonets برای شما و تیمهایتان طراحی شده است، خودکار کنید.
ماژول دوم: بازیابی
بازیابی در LangChain نقش مهمی در برنامههایی دارد که به دادههای خاص کاربر نیاز دارند، که در مجموعه آموزشی مدل گنجانده نشده است. این فرآیند که به عنوان Retrieval Augmented Generation (RAG) شناخته میشود، شامل واکشی دادههای خارجی و ادغام آن در فرآیند تولید مدل زبان است. LangChain مجموعه ای جامع از ابزارها و عملکردها را برای تسهیل این فرآیند ارائه می دهد که هم برای برنامه های کاربردی ساده و هم پیچیده ارائه می شود.
LangChain از طریق مجموعهای از مؤلفهها به بازیابی دست مییابد که یک به یک در مورد آنها بحث خواهیم کرد.
لودرهای سند
لودرهای سند در LangChain استخراج داده ها را از منابع مختلف امکان پذیر می کنند. با بیش از 100 لودر موجود، آنها طیف وسیعی از انواع اسناد، برنامه ها و منابع (سطل های خصوصی s3، وب سایت های عمومی، پایگاه های داده) را پشتیبانی می کنند.
شما می توانید بر اساس نیاز خود یک لودر سند انتخاب کنید اینجا کلیک نمایید.
همه این لودرها داده ها را وارد می کنند سند کلاس ها. نحوه استفاده از دادههای دریافت شده در کلاسهای Document را بعداً یاد خواهیم گرفت.
بارگذار فایل متنی: بارگذاری ساده .txt
را در یک سند ثبت کنید
from langchain.document_loaders import TextLoader loader = TextLoader("./sample.txt")
document = loader.load()
CSV Loader: یک فایل CSV را در یک سند بارگیری کنید.
from langchain.document_loaders.csv_loader import CSVLoader loader = CSVLoader(file_path='./example_data/sample.csv')
documents = loader.load()
ما می توانیم با تعیین نام فیلدها تجزیه را سفارشی کنیم -
loader = CSVLoader(file_path='./example_data/mlb_teams_2012.csv', csv_args={ 'delimiter': ',', 'quotechar': '"', 'fieldnames': ['MLB Team', 'Payroll in millions', 'Wins']
})
documents = loader.load()
بارگذارهای PDF: PDF Loader در LangChain روش های مختلفی را برای تجزیه و استخراج محتوا از فایل های PDF ارائه می دهد. هر لودر نیازهای متفاوتی را برآورده می کند و از کتابخانه های زیربنایی مختلفی استفاده می کند. در زیر نمونه های دقیق برای هر لودر آورده شده است.
PyPDFLoader برای تجزیه اولیه PDF استفاده می شود.
from langchain.document_loaders import PyPDFLoader loader = PyPDFLoader("example_data/layout-parser-paper.pdf")
pages = loader.load_and_split()
MathPixLoader برای استخراج محتوا و نمودارهای ریاضی ایده آل است.
from langchain.document_loaders import MathpixPDFLoader loader = MathpixPDFLoader("example_data/math-content.pdf")
data = loader.load()
PyMuPDFLoader سریع است و شامل استخراج فراداده دقیق است.
from langchain.document_loaders import PyMuPDFLoader loader = PyMuPDFLoader("example_data/layout-parser-paper.pdf")
data = loader.load() # Optionally pass additional arguments for PyMuPDF's get_text() call
data = loader.load(option="text")
PDFMiner Loader برای کنترل دقیق تر بر استخراج متن استفاده می شود.
from langchain.document_loaders import PDFMinerLoader loader = PDFMinerLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
AmazonTextractPDFParser از AWS Textract برای OCR و دیگر ویژگیهای پیشرفته تجزیه PDF استفاده میکند.
from langchain.document_loaders import AmazonTextractPDFLoader # Requires AWS account and configuration
loader = AmazonTextractPDFLoader("example_data/complex-layout.pdf")
documents = loader.load()
PDFMinerPDFasHTMLLoader HTML را از PDF برای تجزیه معنایی تولید می کند.
from langchain.document_loaders import PDFMinerPDFasHTMLLoader loader = PDFMinerPDFasHTMLLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
PDFPlumberLoader فراداده های دقیقی را ارائه می دهد و از یک سند در هر صفحه پشتیبانی می کند.
from langchain.document_loaders import PDFPlumberLoader loader = PDFPlumberLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
لودرهای یکپارچه: LangChain طیف گسترده ای از لودرهای سفارشی را برای بارگیری مستقیم داده ها از برنامه های شما (مانند Slack، Sigma، Notion، Confluence، Google Drive و بسیاری دیگر) و پایگاه داده و استفاده از آنها در برنامه های LLM ارائه می دهد.
لیست کامل است اینجا کلیک نمایید.
در زیر چند مثال برای نشان دادن این موضوع وجود دارد -
مثال I - Slack
Slack، یک پلت فرم پیام فوری پرکاربرد، می تواند در جریان کار و برنامه های کاربردی LLM ادغام شود.
- به صفحه مدیریت فضای کاری Slack خود بروید.
- هدایت به
{your_slack_domain}.slack.com/services/export
. - محدوده تاریخ مورد نظر را انتخاب کرده و صادرات را آغاز کنید.
- Slack پس از آماده شدن صادرات از طریق ایمیل و DM اطلاع می دهد.
- صادرات منجر به الف
.zip
فایلی که در پوشه دانلودها یا مسیر دانلود تعیین شده شما قرار دارد. - مسیر دانلود شده را تعیین کنید
.zip
فایل بهLOCAL_ZIPFILE
. - استفاده از
SlackDirectoryLoader
ازlangchain.document_loaders
بسته.
from langchain.document_loaders import SlackDirectoryLoader SLACK_WORKSPACE_URL = "https://xxx.slack.com" # Replace with your Slack URL
LOCAL_ZIPFILE = "" # Path to the Slack zip file loader = SlackDirectoryLoader(LOCAL_ZIPFILE, SLACK_WORKSPACE_URL)
docs = loader.load()
print(docs)
مثال II - Figma
Figma، یک ابزار محبوب برای طراحی رابط، یک REST API برای یکپارچه سازی داده ها ارائه می دهد.
- کلید فایل Figma را از فرمت URL دریافت کنید:
https://www.figma.com/file/{filekey}/sampleFilename
. - شناسه گره ها در پارامتر URL یافت می شوند
?node-id={node_id}
. - ایجاد یک نشانه دسترسی زیر دستورالعمل در مرکز راهنمایی Figma.
- La
FigmaFileLoader
کلاس ازlangchain.document_loaders.figma
برای بارگذاری داده های Figma استفاده می شود. - ماژول های مختلف LangChain مانند
CharacterTextSplitter
,ChatOpenAI
و غیره برای پردازش به کار گرفته می شوند.
import os
from langchain.document_loaders.figma import FigmaFileLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.chat_models import ChatOpenAI
from langchain.indexes import VectorstoreIndexCreator
from langchain.chains import ConversationChain, LLMChain
from langchain.memory import ConversationBufferWindowMemory
from langchain.prompts.chat import ChatPromptTemplate, SystemMessagePromptTemplate, AIMessagePromptTemplate, HumanMessagePromptTemplate figma_loader = FigmaFileLoader( os.environ.get("ACCESS_TOKEN"), os.environ.get("NODE_IDS"), os.environ.get("FILE_KEY"),
) index = VectorstoreIndexCreator().from_loaders([figma_loader])
figma_doc_retriever = index.vectorstore.as_retriever()
- La
generate_code
تابع از داده های Figma برای ایجاد کد HTML/CSS استفاده می کند. - از یک مکالمه قالبی با یک مدل مبتنی بر GPT استفاده می کند.
def generate_code(human_input): # Template for system and human prompts system_prompt_template = "Your coding instructions..." human_prompt_template = "Code the {text}. Ensure it's mobile responsive" # Creating prompt templates system_message_prompt = SystemMessagePromptTemplate.from_template(system_prompt_template) human_message_prompt = HumanMessagePromptTemplate.from_template(human_prompt_template) # Setting up the AI model gpt_4 = ChatOpenAI(temperature=0.02, model_name="gpt-4") # Retrieving relevant documents relevant_nodes = figma_doc_retriever.get_relevant_documents(human_input) # Generating and formatting the prompt conversation = [system_message_prompt, human_message_prompt] chat_prompt = ChatPromptTemplate.from_messages(conversation) response = gpt_4(chat_prompt.format_prompt(context=relevant_nodes, text=human_input).to_messages()) return response # Example usage
response = generate_code("page top header")
print(response.content)
- La
generate_code
تابع، هنگام اجرا، کد HTML/CSS را بر اساس ورودی طراحی Figma برمیگرداند.
اجازه دهید اکنون از دانش خود برای ایجاد چند مجموعه سند استفاده کنیم.
ما ابتدا یک PDF، گزارش پایداری سالانه BCG را بارگذاری می کنیم.
ما برای این کار از PyPDFLoader استفاده می کنیم.
from langchain.document_loaders import PyPDFLoader loader = PyPDFLoader("bcg-2022-annual-sustainability-report-apr-2023.pdf")
pdfpages = loader.load_and_split()
اکنون دادههای Airtable را دریافت میکنیم. ما یک Airtable حاوی اطلاعاتی در مورد مدلهای مختلف OCR و استخراج دادهها داریم –
اجازه دهید از AirtableLoader برای این کار استفاده کنیم که در لیست لودرهای یکپارچه یافت می شود.
from langchain.document_loaders import AirtableLoader api_key = "XXXXX"
base_id = "XXXXX"
table_id = "XXXXX" loader = AirtableLoader(api_key, table_id, base_id)
airtabledocs = loader.load()
اجازه دهید اکنون ادامه دهیم و نحوه استفاده از این کلاس های سند را بیاموزیم.
ترانسفورماتورهای سند
ترانسفورماتورهای سند در LangChain ابزارهای ضروری طراحی شده برای دستکاری اسناد هستند که در زیربخش قبلی خود ایجاد کردیم.
آنها برای کارهایی مانند تقسیم اسناد طولانی به قطعات کوچکتر، ترکیب کردن و فیلتر کردن استفاده می شوند که برای تطبیق اسناد با پنجره زمینه مدل یا برآورده کردن نیازهای برنامه خاص بسیار مهم هستند.
یکی از این ابزارها RecursiveCharacterTextSplitter است، یک تقسیمکننده متن همه کاره که از فهرست کاراکترها برای تقسیم استفاده میکند. این اجازه می دهد تا پارامترهایی مانند اندازه تکه، همپوشانی، و شاخص شروع. در اینجا مثالی از نحوه استفاده از آن در پایتون آورده شده است:
from langchain.text_splitter import RecursiveCharacterTextSplitter state_of_the_union = "Your long text here..." text_splitter = RecursiveCharacterTextSplitter( chunk_size=100, chunk_overlap=20, length_function=len, add_start_index=True,
) texts = text_splitter.create_documents([state_of_the_union])
print(texts[0])
print(texts[1])
ابزار دیگر CharacterTextSplitter است که متن را بر اساس یک کاراکتر مشخص تقسیم میکند و شامل کنترلهایی برای اندازه تکه و همپوشانی است:
from langchain.text_splitter import CharacterTextSplitter text_splitter = CharacterTextSplitter( separator="nn", chunk_size=1000, chunk_overlap=200, length_function=len, is_separator_regex=False,
) texts = text_splitter.create_documents([state_of_the_union])
print(texts[0])
HTMLHeaderTextSplitter برای تقسیم محتوای HTML بر اساس تگ های هدر طراحی شده است و ساختار معنایی را حفظ می کند:
from langchain.text_splitter import HTMLHeaderTextSplitter html_string = "Your HTML content here..."
headers_to_split_on = [("h1", "Header 1"), ("h2", "Header 2")] html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
html_header_splits = html_splitter.split_text(html_string)
print(html_header_splits[0])
دستکاری پیچیده تری را می توان با ترکیب HTMLHeaderTextSplitter با تقسیم کننده دیگری مانند Pipelined Splitter به دست آورد:
from langchain.text_splitter import HTMLHeaderTextSplitter, RecursiveCharacterTextSplitter url = "https://example.com"
headers_to_split_on = [("h1", "Header 1"), ("h2", "Header 2")]
html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
html_header_splits = html_splitter.split_text_from_url(url) chunk_size = 500
text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size)
splits = text_splitter.split_documents(html_header_splits)
print(splits[0])
LangChain همچنین تقسیمکنندههای خاصی را برای زبانهای برنامهنویسی مختلف، مانند شکاف کد Python و شکاف کد جاوا اسکریپت ارائه میکند:
from langchain.text_splitter import RecursiveCharacterTextSplitter, Language python_code = """
def hello_world(): print("Hello, World!")
hello_world() """ python_splitter = RecursiveCharacterTextSplitter.from_language( language=Language.PYTHON, chunk_size=50
)
python_docs = python_splitter.create_documents([python_code])
print(python_docs[0]) js_code = """
function helloWorld() { console.log("Hello, World!");
}
helloWorld(); """ js_splitter = RecursiveCharacterTextSplitter.from_language( language=Language.JS, chunk_size=60
)
js_docs = js_splitter.create_documents([js_code])
print(js_docs[0])
برای تقسیم متن بر اساس تعداد توکن، که برای مدلهای زبانی با محدودیت نشانهها مفید است، از TokenTextSplitter استفاده میشود:
from langchain.text_splitter import TokenTextSplitter text_splitter = TokenTextSplitter(chunk_size=10)
texts = text_splitter.split_text(state_of_the_union)
print(texts[0])
در نهایت، LongContextReorder اسناد را مجدداً مرتب می کند تا از کاهش عملکرد در مدل ها به دلیل زمینه های طولانی جلوگیری کند:
from langchain.document_transformers import LongContextReorder reordering = LongContextReorder()
reordered_docs = reordering.transform_documents(docs)
print(reordered_docs[0])
این ابزارها روشهای مختلفی را برای تبدیل اسناد در LangChain نشان میدهند، از تقسیم متن ساده تا مرتبسازی مجدد پیچیده و تقسیمبندی خاص زبان. برای موارد استفاده عمیق تر و خاص، باید به بخش اسناد و ادغام LangChain مراجعه کنید.
در مثالهای ما، لودرها قبلاً اسناد تکهای را برای ما ایجاد کردهاند و این قسمت قبلاً مدیریت شده است.
مدل های جاسازی متن
مدلهای جاسازی متن در LangChain یک رابط استاندارد برای ارائهدهندگان مدلهای جاسازی مختلف مانند OpenAI، Cohere، و Hugging Face ارائه میکنند. این مدلها متن را به نمایشهای برداری تبدیل میکنند و عملیاتهایی مانند جستجوی معنایی را از طریق شباهت متن در فضای برداری امکانپذیر میسازند.
برای شروع کار با مدلهای جاسازی متن، معمولاً باید بستههای خاصی را نصب کنید و کلیدهای API را تنظیم کنید. ما قبلاً این کار را برای OpenAI انجام داده ایم
در LangChain، embed_documents
روش برای جاسازی متون متعدد استفاده می شود و فهرستی از نمایش های برداری را ارائه می دهد. برای مثال:
from langchain.embeddings import OpenAIEmbeddings # Initialize the model
embeddings_model = OpenAIEmbeddings() # Embed a list of texts
embeddings = embeddings_model.embed_documents( ["Hi there!", "Oh, hello!", "What's your name?", "My friends call me World", "Hello World!"]
)
print("Number of documents embedded:", len(embeddings))
print("Dimension of each embedding:", len(embeddings[0]))
برای جاسازی یک متن واحد، مانند یک عبارت جستجو، embed_query
روش استفاده می شود. این برای مقایسه یک پرس و جو با مجموعه ای از جاسازی های سند مفید است. مثلا:
from langchain.embeddings import OpenAIEmbeddings # Initialize the model
embeddings_model = OpenAIEmbeddings() # Embed a single query
embedded_query = embeddings_model.embed_query("What was the name mentioned in the conversation?")
print("First five dimensions of the embedded query:", embedded_query[:5])
درک این تعبیه ها بسیار مهم است. هر قطعه متن به یک بردار تبدیل می شود که ابعاد آن به مدل استفاده شده بستگی دارد. به عنوان مثال، مدل های OpenAI به طور معمول بردارهای 1536 بعدی را تولید می کنند. سپس از این تعبیهها برای بازیابی اطلاعات مرتبط استفاده میشود.
قابلیت جاسازی LangChain به OpenAI محدود نمی شود، بلکه برای کار با ارائه دهندگان مختلف طراحی شده است. تنظیم و استفاده ممکن است بسته به ارائه دهنده کمی متفاوت باشد، اما مفهوم اصلی جاسازی متون در فضای برداری یکسان است. برای استفاده دقیق، از جمله تنظیمات پیشرفته و ادغام با ارائه دهندگان مدل های جاسازی مختلف، مستندات LangChain در بخش Integrations منبع ارزشمندی است.
فروشگاه های وکتور
فروشگاه های وکتور در LangChain از ذخیره سازی و جستجوی کارآمد جاسازی های متن پشتیبانی می کنند. LangChain با بیش از 50 فروشگاه برداری ادغام می شود و یک رابط استاندارد برای سهولت استفاده ارائه می دهد.
مثال: ذخیره و جستجوی جاسازی ها
پس از جاسازی متون، می توانیم آنها را در یک فروشگاه برداری مانند ذخیره کنیم Chroma
و جستجوهای مشابه انجام دهید:
from langchain.vectorstores import Chroma db = Chroma.from_texts(embedded_texts)
similar_texts = db.similarity_search("search query")
اجازه دهید از فروشگاه بردار FAISS برای ایجاد نمایه برای اسناد خود استفاده کنیم.
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS pdfstore = FAISS.from_documents(pdfpages, embedding=OpenAIEmbeddings()) airtablestore = FAISS.from_documents(airtabledocs, embedding=OpenAIEmbeddings())
رتریورها
Retriever ها در LangChain رابط هایی هستند که اسناد را در پاسخ به یک پرس و جوی ساختار نیافته برمی گرداند. آنها عمومی تر از ذخیره های برداری هستند و به جای ذخیره سازی بر بازیابی تمرکز دارند. اگرچه ذخیرههای برداری میتوانند به عنوان ستون فقرات رتریور استفاده شوند، انواع دیگری از رتریورها نیز وجود دارند.
برای راه اندازی Chroma retriever، ابتدا آن را با استفاده از آن نصب کنید pip install chromadb
. سپس، اسناد را با استفاده از یک سری دستورات پایتون بارگیری، تقسیم، جاسازی و بازیابی می کنید. در اینجا یک نمونه کد برای راه اندازی یک بازیابی Chroma آورده شده است:
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma full_text = open("state_of_the_union.txt", "r").read()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
texts = text_splitter.split_text(full_text) embeddings = OpenAIEmbeddings()
db = Chroma.from_texts(texts, embeddings)
retriever = db.as_retriever() retrieved_docs = retriever.invoke("What did the president say about Ketanji Brown Jackson?")
print(retrieved_docs[0].page_content)
MultiQueryRetriever با ایجاد پرس و جوهای متعدد برای یک پرس و جوی ورودی کاربر، تنظیم سریع را خودکار می کند و نتایج را ترکیب می کند. در اینجا مثالی از کاربرد ساده آن آورده شده است:
from langchain.chat_models import ChatOpenAI
from langchain.retrievers.multi_query import MultiQueryRetriever question = "What are the approaches to Task Decomposition?"
llm = ChatOpenAI(temperature=0)
retriever_from_llm = MultiQueryRetriever.from_llm( retriever=db.as_retriever(), llm=llm
) unique_docs = retriever_from_llm.get_relevant_documents(query=question)
print("Number of unique documents:", len(unique_docs))
فشرده سازی متنی در LangChain اسناد بازیابی شده را با استفاده از زمینه پرس و جو فشرده می کند و اطمینان حاصل می کند که فقط اطلاعات مربوطه برگردانده می شود. این شامل کاهش محتوا و فیلتر کردن اسناد کمتر مرتبط است. مثال کد زیر نحوه استفاده از Contextual Compression Retriever را نشان می دهد:
from langchain.llms import OpenAI
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor llm = OpenAI(temperature=0)
compressor = LLMChainExtractor.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(base_compressor=compressor, base_retriever=retriever) compressed_docs = compression_retriever.get_relevant_documents("What did the president say about Ketanji Jackson Brown")
print(compressed_docs[0].page_content)
EnsembleRetriever الگوریتم های مختلف بازیابی را برای دستیابی به عملکرد بهتر ترکیب می کند. نمونه ای از ترکیب BM25 و FAISS Retrievers در کد زیر نشان داده شده است:
from langchain.retrievers import BM25Retriever, EnsembleRetriever
from langchain.vectorstores import FAISS bm25_retriever = BM25Retriever.from_texts(doc_list).set_k(2)
faiss_vectorstore = FAISS.from_texts(doc_list, OpenAIEmbeddings())
faiss_retriever = faiss_vectorstore.as_retriever(search_kwargs={"k": 2}) ensemble_retriever = EnsembleRetriever( retrievers=[bm25_retriever, faiss_retriever], weights=[0.5, 0.5]
) docs = ensemble_retriever.get_relevant_documents("apples")
print(docs[0].page_content)
MultiVector Retriever در LangChain امکان جستجوی اسناد با چندین بردار در هر سند را میدهد که برای ثبت جنبههای معنایی مختلف در یک سند مفید است. روشهای ایجاد بردارهای چندگانه شامل تقسیم به تکههای کوچکتر، خلاصهسازی یا ایجاد سؤالات فرضی است. برای تقسیم اسناد به قطعات کوچکتر، می توان از کد پایتون زیر استفاده کرد:
python
from langchain.retrievers.multi_vector import MultiVectorRetriever
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.storage import InMemoryStore
from langchain.document_loaders from TextLoader
import uuid loaders = [TextLoader("file1.txt"), TextLoader("file2.txt")]
docs = [doc for loader in loaders for doc in loader.load()]
text_splitter = RecursiveCharacterTextSplitter(chunk_size=10000)
docs = text_splitter.split_documents(docs) vectorstore = Chroma(collection_name="full_documents", embedding_function=OpenAIEmbeddings())
store = InMemoryStore()
id_key = "doc_id"
retriever = MultiVectorRetriever(vectorstore=vectorstore, docstore=store, id_key=id_key) doc_ids = [str(uuid.uuid4()) for _ in docs]
child_text_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
sub_docs = [sub_doc for doc in docs for sub_doc in child_text_splitter.split_documents([doc])]
for sub_doc in sub_docs: sub_doc.metadata[id_key] = doc_ids[sub_docs.index(sub_doc)] retriever.vectorstore.add_documents(sub_docs)
retriever.docstore.mset(list(zip(doc_ids, docs)))
ایجاد خلاصه برای بازیابی بهتر به دلیل نمایش محتوای متمرکزتر روش دیگری است. در اینجا نمونه ای از تولید خلاصه آورده شده است:
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.document import Document chain = (lambda x: x.page_content) | ChatPromptTemplate.from_template("Summarize the following document:nn{doc}") | ChatOpenAI(max_retries=0) | StrOutputParser()
summaries = chain.batch(docs, {"max_concurrency": 5}) summary_docs = [Document(page_content=s, metadata={id_key: doc_ids[i]}) for i, s in enumerate(summaries)]
retriever.vectorstore.add_documents(summary_docs)
retriever.docstore.mset(list(zip(doc_ids, docs)))
ایجاد سؤالات فرضی مرتبط با هر سند با استفاده از LLM رویکرد دیگری است. این کار با کد زیر قابل انجام است:
functions = [{"name": "hypothetical_questions", "parameters": {"questions": {"type": "array", "items": {"type": "string"}}}}]
from langchain.output_parsers.openai_functions import JsonKeyOutputFunctionsParser chain = (lambda x: x.page_content) | ChatPromptTemplate.from_template("Generate 3 hypothetical questions:nn{doc}") | ChatOpenAI(max_retries=0).bind(functions=functions, function_call={"name": "hypothetical_questions"}) | JsonKeyOutputFunctionsParser(key_name="questions")
hypothetical_questions = chain.batch(docs, {"max_concurrency": 5}) question_docs = [Document(page_content=q, metadata={id_key: doc_ids[i]}) for i, questions in enumerate(hypothetical_questions) for q in questions]
retriever.vectorstore.add_documents(question_docs)
retriever.docstore.mset(list(zip(doc_ids, docs)))
Parent Document Retriever یکی دیگر از بازیابیهایی است که با ذخیره تکههای کوچک و بازیابی اسناد والدین بزرگتر، تعادلی بین دقت جاسازی و حفظ بافت ایجاد میکند. اجرای آن به شرح زیر است:
from langchain.retrievers import ParentDocumentRetriever loaders = [TextLoader("file1.txt"), TextLoader("file2.txt")]
docs = [doc for loader in loaders for doc in loader.load()] child_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
vectorstore = Chroma(collection_name="full_documents", embedding_function=OpenAIEmbeddings())
store = InMemoryStore()
retriever = ParentDocumentRetriever(vectorstore=vectorstore, docstore=store, child_splitter=child_splitter) retriever.add_documents(docs, ids=None) retrieved_docs = retriever.get_relevant_documents("query")
یک retriever خود پرسوجو پرسوجوهای ساختاریافته را از ورودیهای زبان طبیعی میسازد و آنها را در VectorStore زیربنایی خود اعمال میکند. پیاده سازی آن در کد زیر نشان داده شده است:
from langchain.chat_models from ChatOpenAI
from langchain.chains.query_constructor.base from AttributeInfo
from langchain.retrievers.self_query.base from SelfQueryRetriever metadata_field_info = [AttributeInfo(name="genre", description="...", type="string"), ...]
document_content_description = "Brief summary of a movie"
llm = ChatOpenAI(temperature=0) retriever = SelfQueryRetriever.from_llm(llm, vectorstore, document_content_description, metadata_field_info) retrieved_docs = retriever.invoke("query")
WebResearchRetriever تحقیقات وب را بر اساس یک پرس و جو انجام می دهد -
from langchain.retrievers.web_research import WebResearchRetriever # Initialize components
llm = ChatOpenAI(temperature=0)
search = GoogleSearchAPIWrapper()
vectorstore = Chroma(embedding_function=OpenAIEmbeddings()) # Instantiate WebResearchRetriever
web_research_retriever = WebResearchRetriever.from_llm(vectorstore=vectorstore, llm=llm, search=search) # Retrieve documents
docs = web_research_retriever.get_relevant_documents("query")
برای مثالهایمان، میتوانیم از retriver استانداردی که قبلاً به عنوان بخشی از شی ذخیرهسازی برداری ما پیادهسازی شده است، به شرح زیر استفاده کنیم:
اکنون میتوانیم از رتریورها پرس و جو کنیم. خروجی پرس و جو ما اشیاء سند مربوط به پرس و جو خواهد بود. اینها در نهایت برای ایجاد پاسخ های مرتبط در بخش های بعدی مورد استفاده قرار خواهند گرفت.
کارها و گردشهای کار دستی را با سازنده گردش کار مبتنی بر هوش مصنوعی، که توسط Nanonets برای شما و تیمهایتان طراحی شده است، خودکار کنید.
ماژول سوم: نمایندگان
LangChain یک مفهوم قدرتمند به نام "عامل" را معرفی می کند که ایده زنجیره ها را به سطح کاملاً جدیدی می برد. عامل ها از مدل های زبان برای تعیین پویا دنباله ای از اقدامات برای انجام استفاده می کنند و آنها را فوق العاده همه کاره و سازگار می کند. بر خلاف زنجیرههای سنتی، که در آن اقدامات در کد سخت کدگذاری میشوند، عاملها از مدلهای زبان به عنوان موتورهای استدلال استفاده میکنند تا تصمیم بگیرند که کدام اقدامات و به چه ترتیبی انجام شود.
نماینده جزء اصلی مسئول تصمیم گیری است. از قدرت یک مدل زبانی استفاده میکند و گامهای بعدی را برای دستیابی به یک هدف خاص تعیین میکند. ورودی های یک عامل معمولاً شامل:
- ابزار: توضیحات ابزارهای موجود (در ادامه در این مورد بیشتر خواهد شد).
- ورودی کاربر: هدف یا درخواست سطح بالا از کاربر.
- مراحل میانی: تاریخچه ای از جفت های (عمل، خروجی ابزار) اجرا شده برای رسیدن به ورودی کاربر فعلی.
خروجی یک عامل می تواند بعدی باشد اقدام برای انجام اقدامات (AgentActions) یا فینال پاسخ برای ارسال به کاربر (AgentFinish) یک اقدام مشخص می کند a ابزار و ورودی برای آن ابزار
ابزار
ابزارها رابط هایی هستند که یک عامل می تواند از آنها برای تعامل با جهان استفاده کند. آنها عامل ها را قادر می سازند تا وظایف مختلفی مانند جستجو در وب، اجرای دستورات پوسته یا دسترسی به API های خارجی را انجام دهند. در LangChain، ابزارها برای گسترش قابلیت های عامل ها و قادر ساختن آنها برای انجام وظایف مختلف ضروری هستند.
برای استفاده از ابزارها در LangChain، می توانید آنها را با استفاده از قطعه زیر بارگذاری کنید:
from langchain.agents import load_tools tool_names = [...]
tools = load_tools(tool_names)
برخی از ابزارها ممکن است برای مقداردهی اولیه به یک مدل زبان پایه (LLM) نیاز داشته باشند. در چنین مواردی، می توانید یک LLM را نیز بگذرانید:
from langchain.agents import load_tools tool_names = [...]
llm = ...
tools = load_tools(tool_names, llm=llm)
این تنظیمات به شما امکان می دهد به ابزارهای مختلفی دسترسی داشته باشید و آنها را در گردش کار نماینده خود ادغام کنید. لیست کامل ابزارها با مستندات استفاده است اینجا کلیک نمایید.
بیایید به چند نمونه از ابزار نگاه کنیم.
DuckDuckGo
ابزار DuckDuckGo شما را قادر می سازد با استفاده از موتور جستجوی خود جستجوهای وب را انجام دهید. در اینجا نحوه استفاده از آن آمده است:
from langchain.tools import DuckDuckGoSearchRun
search = DuckDuckGoSearchRun()
search.run("manchester united vs luton town match summary")
DataForSeo
جعبه ابزار DataForSeo به شما امکان می دهد با استفاده از DataForSeo API نتایج موتورهای جستجو را به دست آورید. برای استفاده از این جعبه ابزار، باید اعتبار API خود را تنظیم کنید. در اینجا نحوه پیکربندی اعتبارنامه آمده است:
import os os.environ["DATAFORSEO_LOGIN"] = "<your_api_access_username>"
os.environ["DATAFORSEO_PASSWORD"] = "<your_api_access_password>"
هنگامی که اعتبار شما تنظیم شد، می توانید a ایجاد کنید DataForSeoAPIWrapper
ابزار دسترسی به API:
from langchain.utilities.dataforseo_api_search import DataForSeoAPIWrapper wrapper = DataForSeoAPIWrapper() result = wrapper.run("Weather in Los Angeles")
La DataForSeoAPIWrapper
ابزار نتایج موتورهای جستجو را از منابع مختلف بازیابی می کند.
می توانید نوع نتایج و فیلدهای بازگردانده شده در پاسخ JSON را سفارشی کنید. به عنوان مثال، میتوانید انواع، فیلدهای نتیجه را مشخص کنید و حداکثر تعداد نتایج را برای بازگشت تعیین کنید:
json_wrapper = DataForSeoAPIWrapper( json_result_types=["organic", "knowledge_graph", "answer_box"], json_result_fields=["type", "title", "description", "text"], top_count=3,
) json_result = json_wrapper.results("Bill Gates")
این مثال با تعیین انواع نتایج، فیلدها و محدود کردن تعداد نتایج، پاسخ JSON را سفارشی میکند.
همچنین می توانید مکان و زبان نتایج جستجوی خود را با ارسال پارامترهای اضافی به پوشش API مشخص کنید:
customized_wrapper = DataForSeoAPIWrapper( top_count=10, json_result_types=["organic", "local_pack"], json_result_fields=["title", "description", "type"], params={"location_name": "Germany", "language_code": "en"},
) customized_result = customized_wrapper.results("coffee near me")
با ارائه پارامترهای مکان و زبان، می توانید نتایج جستجوی خود را برای مناطق و زبان های خاص تنظیم کنید.
شما این امکان را دارید که موتور جستجوی مورد نظر خود را انتخاب کنید. به سادگی موتور جستجوی مورد نظر را مشخص کنید:
customized_wrapper = DataForSeoAPIWrapper( top_count=10, json_result_types=["organic", "local_pack"], json_result_fields=["title", "description", "type"], params={"location_name": "Germany", "language_code": "en", "se_name": "bing"},
) customized_result = customized_wrapper.results("coffee near me")
در این مثال، جستجو برای استفاده از Bing به عنوان موتور جستجو سفارشی شده است.
بسته بندی API همچنین به شما امکان می دهد نوع جستجویی را که می خواهید انجام دهید مشخص کنید. به عنوان مثال، می توانید جستجوی نقشه ها را انجام دهید:
maps_search = DataForSeoAPIWrapper( top_count=10, json_result_fields=["title", "value", "address", "rating", "type"], params={ "location_coordinate": "52.512,13.36,12z", "language_code": "en", "se_type": "maps", },
) maps_search_result = maps_search.results("coffee near me")
این جستجو را برای بازیابی اطلاعات مربوط به نقشه ها سفارشی می کند.
پوسته (باش)
جعبه ابزار Shell دسترسی عوامل را به محیط پوسته فراهم می کند و به آنها اجازه می دهد دستورات شل را اجرا کنند. این ویژگی قدرتمند است، اما باید با احتیاط از آن استفاده کرد، به خصوص در محیط های sandbox. در اینجا نحوه استفاده از ابزار Shell آورده شده است:
from langchain.tools import ShellTool shell_tool = ShellTool() result = shell_tool.run({"commands": ["echo 'Hello World!'", "time"]})
در این مثال، ابزار Shell دو فرمان پوسته را اجرا میکند: تکرار "Hello World!" و نمایش زمان فعلی
شما می توانید ابزار Shell را در اختیار یک عامل قرار دهید تا کارهای پیچیده تری را انجام دهد. در اینجا یک مثال از یک عامل است که پیوندها را از یک صفحه وب با استفاده از ابزار Shell دریافت می کند:
from langchain.agents import AgentType, initialize_agent
from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(temperature=0.1) shell_tool.description = shell_tool.description + f"args {shell_tool.args}".replace( "{", "{{"
).replace("}", "}}")
self_ask_with_search = initialize_agent( [shell_tool], llm, agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)
self_ask_with_search.run( "Download the langchain.com webpage and grep for all urls. Return only a sorted list of them. Be sure to use double quotes."
)
در این سناریو، عامل از ابزار Shell برای اجرای دنباله ای از دستورات برای واکشی، فیلتر کردن و مرتب کردن URL ها از یک صفحه وب استفاده می کند.
مثال های ارائه شده برخی از ابزارهای موجود در LangChain را نشان می دهد. این ابزارها در نهایت قابلیت های عامل ها را گسترش می دهند (که در بخش بعدی بررسی می شود) و آنها را برای انجام وظایف مختلف به طور موثر توانمند می سازند. بسته به نیاز خود، میتوانید ابزارها و جعبهابزارهایی را انتخاب کنید که به بهترین وجه با نیازهای پروژه شما مطابقت دارند و آنها را در جریان کاری نماینده خود ادغام کنید.
بازگشت به نمایندگان
حالا بریم سراغ عوامل.
AgentExecutor محیط زمان اجرا برای یک عامل است. مسئول فراخوانی عامل، اجرای اقداماتی که انتخاب میکند، خروجیهای عملیات را به عامل برمیگرداند و فرآیند را تا پایان کار تکرار میکند. در شبه کد، AgentExecutor ممکن است چیزی شبیه به این باشد:
next_action = agent.get_action(...)
while next_action != AgentFinish: observation = run(next_action) next_action = agent.get_action(..., next_action, observation)
return next_action
AgentExecutor پیچیدگیهای مختلفی را مدیریت میکند، مانند رسیدگی به مواردی که عامل یک ابزار ناموجود را انتخاب میکند، خطاهای ابزار را مدیریت میکند، خروجیهای تولید شده توسط عامل را مدیریت میکند، و ارائه گزارش و قابلیت مشاهده در همه سطوح.
در حالی که کلاس AgentExecutor زمان اجرا عامل اصلی در LangChain است، زمان های اجرا آزمایشی دیگری نیز پشتیبانی می شود، از جمله:
- عامل برنامه ریزی و اجرا
- Baby AGI
- GPT خودکار
برای به دست آوردن درک بهتر از چارچوب عامل، بیایید یک عامل پایه را از ابتدا بسازیم، و سپس به بررسی عوامل از پیش ساخته شده بپردازیم.
قبل از اینکه به ساخت عامل بپردازیم، ضروری است که برخی از اصطلاحات و طرحواره های کلیدی را دوباره مرور کنیم:
- AgentAction: این یک کلاس داده است که نشان دهنده عملکردی است که یک عامل باید انجام دهد. این شامل یک
tool
ویژگی (نام ابزاری که باید فراخوانی شود) و الفtool_input
ویژگی (ورودی آن ابزار). - AgentFinish: این کلاس داده نشان می دهد که عامل وظیفه خود را به پایان رسانده است و باید پاسخی را به کاربر بازگرداند. معمولاً شامل یک فرهنگ لغت از مقادیر بازگشتی است که اغلب با یک کلید "خروجی" حاوی متن پاسخ است.
- مراحل میانی: اینها سوابق اقدامات عامل قبلی و خروجی های مربوطه هستند. آنها برای انتقال زمینه به تکرارهای آتی عامل بسیار مهم هستند.
در مثال ما از OpenAI Function Calling برای ایجاد عامل خود استفاده خواهیم کرد. این رویکرد برای ایجاد عامل قابل اعتماد است. ما با ایجاد یک ابزار ساده که طول یک کلمه را محاسبه می کند شروع می کنیم. این ابزار مفید است زیرا مدلهای زبانی ممکن است گاهی اوقات به دلیل توکنسازی هنگام شمارش طول کلمات اشتباه کنند.
ابتدا، بیایید مدل زبانی را که برای کنترل عامل استفاده می کنیم، بارگذاری کنیم:
from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
بیایید مدل را با محاسبه طول کلمه آزمایش کنیم:
llm.invoke("how many letters in the word educa?")
پاسخ باید تعداد حروف کلمه "educa" را نشان دهد.
در مرحله بعد، یک تابع ساده پایتون برای محاسبه طول یک کلمه تعریف می کنیم:
from langchain.agents import tool @tool
def get_word_length(word: str) -> int: """Returns the length of a word.""" return len(word)
ما ابزاری به نام ایجاد کرده ایم get_word_length
که یک کلمه را به عنوان ورودی می گیرد و طول آن را برمی گرداند.
اکنون، بیایید درخواست را برای عامل ایجاد کنیم. اعلان به عامل دستور می دهد که چگونه خروجی را استدلال و قالب بندی کند. در مورد ما، ما از OpenAI Function Calling استفاده می کنیم که به حداقل دستورالعمل نیاز دارد. ما درخواست را با متغیرهایی برای ورودی کاربر و صفحه اسکرچ عامل تعریف می کنیم:
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder prompt = ChatPromptTemplate.from_messages( [ ( "system", "You are a very powerful assistant but not great at calculating word lengths.", ), ("user", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]
)
حال، چگونه عامل می داند که از چه ابزارهایی می تواند استفاده کند؟ ما به مدلهای زبان فراخوانی تابع OpenAI تکیه میکنیم که باید توابع جداگانه ارسال شوند. برای ارائه ابزارهای خود به عامل، آنها را به صورت فراخوانی تابع OpenAI قالب بندی می کنیم:
from langchain.tools.render import format_tool_to_openai_function llm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools])
اکنون میتوانیم عامل را با تعریف نگاشت ورودی و اتصال مؤلفهها ایجاد کنیم:
این زبان LCEL است. بعداً به تفصیل در این مورد بحث خواهیم کرد.
from langchain.agents.format_scratchpad import format_to_openai_function_messages
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai _function_messages( x["intermediate_steps"] ), } | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser()
)
ما عامل خود را ایجاد کرده ایم که ورودی کاربر را درک می کند، از ابزارهای موجود استفاده می کند و خروجی را فرمت می کند. حالا بیایید با آن تعامل کنیم:
agent.invoke({"input": "how many letters in the word educa?", "intermediate_steps": []})
نماینده باید با یک AgentAction پاسخ دهد که نشان دهنده اقدام بعدی است.
ما عامل را ایجاد کرده ایم، اما اکنون باید یک زمان اجرا برای آن بنویسیم. ساده ترین زمان اجرا زمانی است که به طور مداوم عامل را فراخوانی می کند، اقدامات را اجرا می کند و تا زمانی که عامل تمام شود تکرار می شود. در اینجا یک مثال است:
from langchain.schema.agent import AgentFinish user_input = "how many letters in the word educa?"
intermediate_steps = [] while True: output = agent.invoke( { "input": user_input, "intermediate_steps": intermediate_steps, } ) if isinstance(output, AgentFinish): final_result = output.return_values["output"] break else: print(f"TOOL NAME: {output.tool}") print(f"TOOL INPUT: {output.tool_input}") tool = {"get_word_length": get_word_length}[output.tool] observation = tool.run(output.tool_input) intermediate_steps.append((output, observation)) print(final_result)
در این حلقه، ما به طور مکرر عامل را فراخوانی می کنیم، اقدامات را اجرا می کنیم و مراحل میانی را به روز می کنیم تا زمانی که عامل به پایان برسد. ما همچنین تعاملات ابزار را در حلقه مدیریت می کنیم.
برای سادهسازی این فرآیند، LangChain کلاس AgentExecutor را ارائه میکند که اجرای عامل را محصور میکند و مدیریت خطا، توقف اولیه، ردیابی و سایر پیشرفتها را ارائه میدهد. بیایید از AgentExecutor برای تعامل با عامل استفاده کنیم:
from langchain.agents import AgentExecutor agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) agent_executor.invoke({"input": "how many letters in the word educa?"})
AgentExecutor فرآیند اجرا را ساده می کند و راه مناسبی برای تعامل با عامل ارائه می دهد.
حافظه نیز بعداً به تفصیل مورد بحث قرار خواهد گرفت.
عاملی که ما تا کنون ایجاد کردهایم فاقد وضعیت است، یعنی تعاملات قبلی را به خاطر نمیآورد. برای فعال کردن سؤالات و مکالمات بعدی، باید حافظه را به نماینده اضافه کنیم. این شامل دو مرحله است:
- برای ذخیره تاریخچه چت، یک متغیر حافظه در اعلان اضافه کنید.
- سابقه چت را در طول تعامل پیگیری کنید.
بیایید با اضافه کردن یک مکان نگهدار حافظه در اعلان شروع کنیم:
from langchain.prompts import MessagesPlaceholder MEMORY_KEY = "chat_history"
prompt = ChatPromptTemplate.from_messages( [ ( "system", "You are a very powerful assistant but not great at calculating word lengths.", ), MessagesPlaceholder(variable_name=MEMORY_KEY), ("user", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]
)
اکنون، یک لیست برای ردیابی تاریخچه چت ایجاد کنید:
from langchain.schema.messages import HumanMessage, AIMessage chat_history = []
در مرحله ایجاد عامل، حافظه را نیز اضافه می کنیم:
agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai_function_messages( x["intermediate_steps"] ), "chat_history": lambda x: x["chat_history"], } | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser()
)
اکنون، هنگام اجرای عامل، مطمئن شوید که تاریخچه چت را به روز کنید:
input1 = "how many letters 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": "is that a real word?", "chat_history": chat_history})
این عامل را قادر می سازد تا تاریخچه مکالمه را حفظ کند و به سؤالات بعدی بر اساس تعاملات قبلی پاسخ دهد.
تبریک می گویم! شما با موفقیت اولین نماینده سرتاسر خود را در LangChain ایجاد و اجرا کردید. برای بررسی عمیقتر قابلیتهای LangChain، میتوانید کاوش کنید:
- انواع مختلف عامل پشتیبانی می شود.
- عوامل از پیش ساخته شده
- نحوه کار با ابزارها و ادغام ابزار.
انواع عامل
LangChain انواع مختلفی را ارائه می دهد که هر کدام برای موارد استفاده خاص مناسب هستند. در اینجا برخی از عوامل موجود آورده شده است:
- Zero-shot ReAct: این عامل از چارچوب ReAct برای انتخاب ابزار صرفاً بر اساس توضیحات آنها استفاده می کند. این نیاز به توضیحات برای هر ابزار دارد و بسیار متنوع است.
- ورودی ساختار یافته ReAct: این عامل ابزارهای چند ورودی را مدیریت می کند و برای کارهای پیچیده مانند پیمایش در مرورگر وب مناسب است. از طرح استدلال ابزار برای ورودی ساختاریافته استفاده می کند.
- توابع OpenAI: این عامل بهطور خاص برای مدلهایی که برای فراخوانی عملکرد تنظیم شدهاند طراحی شده است، با مدلهایی مانند gpt-3.5-turbo-0613 و gpt-4-0613 سازگار است. ما از این برای ایجاد اولین عامل خود در بالا استفاده کردیم.
- مکالمه ای: این عامل که برای تنظیمات مکالمه طراحی شده است، از ReAct برای انتخاب ابزار استفاده می کند و از حافظه برای یادآوری تعاملات قبلی استفاده می کند.
- با جستجو از خود بپرسید: این عامل بر یک ابزار واحد، "پاسخ میانی" متکی است که پاسخ های واقعی به سوالات را جستجو می کند. این معادل همان سوال اصلی خود با مقاله جستجو است.
- ذخیره اسناد ReAct: این عامل با استفاده از چارچوب ReAct با یک فروشگاه اسناد تعامل دارد. این به ابزارهای «جستجو» و «جستجو» نیاز دارد و مشابه نمونه ویکیپدیا مقاله اصلی ReAct است.
این انواع نمایندگی را کاوش کنید تا در LangChain یکی را پیدا کنید که به بهترین وجه با نیازهای شما مطابقت دارد. این عوامل به شما این امکان را میدهند که مجموعهای از ابزارها را در درون آنها به هم متصل کنید تا اقدامات را مدیریت کرده و پاسخها را تولید کنید. بیشتر بدانید چگونه می توانید نماینده خود را با ابزارهای اینجا بسازید.
عوامل از پیش ساخته شده
بیایید به کاوش خود در مورد نمایندگان ادامه دهیم و بر عوامل از پیش ساخته شده موجود در LangChain تمرکز کنیم.
جیمیل
LangChain یک جعبه ابزار Gmail را ارائه می دهد که به شما امکان می دهد ایمیل LangChain خود را به API Gmail متصل کنید. برای شروع، باید اعتبارنامه خود را تنظیم کنید، که در مستندات Gmail API توضیح داده شده است. وقتی که دانلود کردید credentials.json
فایل، می توانید با استفاده از Gmail API ادامه دهید. علاوه بر این، باید چند کتابخانه مورد نیاز را با استفاده از دستورات زیر نصب کنید:
pip install --upgrade google-api-python-client > /dev/null
pip install --upgrade google-auth-oauthlib > /dev/null
pip install --upgrade google-auth-httplib2 > /dev/null
pip install beautifulsoup4 > /dev/null # Optional for parsing HTML messages
شما می توانید جعبه ابزار Gmail را به صورت زیر ایجاد کنید:
from langchain.agents.agent_toolkits import GmailToolkit toolkit = GmailToolkit()
همچنین می توانید احراز هویت را بر اساس نیاز خود سفارشی کنید. در پشت صحنه، یک منبع googleapi با استفاده از روش های زیر ایجاد می شود:
from langchain.tools.gmail.utils import build_resource_service, get_gmail_credentials credentials = get_gmail_credentials( token_file="token.json", scopes=["https://mail.google.com/"], client_secrets_file="credentials.json",
)
api_resource = build_resource_service(credentials=credentials)
toolkit = GmailToolkit(api_resource=api_resource)
جعبه ابزار ابزارهای مختلفی را ارائه می دهد که می توانند در یک عامل استفاده شوند، از جمله:
GmailCreateDraft
: یک ایمیل پیش نویس با فیلدهای پیام مشخص شده ایجاد کنید.GmailSendMessage
: ارسال پیام های ایمیل.GmailSearch
: پیام های ایمیل یا رشته ها را جستجو کنید.GmailGetMessage
: یک ایمیل با شناسه پیام واکشی کنید.GmailGetThread
: پیام های ایمیل را جستجو کنید.
برای استفاده از این ابزارها در یک عامل، می توانید عامل را به صورت زیر مقداردهی کنید:
from langchain.llms import OpenAI
from langchain.agents import initialize_agent, AgentType llm = OpenAI(temperature=0)
agent = initialize_agent( tools=toolkit.get_tools(), llm=llm, agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
)
در اینجا چند مثال از نحوه استفاده از این ابزار آورده شده است:
- یک پیش نویس جیمیل برای ویرایش ایجاد کنید:
agent.run( "Create a gmail draft for me to edit of a letter from the perspective of a sentient parrot " "who is looking to collaborate on some research with her estranged friend, a cat. " "Under no circumstances may you send the message, however."
)
- آخرین ایمیل را در پیش نویس های خود جستجو کنید:
agent.run("Could you search in my drafts for the latest email?")
این مثالها قابلیتهای جعبه ابزار Gmail LangChain را در یک نماینده نشان میدهند و شما را قادر میسازد تا به صورت برنامهنویسی با Gmail تعامل داشته باشید.
عامل پایگاه داده SQL
این بخش یک نمای کلی از یک عامل طراحی شده برای تعامل با پایگاه های داده SQL، به ویژه پایگاه داده Chinook را ارائه می دهد. این عامل می تواند به سوالات کلی در مورد پایگاه داده پاسخ دهد و خطاها را بازیابی کند. لطفاً توجه داشته باشید که هنوز در حال توسعه فعال است و ممکن است همه پاسخ ها صحیح نباشند. هنگام اجرای آن بر روی داده های حساس محتاط باشید، زیرا ممکن است دستورات DML را در پایگاه داده شما انجام دهد.
برای استفاده از این عامل، می توانید آن را به صورت زیر مقداردهی اولیه کنید:
from langchain.agents import create_sql_agent
from langchain.agents.agent_toolkits import SQLDatabaseToolkit
from langchain.sql_database import SQLDatabase
from langchain.llms.openai import OpenAI
from langchain.agents import AgentExecutor
from langchain.agents.agent_types import AgentType
from langchain.chat_models import ChatOpenAI db = SQLDatabase.from_uri("sqlite:///../../../../../notebooks/Chinook.db")
toolkit = SQLDatabaseToolkit(db=db, llm=OpenAI(temperature=0)) agent_executor = create_sql_agent( llm=OpenAI(temperature=0), toolkit=toolkit, verbose=True, agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
)
این عامل را می توان با استفاده از ZERO_SHOT_REACT_DESCRIPTION
نوع عامل برای پاسخ به سوالات و ارائه توضیحات طراحی شده است. یا می توانید عامل را با استفاده از عبارت مقداردهی اولیه کنید OPENAI_FUNCTIONS
نوع عامل با مدل GPT-3.5-turbo OpenAI، که ما در مشتری قبلی خود از آن استفاده کردیم.
سلب مسئولیت
- زنجیره پرس و جو ممکن است جستارهای درج/به روز رسانی/حذف ایجاد کند. محتاط باشید و در صورت نیاز از یک درخواست سفارشی استفاده کنید یا یک کاربر SQL بدون مجوز نوشتن ایجاد کنید.
- توجه داشته باشید که اجرای برخی پرس و جوها، مانند "اجرای بزرگترین پرس و جو ممکن"، می تواند پایگاه داده SQL شما را بارگذاری کند، به خصوص اگر حاوی میلیون ها ردیف باشد.
- پایگاه داده های انبار گرا اغلب از سهمیه های سطح کاربر برای محدود کردن استفاده از منابع پشتیبانی می کنند.
میتوانید از نماینده بخواهید که جدولی، مانند جدول «لیست آهنگ» را توصیف کند. در اینجا مثالی از نحوه انجام آن آورده شده است:
agent_executor.run("Describe the playlisttrack table")
عامل اطلاعاتی در مورد طرحواره جدول و ردیف های نمونه ارائه می دهد.
اگر به اشتباه در مورد جدولی که وجود ندارد سؤال کنید، عامل می تواند بازیابی کند و اطلاعاتی درباره نزدیکترین جدول تطبیق ارائه کند. مثلا:
agent_executor.run("Describe the playlistsong table")
نماینده نزدیکترین جدول تطبیق را پیدا می کند و اطلاعاتی در مورد آن ارائه می دهد.
همچنین می توانید از عامل بخواهید که پرس و جوهایی را در پایگاه داده اجرا کند. برای مثال:
agent_executor.run("List the total sales per country. Which country's customers spent the most?")
نماینده پرس و جو را اجرا می کند و نتیجه را ارائه می دهد، مانند کشوری که بیشترین فروش کل را دارد.
برای دریافت تعداد کل آهنگهای موجود در هر فهرست پخش، میتوانید از عبارت زیر استفاده کنید:
agent_executor.run("Show the total number of tracks in each playlist. The Playlist name should be included in the result.")
نماینده نام لیست پخش را به همراه تعداد کل آهنگ مربوطه برمی گرداند.
در مواردی که نماینده با خطا مواجه می شود، می تواند بازیابی و پاسخ های دقیق ارائه دهد. برای مثال:
agent_executor.run("Who are the top 3 best selling artists?")
حتی پس از مواجهه با خطای اولیه، نماینده به تنظیم و ارائه پاسخ صحیح میپردازد که در این صورت 3 هنرمند پرفروش است.
Pandas DataFrame Agent
این بخش عاملی را معرفی می کند که برای تعامل با Pandas DataFrames برای اهداف پاسخگویی به سؤالات طراحی شده است. لطفاً توجه داشته باشید که این عامل از عامل پایتون در زیر هود برای اجرای کد پایتون تولید شده توسط یک مدل زبان (LLM) استفاده می کند. هنگام استفاده از این عامل برای جلوگیری از آسیب احتمالی کدهای مخرب پایتون تولید شده توسط LLM احتیاط کنید.
می توانید عامل Pandas DataFrame را به صورت زیر مقداردهی کنید:
from langchain_experimental.agents.agent_toolkits import create_pandas_dataframe_agent
from langchain.chat_models import ChatOpenAI
from langchain.agents.agent_types import AgentType from langchain.llms import OpenAI
import pandas as pd df = pd.read_csv("titanic.csv") # Using ZERO_SHOT_REACT_DESCRIPTION agent type
agent = create_pandas_dataframe_agent(OpenAI(temperature=0), df, verbose=True) # Alternatively, using OPENAI_FUNCTIONS agent type
# agent = create_pandas_dataframe_agent(
# ChatOpenAI(temperature=0, model="gpt-3.5-turbo-0613"),
# df,
# verbose=True,
# agent_type=AgentType.OPENAI_FUNCTIONS,
# )
میتوانید از عامل بخواهید تعداد ردیفهای DataFrame را بشمارد:
agent.run("how many rows are there?")
عامل کد را اجرا می کند df.shape[0]
و پاسخی مانند "891 ردیف در چارچوب داده وجود دارد" را ارائه دهید.
همچنین میتوانید از نماینده بخواهید ردیفها را بر اساس معیارهای خاص، مانند یافتن تعداد افرادی که بیش از ۳ خواهر و برادر دارند، فیلتر کند:
agent.run("how many people have more than 3 siblings")
عامل کد را اجرا می کند df[df['SibSp'] > 3].shape[0]
و پاسخی مانند "30 نفر بیش از 3 خواهر و برادر دارند" را ارائه دهید.
اگر می خواهید جذر میانگین سنی را محاسبه کنید، می توانید از نماینده بپرسید:
agent.run("whats the square root of the average age?")
عامل با استفاده از میانگین سنی را محاسبه می کند df['Age'].mean()
و سپس جذر را با استفاده از آن محاسبه کنید math.sqrt()
. این پاسخ را ارائه می دهد، مانند "ریشه دوم میانگین سنی 5.449689683556195 است."
بیایید یک کپی از DataFrame ایجاد کنیم و مقادیر سن از دست رفته با میانگین سن پر می شوند:
df1 = df.copy()
df1["Age"] = df1["Age"].fillna(df1["Age"].mean())
سپس، می توانید عامل را با هر دو DataFrame مقداردهی کنید و از آن یک سوال بپرسید:
agent = create_pandas_dataframe_agent(OpenAI(temperature=0), [df, df1], verbose=True)
agent.run("how many rows in the age column are different?")
عامل ستون های سنی را در هر دو DataFrame مقایسه می کند و پاسخی را ارائه می دهد، مانند "177 ردیف در ستون سن متفاوت است."
جعبه ابزار جیرا
این بخش نحوه استفاده از جعبه ابزار Jira را توضیح می دهد که به عوامل اجازه می دهد تا با یک نمونه Jira تعامل داشته باشند. با استفاده از این جعبه ابزار می توانید اقدامات مختلفی مانند جستجوی مسائل و ایجاد مشکلات را انجام دهید. از کتابخانه atlassian-python-api استفاده می کند. برای استفاده از این جعبه ابزار، باید متغیرهای محیطی را برای نمونه Jira خود تنظیم کنید، از جمله JIRA_API_TOKEN، JIRA_USERNAME، و JIRA_INSTANCE_URL. علاوه بر این، ممکن است لازم باشد کلید OpenAI API خود را به عنوان یک متغیر محیطی تنظیم کنید.
برای شروع، کتابخانه atlassian-python-api را نصب کنید و متغیرهای محیط مورد نیاز را تنظیم کنید:
%pip install atlassian-python-api import os
from langchain.agents import AgentType
from langchain.agents import initialize_agent
from langchain.agents.agent_toolkits.jira.toolkit import JiraToolkit
from langchain.llms import OpenAI
from langchain.utilities.jira import JiraAPIWrapper os.environ["JIRA_API_TOKEN"] = "abc"
os.environ["JIRA_USERNAME"] = "123"
os.environ["JIRA_INSTANCE_URL"] = "https://jira.atlassian.com"
os.environ["OPENAI_API_KEY"] = "xyz" llm = OpenAI(temperature=0)
jira = JiraAPIWrapper()
toolkit = JiraToolkit.from_jira_api_wrapper(jira)
agent = initialize_agent( toolkit.get_tools(), llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)
شما می توانید به نماینده دستور دهید که یک شماره جدید در یک پروژه خاص با خلاصه و توضیحات ایجاد کند:
agent.run("make a new issue in project PW to remind me to make more fried rice")
نماینده اقدامات لازم را برای ایجاد مشکل و ارائه پاسخ انجام می دهد، مانند "یک شماره جدید در پروژه PW با خلاصه "برنج سرخ شده بیشتر بسازید" و توضیحات "یادآوری برای تهیه برنج بیشتر سرخ شده" ایجاد شده است.
این به شما امکان می دهد با استفاده از دستورالعمل های زبان طبیعی و جعبه ابزار Jira با نمونه Jira خود تعامل داشته باشید.
کارها و گردشهای کار دستی را با سازنده گردش کار مبتنی بر هوش مصنوعی، که توسط Nanonets برای شما و تیمهایتان طراحی شده است، خودکار کنید.
ماژول چهارم: زنجیر
LangChain ابزاری است که برای استفاده از مدل های زبان بزرگ (LLM) در برنامه های پیچیده طراحی شده است. چارچوب هایی برای ایجاد زنجیره ای از مؤلفه ها، از جمله LLM ها و سایر انواع مؤلفه ها را فراهم می کند. دو چارچوب اولیه
- زبان بیان LangChain (LCEL)
- رابط زنجیره ای میراث
زبان بیان LangChain (LCEL) نحوی است که امکان ترکیب بصری زنجیرهها را فراهم میکند. از ویژگیهای پیشرفتهای مانند استریم، تماسهای ناهمزمان، دستهبندی، موازیسازی، تلاشهای مجدد، برگشتها و ردیابی پشتیبانی میکند. به عنوان مثال، میتوانید مانند کد زیر، یک تجزیهکننده فرمان، مدل و خروجی در LCEL بنویسید:
from langchain.prompts import ChatPromptTemplate
from langchain.schema import StrOutputParser model = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
prompt = ChatPromptTemplate.from_messages([ ("system", "You're a very knowledgeable historian who provides accurate and eloquent answers to historical questions."), ("human", "{question}")
])
runnable = prompt | model | StrOutputParser() for chunk in runnable.stream({"question": "What are the seven wonders of the world"}): print(chunk, end="", flush=True)
از طرف دیگر، LLMChain گزینه ای مشابه LCEL برای ترکیب کامپوننت ها است. مثال LLMCchain به شرح زیر است:
from langchain.chains import LLMChain chain = LLMChain(llm=model, prompt=prompt, output_parser=StrOutputParser())
chain.run(question="What are the seven wonders of the world")
زنجیرهها در LangChain همچنین میتوانند با ترکیب یک شیء حافظه، حالتی داشته باشند. همانطور که در این مثال نشان داده شده است، این امکان برای ماندگاری داده ها در سراسر تماس ها وجود دارد:
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory conversation = ConversationChain(llm=chat, memory=ConversationBufferMemory())
conversation.run("Answer briefly. What are the first 3 colors of a rainbow?")
conversation.run("And the next 4?")
LangChain همچنین از ادغام با APIهای فراخوانی تابع OpenAI پشتیبانی می کند، که برای به دست آوردن خروجی های ساختاریافته و اجرای توابع در یک زنجیره مفید است. برای بدست آوردن خروجی های ساختاریافته، می توانید آنها را با استفاده از کلاس های Pydantic یا JsonSchema مشخص کنید، همانطور که در زیر نشان داده شده است:
from langchain.pydantic_v1 import BaseModel, Field
from langchain.chains.openai_functions import create_structured_output_runnable
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate class Person(BaseModel): name: str = Field(..., description="The person's name") age: int = Field(..., description="The person's age") fav_food: Optional[str] = Field(None, description="The person's favorite food") llm = ChatOpenAI(model="gpt-4", temperature=0)
prompt = ChatPromptTemplate.from_messages([ # Prompt messages here
]) runnable = create_structured_output_runnable(Person, llm, prompt)
runnable.invoke({"input": "Sally is 13"})
برای خروجی های ساختاریافته، یک رویکرد قدیمی با استفاده از LLMChain نیز موجود است:
from langchain.chains.openai_functions import create_structured_output_chain class Person(BaseModel): name: str = Field(..., description="The person's name") age: int = Field(..., description="The person's age") chain = create_structured_output_chain(Person, llm, prompt, verbose=True)
chain.run("Sally is 13")
LangChain از توابع OpenAI برای ایجاد زنجیره های خاص مختلف برای اهداف مختلف استفاده می کند. اینها شامل زنجیرههایی برای استخراج، برچسبگذاری، OpenAPI و QA با استناد است.
در زمینه استخراج، فرآیند شبیه به زنجیره خروجی ساختاریافته است اما بر استخراج اطلاعات یا موجودیت متمرکز است. برای برچسب گذاری، ایده این است که یک سند را با طبقاتی مانند احساسات، زبان، سبک، موضوعات تحت پوشش یا گرایش سیاسی برچسب گذاری کنید.
نمونه ای از نحوه عملکرد برچسب گذاری در LangChain را می توان با کد پایتون نشان داد. فرآیند با نصب بسته های لازم و راه اندازی محیط شروع می شود:
pip install langchain openai
# Set env var OPENAI_API_KEY or load from a .env file:
# import dotenv
# dotenv.load_dotenv() from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.chains import create_tagging_chain, create_tagging_chain_pydantic
طرح واره برای برچسب گذاری تعریف می شود و ویژگی ها و انواع مورد انتظار آنها را مشخص می کند:
schema = { "properties": { "sentiment": {"type": "string"}, "aggressiveness": {"type": "integer"}, "language": {"type": "string"}, }
} llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo-0613")
chain = create_tagging_chain(schema, llm)
مثالهایی از اجرای زنجیره برچسبگذاری با ورودیهای مختلف، توانایی مدل را در تفسیر احساسات، زبانها و پرخاشگری نشان میدهد:
inp = "Estoy increiblemente contento de haberte conocido! Creo que seremos muy buenos amigos!"
chain.run(inp)
# {'sentiment': 'positive', 'language': 'Spanish'} inp = "Estoy muy enojado con vos! Te voy a dar tu merecido!"
chain.run(inp)
# {'sentiment': 'enojado', 'aggressiveness': 1, 'language': 'es'}
برای کنترل دقیق تر، طرحواره را می توان به طور خاص تری تعریف کرد، از جمله مقادیر ممکن، توضیحات، و ویژگی های مورد نیاز. نمونه ای از این کنترل پیشرفته در زیر نشان داده شده است:
schema = { "properties": { # Schema definitions here }, "required": ["language", "sentiment", "aggressiveness"],
} chain = create_tagging_chain(schema, llm)
طرحواره های Pydantic همچنین می توانند برای تعریف معیارهای برچسب گذاری استفاده شوند، و یک روش پایتونیک برای تعیین ویژگی ها و انواع مورد نیاز ارائه می دهند:
from enum import Enum
from pydantic import BaseModel, Field class Tags(BaseModel): # Class fields here chain = create_tagging_chain_pydantic(Tags, llm)
بهعلاوه، ترانسفورماتور سند برچسبگذار ابرداده LangChain را میتوان برای استخراج ابرداده از اسناد LangChain استفاده کرد، که عملکردی مشابه زنجیره برچسبگذاری را ارائه میدهد اما برای یک سند LangChain اعمال میشود.
استناد به منابع بازیابی یکی دیگر از ویژگی های LangChain است که از توابع OpenAI برای استخراج نقل قول ها از متن استفاده می کند. این در کد زیر نشان داده شده است:
from langchain.chains import create_citation_fuzzy_match_chain
from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo-0613")
chain = create_citation_fuzzy_match_chain(llm)
# Further code for running the chain and displaying results
در LangChain، زنجیرهسازی در برنامههای کاربردی مدل زبان بزرگ (LLM) معمولاً شامل ترکیب یک الگوی سریع با یک LLM و در صورت اختیاری یک تجزیهکننده خروجی است. روش توصیه شده برای انجام این کار از طریق زبان بیان LangChain (LCEL) است، اگرچه رویکرد قدیمی LLMChain نیز پشتیبانی می شود.
با استفاده از LCEL، BasePromptTemplate، BaseLanguageModel و BaseOutputParser همگی رابط Runnable را پیاده سازی می کنند و می توانند به راحتی در یکدیگر لوله شوند. در اینجا یک مثال نشان دهنده این است:
from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.schema import StrOutputParser prompt = PromptTemplate.from_template( "What is a good name for a company that makes {product}?"
)
runnable = prompt | ChatOpenAI() | StrOutputParser()
runnable.invoke({"product": "colorful socks"})
# Output: 'VibrantSocks'
مسیریابی در LangChain امکان ایجاد زنجیره های غیر قطعی را فراهم می کند که در آن خروجی مرحله قبلی مرحله بعدی را تعیین می کند. این به ساختار و حفظ ثبات در تعامل با LLM کمک می کند. به عنوان مثال، اگر دو قالب دارید که برای انواع مختلف سوالات بهینه شده اند، می توانید الگو را بر اساس ورودی کاربر انتخاب کنید.
در اینجا نحوه دستیابی به این هدف با استفاده از LCEL با RunnableBranch آورده شده است که با لیستی از جفتهای (شرط، قابل اجرا) و یک قابل اجرا پیشفرض مقداردهی اولیه میشود:
from langchain.chat_models import ChatOpenAI
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnableBranch
# Code for defining physics_prompt and math_prompt general_prompt = PromptTemplate.from_template( "You are a helpful assistant. Answer the question as accurately as you can.nn{input}"
)
prompt_branch = RunnableBranch( (lambda x: x["topic"] == "math", math_prompt), (lambda x: x["topic"] == "physics", physics_prompt), general_prompt,
) # More code for setting up the classifier and final chain
سپس زنجیره نهایی با استفاده از اجزای مختلف مانند طبقهبندیکننده موضوع، شاخه سریع و تجزیهکننده خروجی ساخته میشود تا جریان را بر اساس موضوع ورودی تعیین کند:
from operator import itemgetter
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough final_chain = ( RunnablePassthrough.assign(topic=itemgetter("input") | classifier_chain) | prompt_branch | ChatOpenAI() | StrOutputParser()
) final_chain.invoke( { "input": "What is the first prime number greater than 40 such that one plus the prime number is divisible by 3?" }
)
# Output: Detailed answer to the math question
این رویکرد انعطاف پذیری و قدرت LangChain را در رسیدگی به پرس و جوهای پیچیده و مسیریابی مناسب آنها بر اساس ورودی را نشان می دهد.
در قلمرو مدلهای زبان، یک روش معمول این است که یک تماس اولیه را با یک سری تماسهای بعدی دنبال کنید و از خروجی یک تماس به عنوان ورودی برای تماس بعدی استفاده کنید. این رویکرد متوالی به ویژه زمانی مفید است که بخواهید بر اساس اطلاعات تولید شده در تعاملات قبلی ایجاد کنید. در حالی که زبان بیان LangChain (LCEL) روش توصیه شده برای ایجاد این توالی ها است، روش SequentialChain هنوز برای سازگاری با عقب آن مستند شده است.
برای نشان دادن این موضوع، بیایید سناریویی را در نظر بگیریم که در آن ابتدا یک خلاصه داستان و سپس یک بررسی بر اساس آن خلاصه میکنیم. با استفاده از پایتون langchain.prompts
، ما دو را ایجاد می کنیم PromptTemplate
موارد: یکی برای خلاصه و دیگری برای بررسی. در اینجا کد تنظیم این قالب ها آمده است:
from langchain.prompts import PromptTemplate synopsis_prompt = PromptTemplate.from_template( "You are a playwright. Given the title of play, it is your job to write a synopsis for that title.nnTitle: {title}nPlaywright: This is a synopsis for the above play:"
) review_prompt = PromptTemplate.from_template( "You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.nnPlay Synopsis:n{synopsis}nReview from a New York Times play critic of the above play:"
)
در رویکرد LCEL، ما این اعلان ها را با آن زنجیر می کنیم ChatOpenAI
و StrOutputParser
برای ایجاد سکانسی که ابتدا یک خلاصه داستان و سپس یک بررسی ایجاد می کند. قطعه کد به شرح زیر است:
from langchain.chat_models import ChatOpenAI
from langchain.schema import StrOutputParser llm = ChatOpenAI()
chain = ( {"synopsis": synopsis_prompt | llm | StrOutputParser()} | review_prompt | llm | StrOutputParser()
)
chain.invoke({"title": "Tragedy at sunset on the beach"})
اگر هم به خلاصه و هم به بررسی نیاز داریم، می توانیم استفاده کنیم RunnablePassthrough
برای ایجاد یک زنجیره جداگانه برای هر یک و سپس ترکیب آنها:
from langchain.schema.runnable import RunnablePassthrough synopsis_chain = synopsis_prompt | llm | StrOutputParser()
review_chain = review_prompt | llm | StrOutputParser()
chain = {"synopsis": synopsis_chain} | RunnablePassthrough.assign(review=review_chain)
chain.invoke({"title": "Tragedy at sunset on the beach"})
برای سناریوهایی که شامل دنبالههای پیچیدهتر هستند، SequentialChain
روش وارد عمل می شود این امکان ورودی و خروجی های متعدد را فراهم می کند. موردی را در نظر بگیرید که در آن به خلاصه ای بر اساس عنوان و دوره نمایشنامه نیاز داریم. در اینجا نحوه تنظیم آن آمده است:
from langchain.llms import OpenAI
from langchain.chains import LLMChain, SequentialChain
from langchain.prompts import PromptTemplate llm = OpenAI(temperature=0.7) synopsis_template = "You are a playwright. Given the title of play and the era it is set in, it is your job to write a synopsis for that title.nnTitle: {title}nEra: {era}nPlaywright: This is a synopsis for the above play:"
synopsis_prompt_template = PromptTemplate(input_variables=["title", "era"], template=synopsis_template)
synopsis_chain = LLMChain(llm=llm, prompt=synopsis_prompt_template, output_key="synopsis") review_template = "You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.nnPlay Synopsis:n{synopsis}nReview from a New York Times play critic of the above play:"
prompt_template = PromptTemplate(input_variables=["synopsis"], template=review_template)
review_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="review") overall_chain = SequentialChain( chains=[synopsis_chain, review_chain], input_variables=["era", "title"], output_variables=["synopsis", "review"], verbose=True,
) overall_chain({"title": "Tragedy at sunset on the beach", "era": "Victorian England"})
در سناریوهایی که می خواهید زمینه را در سراسر یک زنجیره یا برای بخش بعدی زنجیره حفظ کنید، SimpleMemory
می تواند به کار رود. این به ویژه برای مدیریت روابط پیچیده ورودی/خروجی مفید است. به عنوان مثال، در سناریویی که میخواهیم پستهای رسانههای اجتماعی را بر اساس عنوان، دوره، خلاصه و بررسی یک نمایشنامه تولید کنیم، SimpleMemory
می تواند به مدیریت این متغیرها کمک کند:
from langchain.memory import SimpleMemory
from langchain.chains import SequentialChain template = "You are a social media manager for a theater company. Given the title of play, the era it is set in, the date, time and location, the synopsis of the play, and the review of the play, it is your job to write a social media post for that play.nnHere is some context about the time and location of the play:nDate and Time: {time}nLocation: {location}nnPlay Synopsis:n{synopsis}nReview from a New York Times play critic of the above play:n{review}nnSocial Media Post:"
prompt_template = PromptTemplate(input_variables=["synopsis", "review", "time", "location"], template=template)
social_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="social_post_text") overall_chain = SequentialChain( memory=SimpleMemory(memories={"time": "December 25th, 8pm PST", "location": "Theater in the Park"}), chains=[synopsis_chain, review_chain, social_chain], input_variables=["era", "title"], output_variables=["social_post_text"], verbose=True,
) overall_chain({"title": "Tragedy at sunset on the beach", "era": "Victorian England"})
علاوه بر زنجیره های متوالی، زنجیره های تخصصی برای کار با اسناد وجود دارد. هر یک از این زنجیرهها هدف متفاوتی را دنبال میکنند، از ترکیب اسناد تا اصلاح پاسخها بر اساس تجزیه و تحلیل اسناد تکراری، نقشهبرداری و کاهش محتوای سند برای خلاصهسازی یا رتبهبندی مجدد بر اساس پاسخهای امتیازدهی شده. این زنجیرهها را میتوان با LCEL برای انعطافپذیری و سفارشیسازی بیشتر بازسازی کرد.
-
StuffDocumentsChain
فهرستی از اسناد را در یک اعلان واحد که به یک LLM ارسال می شود ترکیب می کند. -
RefineDocumentsChain
پاسخ خود را به طور مکرر برای هر سند به روز می کند، مناسب برای کارهایی که اسناد از ظرفیت بافت مدل فراتر می رود. -
MapReduceDocumentsChain
یک زنجیره را برای هر سند به صورت جداگانه اعمال می کند و سپس نتایج را ترکیب می کند. -
MapRerankDocumentsChain
هر پاسخ مبتنی بر سند را نمره می دهد و بالاترین امتیاز را انتخاب می کند.
در اینجا مثالی از نحوه راه اندازی a آورده شده است MapReduceDocumentsChain
با استفاده از LCEL:
from functools import partial
from langchain.chains.combine_documents import collapse_docs, split_list_of_docs
from langchain.schema import Document, StrOutputParser
from langchain.schema.prompt_template import format_document
from langchain.schema.runnable import RunnableParallel, RunnablePassthrough llm = ChatAnthropic()
document_prompt = PromptTemplate.from_template("{page_content}")
partial_format_document = partial(format_document, prompt=document_prompt) map_chain = ( {"context": partial_format_document} | PromptTemplate.from_template("Summarize this content:nn{context}") | llm | StrOutputParser()
) map_as_doc_chain = ( RunnableParallel({"doc": RunnablePassthrough(), "content": map_chain}) | (lambda x: Document(page_content=x["content"], metadata=x["doc"].metadata))
).with_config(run_name="Summarize (return doc)") def format_docs(docs): return "nn".join(partial_format_document(doc) for doc in docs) collapse_chain = ( {"context": format_docs} | PromptTemplate.from_template("Collapse this content:nn{context}") | llm | StrOutputParser()
) reduce_chain = ( {"context": format_docs} | PromptTemplate.from_template("Combine these summaries:nn{context}") | llm | StrOutputParser()
).with_config(run_name="Reduce") map_reduce = (map_as_doc_chain.map() | collapse | reduce_chain).with_config(run_name="Map reduce")
این پیکربندی امکان تجزیه و تحلیل دقیق و جامع محتوای سند را فراهم می کند و از نقاط قوت LCEL و مدل زبان زیربنایی استفاده می کند.
کارها و گردشهای کار دستی را با سازنده گردش کار مبتنی بر هوش مصنوعی، که توسط Nanonets برای شما و تیمهایتان طراحی شده است، خودکار کنید.
ماژول V: حافظه
در LangChain، حافظه یک جنبه اساسی از رابطهای مکالمه است که به سیستمها اجازه میدهد به تعاملات گذشته اشاره کنند. این امر از طریق ذخیره و جستجوی اطلاعات، با دو عمل اصلی: خواندن و نوشتن به دست می آید. سیستم حافظه دو بار در طول اجرا با یک زنجیره تعامل می کند و ورودی های کاربر را افزایش می دهد و ورودی ها و خروجی ها را برای مراجعات بعدی ذخیره می کند.
ساخت حافظه در یک سیستم
- ذخیره سازی پیام های چت: ماژول حافظه LangChain روش های مختلفی را برای ذخیره پیام های چت، از لیست های درون حافظه گرفته تا پایگاه های داده، ادغام می کند. این تضمین می کند که تمام تعاملات چت برای مراجعات بعدی ثبت می شود.
- پرس و جو از پیام های چت: فراتر از ذخیره پیام های چت، LangChain از ساختارهای داده و الگوریتم ها برای ایجاد نمای مفیدی از این پیام ها استفاده می کند. سیستمهای حافظه ساده ممکن است پیامهای اخیر را برگردانند، در حالی که سیستمهای پیشرفتهتر میتوانند تعاملات گذشته را خلاصه کنند یا بر موجودیتهای ذکر شده در تعامل فعلی تمرکز کنند.
برای نشان دادن استفاده از حافظه در LangChain، این را در نظر بگیرید ConversationBufferMemory
class، یک فرم حافظه ساده که پیام های چت را در یک بافر ذخیره می کند. در اینجا یک مثال است:
from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory()
memory.chat_memory.add_user_message("Hello!")
memory.chat_memory.add_ai_message("How can I assist you?")
هنگام ادغام حافظه در یک زنجیره، درک متغیرهای بازگشتی از حافظه و نحوه استفاده از آنها در زنجیره بسیار مهم است. به عنوان مثال، load_memory_variables
روش کمک می کند تا متغیرهای خوانده شده از حافظه با انتظارات زنجیره تراز شوند.
مثال سرتاسری با LangChain
استفاده را در نظر بگیرید ConversationBufferMemory
در LLMChain
. این زنجیره، همراه با یک الگوی سریع و حافظه مناسب، یک تجربه مکالمه یکپارچه را فراهم می کند. در اینجا یک مثال ساده آورده شده است:
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory llm = OpenAI(temperature=0)
template = "Your conversation template here..."
prompt = PromptTemplate.from_template(template)
memory = ConversationBufferMemory(memory_key="chat_history")
conversation = LLMChain(llm=llm, prompt=prompt, memory=memory) response = conversation({"question": "What's the weather like?"})
این مثال نشان میدهد که چگونه سیستم حافظه LangChain با زنجیرههای خود یکپارچه میشود تا یک تجربه مکالمه منسجم و آگاهانه را فراهم کند.
انواع حافظه در Langchain
Langchain انواع حافظه های مختلفی را ارائه می دهد که می توان از آنها برای تقویت تعامل با مدل های هوش مصنوعی استفاده کرد. هر نوع حافظه پارامترها و انواع بازگشتی خاص خود را دارد که آنها را برای سناریوهای مختلف مناسب می کند. بیایید برخی از انواع حافظه های موجود در Langchain را به همراه نمونه کد بررسی کنیم.
1. حافظه بافر مکالمه
این نوع حافظه به شما امکان ذخیره و استخراج پیام ها از مکالمات را می دهد. می توانید تاریخچه را به صورت رشته یا لیستی از پیام ها استخراج کنید.
from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory()
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.load_memory_variables({}) # Extract history as a string
{'history': 'Human: hinAI: whats up'} # Extract history as a list of messages
{'history': [HumanMessage(content='hi', additional_kwargs={}), AIMessage(content='whats up', additional_kwargs={})]}
همچنین می توانید از حافظه بافر مکالمه در یک زنجیره برای تعاملات چت مانند استفاده کنید.
2. حافظه پنجره بافر مکالمه
این نوع حافظه فهرستی از فعل و انفعالات اخیر را نگه می دارد و از آخرین تعاملات K استفاده می کند و از بزرگ شدن بافر جلوگیری می کند.
from langchain.memory import ConversationBufferWindowMemory memory = ConversationBufferWindowMemory(k=1)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context({"input": "not much you"}, {"output": "not much"})
memory.load_memory_variables({}) {'history': 'Human: not much younAI: not much'}
مانند حافظه بافر مکالمه، شما همچنین می توانید از این نوع حافظه در یک زنجیره برای تعاملات چت مانند استفاده کنید.
3. حافظه موجودیت مکالمه
این نوع حافظه حقایق مربوط به موجودیت های خاص را در یک مکالمه به خاطر می آورد و اطلاعات را با استفاده از LLM استخراج می کند.
from langchain.memory import ConversationEntityMemory
from langchain.llms import OpenAI llm = OpenAI(temperature=0)
memory = ConversationEntityMemory(llm=llm)
_input = {"input": "Deven & Sam are working on a hackathon project"}
memory.load_memory_variables(_input)
memory.save_context( _input, {"output": " That sounds like a great project! What kind of project are they working on?"}
)
memory.load_memory_variables({"input": 'who is Sam'}) {'history': 'Human: Deven & Sam are working on a hackathon projectnAI: That sounds like a great project! What kind of project are they working on?', 'entities': {'Sam': 'Sam is working on a hackathon project with Deven.'}}
4. حافظه نمودار دانش مکالمه
این نوع حافظه از یک نمودار دانش برای بازسازی حافظه استفاده می کند. می توانید موجودیت های فعلی و سه گانه دانش را از پیام ها استخراج کنید.
from langchain.memory import ConversationKGMemory
from langchain.llms import OpenAI llm = OpenAI(temperature=0)
memory = ConversationKGMemory(llm=llm)
memory.save_context({"input": "say hi to sam"}, {"output": "who is sam"})
memory.save_context({"input": "sam is a friend"}, {"output": "okay"})
memory.load_memory_variables({"input": "who is sam"}) {'history': 'On Sam: Sam is friend.'}
همچنین می توانید از این نوع حافظه در یک زنجیره برای بازیابی دانش مبتنی بر مکالمه استفاده کنید.
5. حافظه خلاصه مکالمه
این نوع حافظه خلاصه ای از مکالمه را در طول زمان ایجاد می کند که برای فشرده سازی اطلاعات مکالمات طولانی تر مفید است.
from langchain.memory import ConversationSummaryMemory
from langchain.llms import OpenAI llm = OpenAI(temperature=0)
memory = ConversationSummaryMemory(llm=llm)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.load_memory_variables({}) {'history': 'nThe human greets the AI, to which the AI responds.'}
6. خلاصه مکالمه حافظه بافر
این نوع حافظه خلاصه مکالمه و بافر را ترکیب می کند و تعادل بین تعاملات اخیر و خلاصه را حفظ می کند. از طول رمز برای تعیین زمان شستشوی تعاملات استفاده می کند.
from langchain.memory import ConversationSummaryBufferMemory
from langchain.llms import OpenAI llm = OpenAI()
memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=10)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context({"input": "not much you"}, {"output": "not much"})
memory.load_memory_variables({}) {'history': 'System: nThe human says "hi", and the AI responds with "whats up".nHuman: not much younAI: not much'}
می توانید از این انواع حافظه برای تقویت تعاملات خود با مدل های هوش مصنوعی در Langchain استفاده کنید. هر نوع حافظه هدف خاصی را دنبال می کند و می تواند بر اساس نیاز شما انتخاب شود.
7. حافظه بافر رمز مکالمه
ConversationTokenBufferMemory نوع دیگری از حافظه است که بافری از تعاملات اخیر را در حافظه نگه می دارد. برخلاف انواع حافظه قبلی که بر تعداد فعل و انفعالات تمرکز می کنند، این حافظه از طول رمز برای تعیین زمان شستشوی تعاملات استفاده می کند.
استفاده از حافظه با LLM:
from langchain.memory import ConversationTokenBufferMemory
from langchain.llms import OpenAI llm = OpenAI() memory = ConversationTokenBufferMemory(llm=llm, max_token_limit=10)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context({"input": "not much you"}, {"output": "not much"}) memory.load_memory_variables({}) {'history': 'Human: not much younAI: not much'}
در این مثال، حافظه تنظیم شده است تا تعاملات را بر اساس طول نشانه به جای تعداد تعاملات محدود کند.
همچنین می توانید هنگام استفاده از این نوع حافظه، تاریخچه را به عنوان لیستی از پیام ها دریافت کنید.
memory = ConversationTokenBufferMemory( llm=llm, max_token_limit=10, return_messages=True
)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context({"input": "not much you"}, {"output": "not much"})
استفاده در زنجیره:
می توانید از ConversationTokenBufferMemory در یک زنجیره برای بهبود تعاملات با مدل هوش مصنوعی استفاده کنید.
from langchain.chains import ConversationChain conversation_with_summary = ConversationChain( llm=llm, # We set a very low max_token_limit for the purposes of testing. memory=ConversationTokenBufferMemory(llm=OpenAI(), max_token_limit=60), verbose=True,
)
conversation_with_summary.predict(input="Hi, what's up?")
در این مثال، ConversationTokenBufferMemory در یک ConversationChain برای مدیریت مکالمه و محدود کردن تعاملات بر اساس طول توکن استفاده میشود.
8. VectorStoreRetrieverMemory
VectorStoreRetrieverMemory حافظهها را در یک فروشگاه برداری ذخیره میکند و هر بار که فراخوانی میشود، بالاترین K ترین اسناد را جستجو میکند. این نوع حافظه به طور صریح ترتیب تعاملات را ردیابی نمی کند، اما از بازیابی برداری برای واکشی خاطرات مربوطه استفاده می کند.
from datetime import datetime
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.llms import OpenAI
from langchain.memory import VectorStoreRetrieverMemory
from langchain.chains import ConversationChain
from langchain.prompts import PromptTemplate # Initialize your vector store (specifics depend on the chosen vector store)
import faiss
from langchain.docstore import InMemoryDocstore
from langchain.vectorstores import FAISS embedding_size = 1536 # Dimensions of the OpenAIEmbeddings
index = faiss.IndexFlatL2(embedding_size)
embedding_fn = OpenAIEmbeddings().embed_query
vectorstore = FAISS(embedding_fn, index, InMemoryDocstore({}), {}) # Create your VectorStoreRetrieverMemory
retriever = vectorstore.as_retriever(search_kwargs=dict(k=1))
memory = VectorStoreRetrieverMemory(retriever=retriever) # Save context and relevant information to the memory
memory.save_context({"input": "My favorite food is pizza"}, {"output": "that's good to know"})
memory.save_context({"input": "My favorite sport is soccer"}, {"output": "..."})
memory.save_context({"input": "I don't like the Celtics"}, {"output": "ok"}) # Retrieve relevant information from memory based on a query
print(memory.load_memory_variables({"prompt": "what sport should i watch?"})["history"])
در این مثال، VectorStoreRetrieverMemory برای ذخیره و بازیابی اطلاعات مرتبط از یک مکالمه بر اساس بازیابی برداری استفاده می شود.
همانطور که در مثال های قبلی نشان داده شده است، همچنین می توانید از VectorStoreRetrieverMemory در یک زنجیره برای بازیابی دانش مبتنی بر مکالمه استفاده کنید.
این انواع مختلف حافظه در Langchain راههای مختلفی را برای مدیریت و بازیابی اطلاعات از مکالمات ارائه میکنند و قابلیتهای مدلهای هوش مصنوعی را در درک و پاسخ به پرسشهای کاربر و زمینه افزایش میدهند. هر نوع حافظه را می توان بر اساس نیازهای خاص برنامه شما انتخاب کرد.
اکنون نحوه استفاده از حافظه با LLMCchain را یاد خواهیم گرفت. حافظه در یک زنجیره LLMC به مدل اجازه می دهد تا تعاملات و زمینه قبلی را به خاطر بسپارد تا پاسخ های منسجم و آگاهانه تری را ارائه دهد.
برای تنظیم حافظه در LLMChain، باید یک کلاس حافظه مانند ConversationBufferMemory ایجاد کنید. در اینجا نحوه تنظیم آن آمده است:
from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.memory import ConversationBufferMemory
from langchain.prompts import PromptTemplate template = """You are a chatbot having a conversation with a human. {chat_history}
Human: {human_input}
Chatbot:""" prompt = PromptTemplate( input_variables=["chat_history", "human_input"], template=template
)
memory = ConversationBufferMemory(memory_key="chat_history") llm = OpenAI()
llm_chain = LLMChain( llm=llm, prompt=prompt, verbose=True, memory=memory,
) llm_chain.predict(human_input="Hi there my friend")
در این مثال، ConversationBufferMemory برای ذخیره تاریخچه مکالمه استفاده می شود. این memory_key
پارامتر کلید مورد استفاده برای ذخیره تاریخچه مکالمه را مشخص می کند.
اگر از یک مدل چت به جای یک مدل به سبک تکمیل استفاده می کنید، می توانید برای استفاده بهتر از حافظه، دستورات خود را متفاوت ساختار دهید. در اینجا مثالی از نحوه راه اندازی یک LLMChain مبتنی بر مدل چت با حافظه آورده شده است:
from langchain.chat_models import ChatOpenAI
from langchain.schema import SystemMessage
from langchain.prompts import ( ChatPromptTemplate, HumanMessagePromptTemplate, MessagesPlaceholder,
) # Create a ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages( [ SystemMessage( content="You are a chatbot having a conversation with a human." ), # The persistent system prompt MessagesPlaceholder( variable_name="chat_history" ), # Where the memory will be stored. HumanMessagePromptTemplate.from_template( "{human_input}" ), # Where the human input will be injected ]
) memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True) llm = ChatOpenAI() chat_llm_chain = LLMChain( llm=llm, prompt=prompt, verbose=True, memory=memory,
) chat_llm_chain.predict(human_input="Hi there my friend")
در این مثال، ChatPromptTemplate برای ساختار اعلان و ConversationBufferMemory برای ذخیره و بازیابی تاریخچه مکالمه استفاده می شود. این رویکرد به ویژه برای مکالمات به سبک چت که در آن زمینه و تاریخ نقش مهمی دارند مفید است.
همچنین میتوان حافظه را با ورودیهای متعدد، مانند زنجیره پرسش/پاسخ، به زنجیره اضافه کرد. در اینجا مثالی از نحوه تنظیم حافظه در زنجیره پرسش/پاسخ آورده شده است:
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.embeddings.cohere import CohereEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores.elastic_vector_search import ElasticVectorSearch
from langchain.vectorstores import Chroma
from langchain.docstore.document import Document
from langchain.chains.question_answering import load_qa_chain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
from langchain.memory import ConversationBufferMemory # Split a long document into smaller chunks
with open("../../state_of_the_union.txt") as f: state_of_the_union = f.read()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_text(state_of_the_union) # Create an ElasticVectorSearch instance to index and search the document chunks
embeddings = OpenAIEmbeddings()
docsearch = Chroma.from_texts( texts, embeddings, metadatas=[{"source": i} for i in range(len(texts))]
) # Perform a question about the document
query = "What did the president say about Justice Breyer"
docs = docsearch.similarity_search(query) # Set up a prompt for the question-answering chain with memory
template = """You are a chatbot having a conversation with a human. Given the following extracted parts of a long document and a question, create a final answer. {context} {chat_history}
Human: {human_input}
Chatbot:""" prompt = PromptTemplate( input_variables=["chat_history", "human_input", "context"], template=template
)
memory = ConversationBufferMemory(memory_key="chat_history", input_key="human_input")
chain = load_qa_chain( OpenAI(temperature=0), chain_type="stuff", memory=memory, prompt=prompt
) # Ask the question and retrieve the answer
query = "What did the president say about Justice Breyer"
result = chain({"input_documents": docs, "human_input": query}, return_only_outputs=True) print(result)
print(chain.memory.buffer)
در این مثال، یک سوال با استفاده از یک سند تقسیم شده به تکه های کوچکتر پاسخ داده می شود. ConversationBufferMemory برای ذخیره و بازیابی تاریخچه مکالمه استفاده می شود و به مدل اجازه می دهد تا پاسخ های آگاه از زمینه را ارائه دهد.
افزودن حافظه به یک عامل به آن اجازه میدهد تا تعاملات قبلی را برای پاسخ دادن به سؤالات و ارائه پاسخهای آگاه به زمینه به خاطر بسپارد و از آن استفاده کند. در اینجا نحوه تنظیم حافظه در یک عامل آورده شده است:
from langchain.agents import ZeroShotAgent, Tool, AgentExecutor
from langchain.memory import ConversationBufferMemory
from langchain.llms import OpenAI
from langchain.chains import LLMChain
from langchain.utilities import GoogleSearchAPIWrapper # Create a tool for searching
search = GoogleSearchAPIWrapper()
tools = [ Tool( name="Search", func=search.run, description="useful for when you need to answer questions about current events", )
] # Create a prompt with memory
prefix = """Have a conversation with a human, answering the following questions as best you can. You have access to the following tools:"""
suffix = """Begin!" {chat_history}
Question: {input}
{agent_scratchpad}""" prompt = ZeroShotAgent.create_prompt( tools, prefix=prefix, suffix=suffix, input_variables=["input", "chat_history", "agent_scratchpad"],
)
memory = ConversationBufferMemory(memory_key="chat_history") # Create an LLMChain with memory
llm_chain = LLMChain(llm=OpenAI(temperature=0), prompt=prompt)
agent = ZeroShotAgent(llm_chain=llm_chain, tools=tools, verbose=True)
agent_chain = AgentExecutor.from_agent_and_tools( agent=agent, tools=tools, verbose=True, memory=memory
) # Ask a question and retrieve the answer
response = agent_chain.run(input="How many people live in Canada?")
print(response) # Ask a follow-up question
response = agent_chain.run(input="What is their national anthem called?")
print(response)
در این مثال، حافظه به یک عامل اضافه میشود و به آن اجازه میدهد تا تاریخچه مکالمه قبلی را به خاطر بسپارد و پاسخهای آگاه از زمینه را ارائه دهد. این عامل را قادر می سازد تا بر اساس اطلاعات ذخیره شده در حافظه به سؤالات بعدی به طور دقیق پاسخ دهد.
زبان بیان LangChain
در دنیای پردازش زبان طبیعی و یادگیری ماشین، ترکیب زنجیرههای پیچیده عملیات میتواند کاری دلهرهآور باشد. خوشبختانه، LangChain Expression Language (LCEL) به کمک می آید، و راهی شفاف و کارآمد برای ساخت و استقرار خطوط لوله پردازش زبان پیچیده ارائه می کند. LCEL برای ساده سازی فرآیند ترکیب زنجیره ها طراحی شده است، و این امکان را فراهم می کند که به راحتی از نمونه سازی به تولید برسیم. در این وبلاگ، ما بررسی خواهیم کرد که LCEL چیست و چرا ممکن است بخواهید از آن استفاده کنید، همراه با مثالهای کد عملی برای نشان دادن قابلیتهای آن.
LCEL یا LangChain Expression Language ابزاری قدرتمند برای نوشتن زنجیره های پردازش زبان است. این هدف به منظور پشتیبانی از انتقال از نمونه سازی اولیه به تولید یکپارچه، بدون نیاز به تغییرات گسترده کد ساخته شده است. چه در حال ساختن یک زنجیره ساده "prompt + LLM" یا یک خط لوله پیچیده با صدها مرحله باشید، LCEL شما را پوشش می دهد.
در اینجا چند دلیل برای استفاده از LCEL در پروژه های پردازش زبان خود آورده شده است:
- جریان سریع توکن: LCEL توکنها را از یک مدل زبان به تجزیهکننده خروجی در زمان واقعی تحویل میدهد و پاسخگویی و کارایی را بهبود میبخشد.
- APIهای همه کاره: LCEL از APIهای همزمان و ناهمزمان برای نمونه سازی و استفاده در تولید پشتیبانی می کند و چندین درخواست را به طور موثر مدیریت می کند.
- موازی سازی خودکار: LCEL اجرای موازی را در صورت امکان بهینه می کند و تأخیر را در رابط های همگام و همگام کاهش می دهد.
- پیکربندیهای قابل اعتماد: با پشتیبانی از پخش جریانی در حال توسعه، تلاشهای مجدد و بازگشت را برای قابلیت اطمینان زنجیره افزایش یافته در مقیاس پیکربندی کنید.
- Stream Intermediate Results: در طول پردازش برای بهروزرسانیهای کاربر یا اهداف اشکالزدایی، به نتایج میانی دسترسی پیدا کنید.
- ایجاد طرحواره: LCEL طرحواره های Pydantic و JSONSchema را برای اعتبارسنجی ورودی و خروجی تولید می کند.
- ردیابی جامع: LangSmith به طور خودکار تمام مراحل در زنجیره های پیچیده را برای مشاهده و اشکال زدایی ردیابی می کند.
- استقرار آسان: زنجیره های ایجاد شده توسط LCEL را بدون زحمت با استفاده از LangServe مستقر کنید.
حال، بیایید به نمونههای کد عملی که قدرت LCEL را نشان میدهند، بپردازیم. ما وظایف و سناریوهای متداول را که در آن LCEL می درخشد را بررسی خواهیم کرد.
Prompt + LLM
اساسی ترین ترکیب شامل ترکیب یک دستور و یک مدل زبان برای ایجاد زنجیره ای است که ورودی کاربر را می گیرد، آن را به یک اعلان اضافه می کند، آن را به یک مدل ارسال می کند و خروجی مدل خام را برمی گرداند. در اینجا یک مثال است:
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI prompt = ChatPromptTemplate.from_template("tell me a joke about {foo}")
model = ChatOpenAI()
chain = prompt | model result = chain.invoke({"foo": "bears"})
print(result)
در این مثال، زنجیره یک شوخی در مورد خرس ها ایجاد می کند.
می توانید دنباله های توقف را به زنجیره خود متصل کنید تا نحوه پردازش متن را کنترل کنید. مثلا:
chain = prompt | model.bind(stop=["n"])
result = chain.invoke({"foo": "bears"})
print(result)
این پیکربندی تولید متن را هنگامی که با یک کاراکتر خط جدید مواجه می شود متوقف می کند.
LCEL از پیوست کردن اطلاعات فراخوانی تابع به زنجیره شما پشتیبانی می کند. در اینجا یک مثال است:
functions = [ { "name": "joke", "description": "A joke", "parameters": { "type": "object", "properties": { "setup": {"type": "string", "description": "The setup for the joke"}, "punchline": { "type": "string", "description": "The punchline for the joke", }, }, "required": ["setup", "punchline"], }, }
]
chain = prompt | model.bind(function_call={"name": "joke"}, functions=functions)
result = chain.invoke({"foo": "bears"}, config={})
print(result)
این مثال اطلاعات فراخوانی تابع را برای ایجاد یک جوک پیوست می کند.
Prompt + LLM + OutputParser
میتوانید یک تجزیهکننده خروجی اضافه کنید تا خروجی مدل خام را به قالبی کاربردیتر تبدیل کنید. در اینجا نحوه انجام این کار آمده است:
from langchain.schema.output_parser import StrOutputParser chain = prompt | model | StrOutputParser()
result = chain.invoke({"foo": "bears"})
print(result)
خروجی اکنون در قالب رشته ای است که برای کارهای پایین دستی راحت تر است.
هنگام تعیین یک تابع برای بازگشت، می توانید آن را مستقیماً با استفاده از LCEL تجزیه کنید. مثلا:
from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser chain = ( prompt | model.bind(function_call={"name": "joke"}, functions=functions) | JsonOutputFunctionsParser()
)
result = chain.invoke({"foo": "bears"})
print(result)
این مثال خروجی تابع "جوک" را مستقیما تجزیه می کند.
اینها تنها چند نمونه از این هستند که چگونه LCEL وظایف پیچیده پردازش زبان را ساده می کند. چه در حال ساخت رباتهای چت، تولید محتوا یا انجام تغییرات متنی پیچیده باشید، LCEL میتواند گردش کار شما را سادهتر کند و کد شما را قابل نگهداریتر کند.
RAG (نسل تقویت شده با بازیابی)
از LCEL می توان برای ایجاد زنجیره های نسل افزوده بازیابی استفاده کرد که مراحل بازیابی و تولید زبان را ترکیب می کند. در اینجا یک مثال است:
from operator import itemgetter from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough, RunnableLambda
from langchain.vectorstores import FAISS # Create a vector store and retriever
vectorstore = FAISS.from_texts( ["harrison worked at kensho"], embedding=OpenAIEmbeddings()
)
retriever = vectorstore.as_retriever() # Define templates for prompts
template = """Answer the question based only on the following context:
{context} Question: {question} """
prompt = ChatPromptTemplate.from_template(template) model = ChatOpenAI() # Create a retrieval-augmented generation chain
chain = ( {"context": retriever, "question": RunnablePassthrough()} | prompt | model | StrOutputParser()
) result = chain.invoke("where did harrison work?")
print(result)
در این مثال، زنجیره اطلاعات مربوطه را از زمینه بازیابی می کند و پاسخی به سوال ایجاد می کند.
زنجیره بازیابی مکالمه
به راحتی می توانید تاریخچه مکالمه را به زنجیره های خود اضافه کنید. در اینجا مثالی از زنجیره بازیابی مکالمه آورده شده است:
from langchain.schema.runnable import RunnableMap
from langchain.schema import format_document from langchain.prompts.prompt import PromptTemplate # Define templates for prompts
_template = """Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question, in its original language. Chat History:
{chat_history}
Follow Up Input: {question}
Standalone question:"""
CONDENSE_QUESTION_PROMPT = PromptTemplate.from_template(_template) template = """Answer the question based only on the following context:
{context} Question: {question} """
ANSWER_PROMPT = ChatPromptTemplate.from_template(template) # Define input map and context
_inputs = RunnableMap( standalone_question=RunnablePassthrough.assign( chat_history=lambda x: _format_chat_history(x["chat_history"]) ) | CONDENSE_QUESTION_PROMPT | ChatOpenAI(temperature=0) | StrOutputParser(),
)
_context = { "context": itemgetter("standalone_question") | retriever | _combine_documents, "question": lambda x: x["standalone_question"],
}
conversational_qa_chain = _inputs | _context | ANSWER_PROMPT | ChatOpenAI() result = conversational_qa_chain.invoke( { "question": "where did harrison work?", "chat_history": [], }
)
print(result)
در این مثال، زنجیره یک سوال بعدی را در یک زمینه مکالمه بررسی می کند.
با حافظه و اسناد منبع برگشتی
LCEL همچنین از حافظه و اسناد منبع بازگشتی پشتیبانی می کند. در اینجا نحوه استفاده از حافظه در یک زنجیره آورده شده است:
from operator import itemgetter
from langchain.memory import ConversationBufferMemory # Create a memory instance
memory = ConversationBufferMemory( return_messages=True, output_key="answer", input_key="question"
) # Define steps for the chain
loaded_memory = RunnablePassthrough.assign( chat_history=RunnableLambda(memory.load_memory_variables) | itemgetter("history"),
) standalone_question = { "standalone_question": { "question": lambda x: x["question"], "chat_history": lambda x: _format_chat_history(x["chat_history"]), } | CONDENSE_QUESTION_PROMPT | ChatOpenAI(temperature=0) | StrOutputParser(),
} retrieved_documents = { "docs": itemgetter("standalone_question") | retriever, "question": lambda x: x["standalone_question"],
} final_inputs = { "context": lambda x: _combine_documents(x["docs"]), "question": itemgetter("question"),
} answer = { "answer": final_inputs | ANSWER_PROMPT | ChatOpenAI(), "docs": itemgetter("docs"),
} # Create the final chain by combining the steps
final_chain = loaded_memory | standalone_question | retrieved_documents | answer inputs = {"question": "where did harrison work?"}
result = final_chain.invoke(inputs)
print(result)
در این مثال، حافظه برای ذخیره و بازیابی تاریخچه مکالمه و اسناد منبع استفاده می شود.
زنجیرهای چندگانه
با استفاده از Runnables می توانید چندین زنجیره را به هم متصل کنید. در اینجا یک مثال است:
from operator import itemgetter from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import StrOutputParser prompt1 = ChatPromptTemplate.from_template("what is the city {person} is from?")
prompt2 = ChatPromptTemplate.from_template( "what country is the city {city} in? respond in {language}"
) model = ChatOpenAI() chain1 = prompt1 | model | StrOutputParser() chain2 = ( {"city": chain1, "language": itemgetter("language")} | prompt2 | model | StrOutputParser()
) result = chain2.invoke({"person": "obama", "language": "spanish"})
print(result)
در این مثال، دو زنجیره برای تولید اطلاعات در مورد یک شهر و کشور آن به یک زبان مشخص ترکیب شدهاند.
انشعاب و ادغام
LCEL به شما امکان می دهد زنجیره ها را با استفاده از RunnableMaps تقسیم و ادغام کنید. در اینجا نمونه ای از انشعاب و ادغام آورده شده است:
from operator import itemgetter from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import StrOutputParser planner = ( ChatPromptTemplate.from_template("Generate an argument about: {input}") | ChatOpenAI() | StrOutputParser() | {"base_response": RunnablePassthrough()}
) arguments_for = ( ChatPromptTemplate.from_template( "List the pros or positive aspects of {base_response}" ) | ChatOpenAI() | StrOutputParser()
)
arguments_against = ( ChatPromptTemplate.from_template( "List the cons or negative aspects of {base_response}" ) | ChatOpenAI() | StrOutputParser()
) final_responder = ( ChatPromptTemplate.from_messages( [ ("ai", "{original_response}"), ("human", "Pros:n{results_1}nnCons:n{results_2}"), ("system", "Generate a final response given the critique"), ] ) | ChatOpenAI() | StrOutputParser()
) chain = ( planner | { "results_1": arguments_for, "results_2": arguments_against, "original_response": itemgetter("base_response"), } | final_responder
) result = chain.invoke({"input": "scrum"})
print(result)
در این مثال، یک زنجیره انشعاب و ادغام برای ایجاد یک استدلال و ارزیابی جوانب مثبت و منفی آن قبل از ایجاد پاسخ نهایی استفاده می شود.
نوشتن کد پایتون با LCEL
یکی از کاربردهای قدرتمند LangChain Expression Language (LCEL) نوشتن کد پایتون برای حل مشکلات کاربران است. در زیر مثالی از نحوه استفاده از LCEL برای نوشتن کد پایتون آورده شده است:
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain_experimental.utilities import PythonREPL template = """Write some python code to solve the user's problem. Return only python code in Markdown format, e.g.: ```python
....
```"""
prompt = ChatPromptTemplate.from_messages([("system", template), ("human", "{input}")]) model = ChatOpenAI() def _sanitize_output(text: str): _, after = text.split("```python") return after.split("```")[0] chain = prompt | model | StrOutputParser() | _sanitize_output | PythonREPL().run result = chain.invoke({"input": "what's 2 plus 2"})
print(result)
در این مثال، یک کاربر ورودی ارائه می دهد و LCEL کد پایتون را برای حل مشکل تولید می کند. سپس کد با استفاده از Python REPL اجرا میشود و کد پایتون حاصل با فرمت Markdown برگردانده میشود.
لطفاً توجه داشته باشید که استفاده از Python REPL میتواند کد دلخواه را اجرا کند، بنابراین با احتیاط از آن استفاده کنید.
اضافه کردن حافظه به یک زنجیره
حافظه در بسیاری از برنامه های هوش مصنوعی مکالمه ضروری است. در اینجا نحوه افزودن حافظه به یک زنجیره دلخواه آورده شده است:
from operator import itemgetter
from langchain.chat_models import ChatOpenAI
from langchain.memory import ConversationBufferMemory
from langchain.schema.runnable import RunnablePassthrough, RunnableLambda
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder model = ChatOpenAI()
prompt = ChatPromptTemplate.from_messages( [ ("system", "You are a helpful chatbot"), MessagesPlaceholder(variable_name="history"), ("human", "{input}"), ]
) memory = ConversationBufferMemory(return_messages=True) # Initialize memory
memory.load_memory_variables({}) chain = ( RunnablePassthrough.assign( history=RunnableLambda(memory.load_memory_variables) | itemgetter("history") ) | prompt | model
) inputs = {"input": "hi, I'm Bob"}
response = chain.invoke(inputs)
response # Save the conversation in memory
memory.save_context(inputs, {"output": response.content}) # Load memory to see the conversation history
memory.load_memory_variables({})
در این مثال، حافظه برای ذخیره و بازیابی تاریخچه مکالمه استفاده میشود و به ربات چت اجازه میدهد متن را حفظ کرده و به طور مناسب پاسخ دهد.
استفاده از ابزارهای خارجی با Runnables
LCEL به شما امکان می دهد ابزارهای خارجی را به طور یکپارچه با Runnables ادغام کنید. در اینجا یک مثال با استفاده از ابزار جستجوی DuckDuckGo آورده شده است:
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.tools import DuckDuckGoSearchRun search = DuckDuckGoSearchRun() template = """Turn the following user input into a search query for a search engine: {input}"""
prompt = ChatPromptTemplate.from_template(template) model = ChatOpenAI() chain = prompt | model | StrOutputParser() | search search_result = chain.invoke({"input": "I'd like to figure out what games are tonight"})
print(search_result)
در این مثال، LCEL ابزار جستجوی DuckDuckGo را در زنجیره ادغام میکند و به آن اجازه میدهد یک عبارت جستجو از ورودی کاربر ایجاد کند و نتایج جستجو را بازیابی کند.
انعطافپذیری LCEL باعث میشود که ابزارها و سرویسهای خارجی مختلف را در خط لولههای پردازش زبان خود به آسانی بگنجانید و قابلیتها و عملکرد آنها را افزایش دهید.
اضافه کردن Moderation به یک برنامه LLM
برای اطمینان از اینکه برنامه LLM شما به خطمشیهای محتوا پایبند است و شامل پادمانهای تعدیل میشود، میتوانید بررسیهای اعتدال را در زنجیره خود ادغام کنید. در اینجا نحوه اضافه کردن تعدیل با استفاده از LangChain آمده است:
from langchain.chains import OpenAIModerationChain
from langchain.llms import OpenAI
from langchain.prompts import ChatPromptTemplate moderate = OpenAIModerationChain() model = OpenAI()
prompt = ChatPromptTemplate.from_messages([("system", "repeat after me: {input}")]) chain = prompt | model # Original response without moderation
response_without_moderation = chain.invoke({"input": "you are stupid"})
print(response_without_moderation) moderated_chain = chain | moderate # Response after moderation
response_after_moderation = moderated_chain.invoke({"input": "you are stupid"})
print(response_after_moderation)
در این مثال ، OpenAIModerationChain
برای افزودن تعدیل به پاسخ تولید شده توسط LLM استفاده می شود. زنجیره تعدیل پاسخ را برای محتوایی که خطمشی محتوای OpenAI را نقض میکند بررسی میکند. در صورت مشاهده هرگونه تخلف، پاسخ را بر اساس آن علامت گذاری می کند.
مسیریابی با تشابه معنایی
LCEL به شما امکان می دهد منطق مسیریابی سفارشی را بر اساس شباهت معنایی ورودی کاربر پیاده سازی کنید. در اینجا مثالی از نحوه تعیین پویا منطق زنجیره بر اساس ورودی کاربر آورده شده است:
from langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.prompts import PromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnableLambda, RunnablePassthrough
from langchain.utils.math import cosine_similarity physics_template = """You are a very smart physics professor. You are great at answering questions about physics in a concise and easy to understand manner. When you don't know the answer to a question you admit that you don't know. Here is a question:
{query}""" math_template = """You are a very good mathematician. You are great at answering math questions. You are so good because you are able to break down hard problems into their component parts, answer the component parts, and then put them together to answer the broader question. Here is a question:
{query}""" embeddings = OpenAIEmbeddings()
prompt_templates = [physics_template, math_template]
prompt_embeddings = embeddings.embed_documents(prompt_templates) def prompt_router(input): query_embedding = embeddings.embed_query(input["query"]) similarity = cosine_similarity([query_embedding], prompt_embeddings)[0] most_similar = prompt_templates[similarity.argmax()] print("Using MATH" if most_similar == math_template else "Using PHYSICS") return PromptTemplate.from_template(most_similar) chain = ( {"query": RunnablePassthrough()} | RunnableLambda(prompt_router) | ChatOpenAI() | StrOutputParser()
) print(chain.invoke({"query": "What's a black hole"}))
print(chain.invoke({"query": "What's a path integral"}))
در این مثال ، prompt_router
تابع شباهت کسینوس بین ورودی کاربر و الگوهای درخواستی از پیش تعریف شده برای سوالات فیزیک و ریاضی را محاسبه می کند. بر اساس امتیاز شباهت، زنجیره به صورت پویا مرتبطترین الگوی درخواستی را انتخاب میکند و اطمینان حاصل میکند که ربات چت به سؤال کاربر پاسخ مناسبی میدهد.
استفاده از Agents و Runnables
LangChain به شما اجازه می دهد تا با ترکیب Runnable ها، درخواست ها، مدل ها و ابزارها، عامل ایجاد کنید. در اینجا نمونه ای از ساخت یک عامل و استفاده از آن آورده شده است:
from langchain.agents import XMLAgent, tool, AgentExecutor
from langchain.chat_models import ChatAnthropic model = ChatAnthropic(model="claude-2") @tool
def search(query: str) -> str: """Search things about current events.""" return "32 degrees" tool_list = [search] # Get prompt to use
prompt = XMLAgent.get_default_prompt() # Logic for going from intermediate steps to a string to pass into the model
def convert_intermediate_steps(intermediate_steps): log = "" for action, observation in intermediate_steps: log += ( f"<tool>{action.tool}</tool><tool_input>{action.tool_input}" f"</tool_input><observation>{observation}</observation>" ) return log # Logic for converting tools to a string to go in the prompt
def convert_tools(tools): return "n".join([f"{tool.name}: {tool.description}" for tool in tools]) agent = ( { "question": lambda x: x["question"], "intermediate_steps": lambda x: convert_intermediate_steps( x["intermediate_steps"] ), } | prompt.partial(tools=convert_tools(tool_list)) | model.bind(stop=["</tool_input>", "</final_answer>"]) | XMLAgent.get_default_output_parser()
) agent_executor = AgentExecutor(agent=agent, tools=tool_list, verbose=True) result = agent_executor.invoke({"question": "What's the weather in New York?"})
print(result)
در این مثال، یک عامل با ترکیب یک مدل، ابزار، یک اعلان و یک منطق سفارشی برای مراحل میانی و تبدیل ابزار ایجاد میشود. سپس عامل اجرا می شود و به درخواست کاربر پاسخ می دهد.
جستجو در پایگاه داده SQL
شما می توانید از LangChain برای پرس و جو از پایگاه داده SQL و ایجاد پرس و جوهای SQL بر اساس سؤالات کاربر استفاده کنید. در اینجا یک مثال است:
from langchain.prompts import ChatPromptTemplate template = """Based on the table schema below, write a SQL query that would answer the user's question:
{schema} Question: {question}
SQL Query:"""
prompt = ChatPromptTemplate.from_template(template) from langchain.utilities import SQLDatabase # Initialize the database (you'll need the Chinook sample DB for this example)
db = SQLDatabase.from_uri("sqlite:///./Chinook.db") def get_schema(_): return db.get_table_info() def run_query(query): return db.run(query) from langchain.chat_models import ChatOpenAI
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough model = ChatOpenAI() sql_response = ( RunnablePassthrough.assign(schema=get_schema) | prompt | model.bind(stop=["nSQLResult:"]) | StrOutputParser()
) result = sql_response.invoke({"question": "How many employees are there?"})
print(result) template = """Based on the table schema below, question, SQL query, and SQL response, write a natural language response:
{schema} Question: {question}
SQL Query: {query}
SQL Response: {response}"""
prompt_response = ChatPromptTemplate.from_template(template) full_chain = ( RunnablePassthrough.assign(query=sql_response) | RunnablePassthrough.assign( schema=get_schema, response=lambda x: db.run(x["query"]), ) | prompt_response | model
) response = full_chain.invoke({"question": "How many employees are there?"})
print(response)
در این مثال، LangChain برای تولید پرس و جوهای SQL بر اساس سؤالات کاربر و بازیابی پاسخ ها از پایگاه داده SQL استفاده می شود. درخواستها و پاسخها برای ارائه تعامل زبان طبیعی با پایگاه داده فرمتبندی شدهاند.
کارها و گردشهای کار دستی را با سازنده گردش کار مبتنی بر هوش مصنوعی، که توسط Nanonets برای شما و تیمهایتان طراحی شده است، خودکار کنید.
LangServe & LangSmith
LangServe به توسعه دهندگان کمک می کند تا قابل اجراها و زنجیره های LangChain را به عنوان REST API مستقر کنند. این کتابخانه با FastAPI یکپارچه شده است و از pydantic برای اعتبارسنجی داده ها استفاده می کند. علاوه بر این، یک کلاینت را فراهم می کند که می تواند برای فراخوانی برنامه های قابل اجرا مستقر در سرور استفاده شود و یک کلاینت جاوا اسکریپت در LangChainJS در دسترس است.
امکانات
- طرحواره های ورودی و خروجی به طور خودکار از شی LangChain شما استنباط می شوند و در هر تماس API با پیام های خطای غنی اعمال می شوند.
- یک صفحه اسناد API با JSONSchema و Swagger در دسترس است.
- نقاط پایانی /invoke، /batch و /stream کارآمد با پشتیبانی از بسیاری از درخواستهای همزمان در یک سرور واحد.
- نقطه پایانی /stream_log برای پخش تمام (یا برخی) مراحل میانی از زنجیره/عامل شما.
- صفحه زمین بازی در /playground با خروجی جریان و مراحل میانی.
- ردیابی داخلی (اختیاری) به LangSmith. فقط کلید API خود را اضافه کنید (به دستورالعمل ها مراجعه کنید).
- همه با کتابخانههای منبع باز پایتون آزمایششده مانند FastAPI، Pydantic، uvloop و asyncio ساخته شدهاند.
محدودیت ها
- تماسهای مشتری هنوز برای رویدادهایی که در سرور ایجاد میشوند پشتیبانی نمیشوند.
- هنگام استفاده از Pydantic V2، اسناد OpenAPI ایجاد نمیشوند. FastAPI از ترکیب فضای نام pydantic v1 و v2 پشتیبانی نمی کند. برای جزئیات بیشتر به بخش زیر مراجعه کنید.
از LangChain CLI برای بوت استرپ سریع پروژه LangServe استفاده کنید. برای استفاده از langchain CLI، مطمئن شوید که نسخه جدیدی از langchain-cli را نصب کردهاید. می توانید آن را با pip install -U langchain-cli نصب کنید.
langchain app new ../path/to/directory
نمونه LangServe خود را به سرعت با الگوهای LangChain شروع کنید. برای مثالهای بیشتر، فهرست الگوها یا فهرست نمونهها را ببینید.
در اینجا سروری وجود دارد که یک مدل چت OpenAI، یک مدل چت Anthropic و یک زنجیره که از مدل Anthropic برای گفتن یک جوک در مورد یک موضوع استفاده می کند، وجود دارد.
#!/usr/bin/env python
from fastapi import FastAPI
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatAnthropic, ChatOpenAI
from langserve import add_routes app = FastAPI( title="LangChain Server", version="1.0", description="A simple api server using Langchain's Runnable interfaces",
) add_routes( app, ChatOpenAI(), path="/openai",
) add_routes( app, ChatAnthropic(), path="/anthropic",
) model = ChatAnthropic()
prompt = ChatPromptTemplate.from_template("tell me a joke about {topic}")
add_routes( app, prompt | model, path="/chain",
) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="localhost", port=8000)
هنگامی که سرور بالا را مستقر کردید، می توانید اسناد OpenAPI تولید شده را با استفاده از:
curl localhost:8000/docs
حتما پسوند /docs را اضافه کنید.
from langchain.schema import SystemMessage, HumanMessage
from langchain.prompts import ChatPromptTemplate
from langchain.schema.runnable import RunnableMap
from langserve import RemoteRunnable openai = RemoteRunnable("http://localhost:8000/openai/")
anthropic = RemoteRunnable("http://localhost:8000/anthropic/")
joke_chain = RemoteRunnable("http://localhost:8000/chain/") joke_chain.invoke({"topic": "parrots"}) # or async
await joke_chain.ainvoke({"topic": "parrots"}) prompt = [ SystemMessage(content='Act like either a cat or a parrot.'), HumanMessage(content='Hello!')
] # Supports astream
async for msg in anthropic.astream(prompt): print(msg, end="", flush=True) prompt = ChatPromptTemplate.from_messages( [("system", "Tell me a long story about {topic}")]
) # Can define custom chains
chain = prompt | RunnableMap({ "openai": openai, "anthropic": anthropic,
}) chain.batch([{ "topic": "parrots" }, { "topic": "cats" }])
در TypeScript (به LangChain.js نسخه 0.0.166 یا جدیدتر نیاز دارد):
import { RemoteRunnable } from "langchain/runnables/remote"; const chain = new RemoteRunnable({ url: `http://localhost:8000/chain/invoke/`,
});
const result = await chain.invoke({ topic: "cats",
});
پایتون با استفاده از درخواست ها:
import requests
response = requests.post( "http://localhost:8000/chain/invoke/", json={'input': {'topic': 'cats'}}
)
response.json()
شما همچنین می توانید از فر استفاده کنید:
curl --location --request POST 'http://localhost:8000/chain/invoke/' --header 'Content-Type: application/json' --data-raw '{ "input": { "topic": "cats" } }'
کد زیر:
...
add_routes( app, runnable, path="/my_runnable",
)
این نقاط پایانی را به سرور اضافه می کند:
- POST /my_runnable/invoke – قابل اجرا را روی یک ورودی فراخوانی کنید
- POST /my_runnable/batch – اجرا شدن را روی دسته ای از ورودی ها فراخوانی کنید
- POST /my_runnable/stream – در یک ورودی فراخوانی کنید و خروجی را پخش کنید
- POST /my_runnable/stream_log – در یک ورودی فراخوانی کنید و خروجی را پخش کنید، از جمله خروجی مراحل میانی در حین تولید
- دریافت /my_runnable/input_schema – طرحواره json برای ورودی به اجرا
- دریافت /my_runnable/output_schema – طرح json برای خروجی قابل اجرا
- دریافت /my_runnable/config_schema – طرح json برای پیکربندی فایل قابل اجرا
می توانید یک صفحه زمین بازی برای runnable خود در /my_runnable/playground پیدا کنید. این یک رابط کاربری ساده را برای پیکربندی و فراخوانی runnable خود با خروجی جریان و مراحل میانی نشان می دهد.
هم برای کلاینت و هم برای سرور:
pip install "langserve[all]"
یا pip install “langserve[client]” برای کد مشتری و pip install “langserve[server]” برای کد سرور.
اگر میخواهید احراز هویت را به سرور خود اضافه کنید، لطفاً به اسناد امنیتی FastAPI و اسناد میانافزار مراجعه کنید.
می توانید با استفاده از دستور زیر در GCP Cloud Run مستقر شوید:
gcloud run deploy [your-service-name] --source . --port 8001 --allow-unauthenticated --region us-central1 --set-env-vars=OPENAI_API_KEY=your_key
LangServe از Pydantic 2 با برخی محدودیت ها پشتیبانی می کند. هنگام استفاده از Pydantic V2، اسناد OpenAPI برای invoke/batch/stream/stream_log تولید نمیشوند. Fast API از ترکیب فضای نام pydantic v1 و v2 پشتیبانی نمی کند. LangChain از فضای نام v1 در Pydantic v2 استفاده می کند. لطفا دستورالعمل های زیر را برای اطمینان از سازگاری با LangChain بخوانید. به جز این محدودیتها، ما انتظار داریم که نقاط پایانی API، زمین بازی و هر ویژگی دیگری طبق انتظار عمل کنند.
برنامه های LLM اغلب با فایل ها سروکار دارند. معماری های مختلفی وجود دارد که می توان برای اجرای پردازش فایل ایجاد کرد. در سطح بالا:
- فایل ممکن است از طریق یک نقطه پایانی اختصاصی به سرور آپلود شود و با استفاده از یک نقطه پایانی جداگانه پردازش شود.
- فایل ممکن است با مقدار (بایت های فایل) یا مرجع (به عنوان مثال، url s3 به محتوای فایل) آپلود شود.
- نقطه پایانی پردازش ممکن است مسدود یا غیر مسدود باشد.
- اگر پردازش قابل توجهی مورد نیاز باشد، پردازش ممکن است به یک استخر فرآیند اختصاصی بارگذاری شود.
شما باید تعیین کنید که معماری مناسب برای برنامه شما چیست. در حال حاضر، برای آپلود فایل ها بر اساس مقدار در یک runnable، از رمزگذاری base64 برای فایل استفاده کنید (چند بخشی/فرم-داده هنوز پشتیبانی نمی شود).
در اینجا یک مثال که نحوه استفاده از کدگذاری base64 برای ارسال فایل به یک قابل اجرا از راه دور را نشان می دهد. به یاد داشته باشید، همیشه میتوانید فایلها را با مرجع آپلود کنید (مثلاً s3 url) یا آنها را بهعنوان دادههای چندبخشی/فرم در یک نقطه پایانی اختصاصی آپلود کنید.
انواع ورودی و خروجی در همه قابل اجراها تعریف شده است. می توانید از طریق خصوصیات input_schema و output_schema به آنها دسترسی داشته باشید. LangServe از این انواع برای اعتبار سنجی و مستندسازی استفاده می کند. اگر می خواهید انواع پیش فرض استنباط شده را لغو کنید، می توانید از روش with_types استفاده کنید.
در اینجا یک نمونه اسباب بازی برای نشان دادن این ایده آورده شده است:
from typing import Any
from fastapi import FastAPI
from langchain.schema.runnable import RunnableLambda app = FastAPI() def func(x: Any) -> int: """Mistyped function that should accept an int but accepts anything.""" return x + 1 runnable = RunnableLambda(func).with_types( input_schema=int,
) add_routes(app, runnable)
اگر میخواهید دادهها بهجای نمایش دیکتهای معادل، به یک مدل pydantic تبدیل شوند، از CustomUserType ارث بری کنید. در حال حاضر، این نوع فقط در سمت سرور کار می کند و برای تعیین رفتار رمزگشایی مورد نظر استفاده می شود. در صورت ارث بردن از این نوع، سرور به جای تبدیل آن به دیکت، نوع رمزگشایی شده را به عنوان یک مدل pydantic نگه می دارد.
from fastapi import FastAPI
from langchain.schema.runnable import RunnableLambda
from langserve import add_routes
from langserve.schema import CustomUserType app = FastAPI() class Foo(CustomUserType): bar: int def func(foo: Foo) -> int: """Sample function that expects a Foo type which is a pydantic model""" assert isinstance(foo, Foo) return foo.bar add_routes(app, RunnableLambda(func), path="/foo")
زمین بازی به شما این امکان را می دهد که ویجت های سفارشی را برای قابل اجرا از باطن تعریف کنید. ویجت در سطح فیلد مشخص شده و به عنوان بخشی از طرح JSON از نوع ورودی ارسال می شود. یک ویجت باید حاوی کلیدی به نام نوع باشد که مقدار آن یکی از لیست شناخته شده ویجت ها باشد. سایر کلیدهای ویجت با مقادیری مرتبط خواهند شد که مسیرها را در یک شی JSON توصیف می کنند.
طرح کلی:
type JsonPath = number | string | (number | string)[];
type NameSpacedPath = { title: string; path: JsonPath }; // Using title to mimic json schema, but can use namespace
type OneOfPath = { oneOf: JsonPath[] }; type Widget = { type: string // Some well-known type (e.g., base64file, chat, etc.) [key: string]: JsonPath | NameSpacedPath | OneOfPath;
};
ایجاد یک ورودی آپلود فایل در زمین بازی UI برای فایل هایی که به عنوان رشته های کدگذاری شده base64 آپلود می شوند، اجازه می دهد. در اینجا مثال کامل است.
try: from pydantic.v1 import Field
except ImportError: from pydantic import Field from langserve import CustomUserType # ATTENTION: Inherit from CustomUserType instead of BaseModel otherwise
# the server will decode it into a dict instead of a pydantic model.
class FileProcessingRequest(CustomUserType): """Request including a base64 encoded file.""" # The extra field is used to specify a widget for the playground UI. file: str = Field(..., extra={"widget": {"type": "base64file"}}) num_chars: int = 100
کارها و گردشهای کار دستی را با سازنده گردش کار مبتنی بر هوش مصنوعی، که توسط Nanonets برای شما و تیمهایتان طراحی شده است، خودکار کنید.
مقدمه ای بر لنگ اسمیت
LangChain نمونهسازی اولیه برنامهها و نمایندگان LLM را آسان میکند. با این حال، ارائه برنامه های کاربردی LLM به تولید می تواند به طرز فریبنده ای دشوار باشد. به احتمال زیاد مجبور خواهید بود برای ایجاد یک محصول با کیفیت بالا، درخواستها، زنجیرهها و سایر اجزای خود را به شدت سفارشی کنید و تکرار کنید.
برای کمک به این فرآیند، LangSmith، یک پلت فرم یکپارچه برای اشکال زدایی، آزمایش و نظارت بر برنامه های LLM شما معرفی شد.
چه زمانی این ممکن است مفید باشد؟ زمانی که بخواهید به سرعت یک زنجیره، عامل یا مجموعه ای از ابزارهای جدید را اشکال زدایی کنید، نحوه ارتباط و استفاده کامپوننت ها (زنجیره ها، llms، رتریورها و غیره) را تجسم کنید، اعلان ها و LLM های مختلف را برای یک جزء واحد ارزیابی کنید، ممکن است مفید باشد. یک زنجیره معین را چندین بار روی یک مجموعه داده اجرا کنید تا مطمئن شوید که به طور مداوم با یک نوار کیفیت مطابقت دارد، یا ردپای استفاده را ضبط کنید و از خطوط لوله LLM یا تجزیه و تحلیل برای ایجاد بینش استفاده کنید.
پیش نیازها:
- یک حساب LangSmith ایجاد کنید و یک کلید API ایجاد کنید (به گوشه سمت چپ پایین مراجعه کنید).
- با نگاه کردن به اسناد، با پلتفرم آشنا شوید.
حالا ، بیایید شروع کنیم!
ابتدا، متغیرهای محیط خود را طوری پیکربندی کنید که به LangChain بگویند ردیابی را ثبت کند. این کار با تنظیم متغیر محیطی LANGCHAIN_TRACING_V2 روی true انجام می شود. با تنظیم متغیر محیطی LANGCHAIN_PROJECT می توانید به LangChain بگویید که به کدام پروژه وارد شود (اگر این تنظیم نشده باشد، اجراها به پروژه پیش فرض ثبت می شوند). اگر پروژه وجود نداشته باشد، این به طور خودکار برای شما ایجاد می کند. همچنین باید متغیرهای محیطی LANGCHAIN_ENDPOINT و LANGCHAIN_API_KEY را تنظیم کنید.
توجه: شما همچنین می توانید از یک مدیر زمینه در پایتون برای ثبت ردیابی با استفاده از:
from langchain.callbacks.manager import tracing_v2_enabled with tracing_v2_enabled(project_name="My Project"): agent.run("How many people live in canada as of 2023?")
اما در این مثال از متغیرهای محیطی استفاده خواهیم کرد.
%pip install openai tiktoken pandas duckduckgo-search --quiet import os
from uuid import uuid4 unique_id = uuid4().hex[0:8]
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_PROJECT"] = f"Tracing Walkthrough - {unique_id}"
os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"
os.environ["LANGCHAIN_API_KEY"] = "<YOUR-API-KEY>" # Update to your API key # Used by the agent in this tutorial
os.environ["OPENAI_API_KEY"] = "<YOUR-OPENAI-API-KEY>"
کلاینت LangSmith را برای تعامل با API ایجاد کنید:
from langsmith import Client client = Client()
یک کامپوننت LangChain ایجاد کنید و log اجراها را در پلتفرم اجرا کنید. در این مثال، یک عامل به سبک ReAct با دسترسی به یک ابزار جستجوی عمومی (DuckDuckGo) ایجاد خواهیم کرد. درخواست نماینده را می توان در Hub در اینجا مشاهده کرد:
from langchain import hub
from langchain.agents import AgentExecutor
from langchain.agents.format_scratchpad import format_to_openai_function_messages
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser
from langchain.chat_models import ChatOpenAI
from langchain.tools import DuckDuckGoSearchResults
from langchain.tools.render import format_tool_to_openai_function # Fetches the latest version of this prompt
prompt = hub.pull("wfh/langsmith-agent-prompt:latest") llm = ChatOpenAI( model="gpt-3.5-turbo-16k", temperature=0,
) tools = [ DuckDuckGoSearchResults( name="duck_duck_go" ), # General internet search using DuckDuckGo
] llm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools]) runnable_agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai_function_messages( x["intermediate_steps"] ), } | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser()
) agent_executor = AgentExecutor( agent=runnable_agent, tools=tools, handle_parsing_errors=True
)
ما عامل را به طور همزمان روی چندین ورودی اجرا می کنیم تا تأخیر را کاهش دهیم. اجراها در پسزمینه به لانگ اسمیت ثبت میشوند، بنابراین تأخیر اجرا تحت تأثیر قرار نمیگیرد:
inputs = [ "What is LangChain?", "What's LangSmith?", "When was Llama-v2 released?", "What is the langsmith cookbook?", "When did langchain first announce the hub?",
] results = agent_executor.batch([{"input": x} for x in inputs], return_exceptions=True) results[:2]
با فرض اینکه محیط خود را با موفقیت راه اندازی کرده اید، ردیابی عامل شما باید در بخش پروژه ها در برنامه نمایش داده شود. تبریک میگم
به نظر می رسد که عامل به طور موثر از ابزارها استفاده نمی کند. بیایید این را ارزیابی کنیم تا یک خط پایه داشته باشیم.
LangSmith علاوه بر ورود به سیستم، به شما اجازه می دهد تا برنامه های LLM خود را آزمایش و ارزیابی کنید.
در این بخش، از LangSmith برای ایجاد یک مجموعه داده معیار و اجرای ارزیابیکنندگان به کمک هوش مصنوعی بر روی یک عامل استفاده میکنید. شما این کار را در چند مرحله انجام خواهید داد:
- ایجاد یک مجموعه داده LangSmith:
در زیر، ما از کلاینت LangSmith برای ایجاد یک مجموعه داده از سوالات ورودی از بالا و یک برچسب لیست استفاده می کنیم. بعداً از آنها برای اندازهگیری عملکرد یک عامل جدید استفاده خواهید کرد. مجموعه داده مجموعهای از نمونهها است که چیزی جز جفتهای ورودی-خروجی نیستند که میتوانید از آنها به عنوان موارد آزمایشی برای برنامه خود استفاده کنید:
outputs = [ "LangChain is an open-source framework for building applications using large language models. It is also the name of the company building LangSmith.", "LangSmith is a unified platform for debugging, testing, and monitoring language model applications and agents powered by LangChain", "July 18, 2023", "The langsmith cookbook is a github repository containing detailed examples of how to use LangSmith to debug, evaluate, and monitor large language model-powered applications.", "September 5, 2023",
] dataset_name = f"agent-qa-{unique_id}" dataset = client.create_dataset( dataset_name, description="An example dataset of questions over the LangSmith documentation.",
) for query, answer in zip(inputs, outputs): client.create_example( inputs={"input": query}, outputs={"output": answer}, dataset_id=dataset.id )
- راه اندازی یک عامل جدید برای معیار:
LangSmith به شما امکان می دهد هر LLM، زنجیره، عامل یا حتی یک تابع سفارشی را ارزیابی کنید. عوامل مکالمه حالت دار هستند (حافظه دارند). برای اطمینان از اینکه این حالت بین اجرای مجموعه داده به اشتراک گذاشته نمی شود، در یک chain_factory (
تابعی با نام مستعار سازنده) برای مقداردهی اولیه برای هر فراخوانی:
# Since chains can be stateful (e.g. they can have memory), we provide
# a way to initialize a new chain for each row in the dataset. This is done
# by passing in a factory function that returns a new chain for each row.
def agent_factory(prompt): llm_with_tools = llm.bind( functions=[format_tool_to_openai_function(t) for t in tools] ) runnable_agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai_function_messages( x["intermediate_steps"] ), } | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser() ) return AgentExecutor(agent=runnable_agent, tools=tools, handle_parsing_errors=True)
- پیکربندی ارزیابی:
مقایسه دستی نتایج زنجیرهها در رابط کاربری مؤثر است، اما میتواند زمانبر باشد. استفاده از معیارهای خودکار و بازخورد به کمک هوش مصنوعی برای ارزیابی عملکرد جزء می تواند مفید باشد:
from langchain.evaluation import EvaluatorType
from langchain.smith import RunEvalConfig evaluation_config = RunEvalConfig( evaluators=[ EvaluatorType.QA, EvaluatorType.EMBEDDING_DISTANCE, RunEvalConfig.LabeledCriteria("helpfulness"), RunEvalConfig.LabeledScoreString( { "accuracy": """
Score 1: The answer is completely unrelated to the reference.
Score 3: The answer has minor relevance but does not align with the reference.
Score 5: The answer has moderate relevance but contains inaccuracies.
Score 7: The answer aligns with the reference but has minor errors or omissions.
Score 10: The answer is completely accurate and aligns perfectly with the reference.""" }, normalize_by=10, ), ], custom_evaluators=[],
)
- عامل و ارزیابان را اجرا کنید:
از تابع run_on_dataset (یا arun_on_dataset ناهمزمان) برای ارزیابی مدل خود استفاده کنید. این اراده:
- ردیف های نمونه از مجموعه داده مشخص شده را واکشی کنید.
- عامل خود (یا هر تابع سفارشی) را روی هر مثال اجرا کنید.
- برای تولید بازخورد خودکار، ارزیابها را برای ردیابی اجرا و نمونههای مرجع مربوطه اعمال کنید.
نتایج در برنامه LangSmith قابل مشاهده خواهد بود:
chain_results = run_on_dataset( dataset_name=dataset_name, llm_or_chain_factory=functools.partial(agent_factory, prompt=prompt), evaluation=evaluation_config, verbose=True, client=client, project_name=f"runnable-agent-test-5d466cbc-{unique_id}", tags=[ "testing-notebook", "prompt:5d466cbc", ],
)
اکنون که نتایج آزمایشی خود را داریم، میتوانیم تغییراتی در عامل خود ایجاد کنیم و آنها را محک بزنیم. بیایید دوباره این کار را با یک دستور دیگر امتحان کنیم و نتایج را ببینیم:
candidate_prompt = hub.pull("wfh/langsmith-agent-prompt:39f3bbd0") chain_results = run_on_dataset( dataset_name=dataset_name, llm_or_chain_factory=functools.partial(agent_factory, prompt=candidate_prompt), evaluation=evaluation_config, verbose=True, client=client, project_name=f"runnable-agent-test-39f3bbd0-{unique_id}", tags=[ "testing-notebook", "prompt:39f3bbd0", ],
)
LangSmith به شما امکان می دهد داده ها را مستقیماً در برنامه وب به فرمت های رایج مانند CSV یا JSONL صادر کنید. همچنین می توانید از کلاینت برای واکشی اجراها برای تجزیه و تحلیل بیشتر، ذخیره در پایگاه داده خود یا اشتراک گذاری با دیگران استفاده کنید. بیایید ردپای اجرا را از اجرای ارزیابی واکشی کنیم:
runs = client.list_runs(project_name=chain_results["project_name"], execution_order=1) # After some time, these will be populated.
client.read_project(project_name=chain_results["project_name"]).feedback_stats
این یک راهنمای سریع برای شروع بود، اما راههای بسیار بیشتری برای استفاده از LangSmith برای سرعت بخشیدن به جریان توسعهدهنده و ایجاد نتایج بهتر وجود دارد.
برای اطلاعات بیشتر در مورد اینکه چگونه می توانید بیشترین بهره را از LangSmith ببرید، مستندات LangSmith را بررسی کنید.
با نانوشبکه ها ارتقاء سطح پیدا کنید
در حالی که LangChain یک ابزار ارزشمند برای ادغام مدلهای زبان (LLM) با برنامههای کاربردی شما است، ممکن است در موارد استفاده سازمانی با محدودیتهایی مواجه شود. بیایید بررسی کنیم که چگونه نانو شبکه ها فراتر از LangChain می روند تا به این چالش ها رسیدگی کنند:
1. اتصال جامع داده:
LangChain رابطهایی را ارائه میکند، اما ممکن است تمام برنامههای فضای کاری و فرمتهای دادهای که کسبوکارها به آنها متکی هستند را پوشش ندهد. Nanonets برای بیش از 100 برنامه فضای کاری پرکاربرد، از جمله Slack، Notion، Google Suite، Salesforce، Zendesk و بسیاری دیگر، اتصالات داده را فراهم می کند. همچنین از انواع داده های بدون ساختار مانند PDF، TXT، تصاویر، فایل های صوتی و فایل های ویدئویی و همچنین انواع داده های ساختاریافته مانند CSV ها، صفحات گسترده، MongoDB و پایگاه های داده SQL پشتیبانی می کند.
2. اتوماسیون وظایف برای برنامه های فضای کاری:
در حالی که تولید متن/پاسخ عالی کار می کند، قابلیت های LangChain در استفاده از زبان طبیعی برای انجام وظایف در برنامه های مختلف محدود است. Nanonets عامل های ماشه/عملی را برای محبوب ترین برنامه های فضای کاری ارائه می دهد که به شما امکان می دهد گردش های کاری را تنظیم کنید که به رویدادها گوش می دهد و اقدامات را انجام می دهد. برای مثال، میتوانید پاسخهای ایمیل، ورودیهای CRM، پرسشهای SQL و موارد دیگر را از طریق دستورات زبان طبیعی خودکار کنید.
3. همگام سازی داده ها در زمان واقعی:
LangChain داده های ثابت را با اتصال دهنده های داده واکشی می کند، که ممکن است با تغییرات داده ها در پایگاه داده منبع هماهنگ نباشد. در مقابل، نانوشبکه ها همگام سازی بلادرنگ با منابع داده را تضمین می کند و تضمین می کند که همیشه با آخرین اطلاعات کار می کنید.
3. پیکربندی ساده شده:
پیکربندی عناصر خط لوله LangChain، مانند رتریورها و سینت سایزرها، می تواند یک فرآیند پیچیده و زمان بر باشد. نانوشبکهها با ارائه بهینهسازی دادهها و فهرستبندی برای هر نوع داده، که همه در پسزمینه توسط دستیار هوش مصنوعی مدیریت میشوند، این کار را سادهتر میکنند. این امر بار تنظیم دقیق را کاهش می دهد و راه اندازی و استفاده از آن را آسان تر می کند.
4. راه حل یکپارچه:
برخلاف LangChain، که ممکن است به پیاده سازی های منحصر به فردی برای هر کار نیاز داشته باشد، Nanonets به عنوان یک راه حل یک مرحله ای برای اتصال داده های شما با LLM ها عمل می کند. چه نیاز به ایجاد برنامه های LLM داشته باشید یا جریان های کاری هوش مصنوعی، Nanonets یک پلت فرم یکپارچه برای نیازهای متنوع شما ارائه می دهد.
گردش کار هوش مصنوعی نانوشبکه
Nanonets Workflows یک دستیار هوش مصنوعی چند منظوره ایمن است که ادغام دانش و داده های شما با LLM ها را ساده می کند و ایجاد برنامه ها و گردش های کاری بدون کد را تسهیل می کند. این یک رابط کاربری آسان برای استفاده را ارائه می دهد و آن را برای افراد و سازمان ها قابل دسترسی می کند.
برای شروع، میتوانید با یکی از کارشناسان هوش مصنوعی ما تماس بگیرید، که میتواند یک نسخه آزمایشی شخصی و آزمایشی از گردشهای کاری نانوشبکه متناسب با مورد خاص شما ارائه دهد.
پس از راهاندازی، میتوانید از زبان طبیعی برای طراحی و اجرای برنامهها و گردشهای کاری پیچیده که توسط LLM ها پشتیبانی میشوند، استفاده کنید و به طور یکپارچه با برنامهها و دادههای خود یکپارچه شوند.
تیمهای خود را با هوش مصنوعی Nanonets شارژ کنید تا برنامههایی ایجاد کنید و دادههای خود را با برنامهها و جریانهای کاری مبتنی بر هوش مصنوعی ادغام کنید و به تیمهایتان اجازه دهید بر روی آنچه واقعاً مهم است تمرکز کنند.
کارها و گردشهای کار دستی را با سازنده گردش کار مبتنی بر هوش مصنوعی، که توسط Nanonets برای شما و تیمهایتان طراحی شده است، خودکار کنید.
- محتوای مبتنی بر SEO و توزیع روابط عمومی. امروز تقویت شوید.
- PlatoData.Network Vertical Generative Ai. به خودت قدرت بده دسترسی به اینجا.
- PlatoAiStream. هوش وب 3 دانش تقویت شده دسترسی به اینجا.
- PlatoESG. کربن ، CleanTech، انرژی، محیط، خورشیدی، مدیریت پسماند دسترسی به اینجا.
- PlatoHealth. هوش بیوتکنولوژی و آزمایشات بالینی. دسترسی به اینجا.
- منبع: https://nanonets.com/blog/langchain/
- : دارد
- :است
- :نه
- :جایی که
- $UP
- 1
- 10
- 100
- 114
- 13
- ٪۱۰۰
- 2000
- 2012
- 2023
- 25
- 30
- 32
- 36
- 40
- 400
- 408
- 50
- 500
- 7
- 8
- a
- الفبا
- توانایی
- قادر
- درباره ما
- در مورد IT
- بالاتر
- پذیرفتن
- قبول می کند
- دسترسی
- در دسترس
- دسترسی
- انجام دادن
- بر این اساس
- حساب
- دقت
- دقیق
- به درستی
- رسیدن
- دست
- دستیابی به
- در میان
- عمل
- عمل
- اقدامات
- فعال
- سازگار بودن
- انطباقی
- اضافه کردن
- اضافه
- اضافه کردن
- اضافه
- اضافی
- علاوه بر این
- نشانی
- می افزاید:
- اقرار کردن
- پیشرفته
- ماجرا
- پس از
- از نو
- سن
- عامل
- عاملان
- AI
- دستیار هوش مصنوعی
- مدل های هوش مصنوعی
- کمک
- هدف
- الگوریتم
- تراز
- تراز می کند
- معرفی
- اجازه دادن
- اجازه دادن
- اجازه می دهد تا
- تنها
- در امتداد
- در کنار
- قبلا
- همچنین
- هر چند
- همیشه
- an
- تحلیل
- تحلیلی
- علم تجزیه و تحلیل
- و
- آنجلس
- اعلام
- سالیانه
- دیگر
- پاسخ
- پاسخ
- سرود
- آنتروپیک
- هر
- هر چیزی
- API
- کلیدهای API
- رابط های برنامه کاربردی
- نرم افزار
- مربوط
- کاربرد
- برنامه توسعه
- برنامه های کاربردی
- اعمال می شود
- اعمال میشود
- روش
- رویکردها
- مناسب
- به درستی
- برنامه های
- معماری
- هستند
- استدلال
- استدلال
- آرمسترانگ
- دور و بر
- صف
- هنرمندان
- AS
- پرسیدن
- ظاهر
- جنبه
- همکاری
- دستیار
- مرتبط است
- At
- ضمیمه کردن
- توجه
- سمعی
- افزوده شده
- تصدیق
- خودکار بودن
- خودکار
- خودکار می کند
- بطور خودکار
- اتوماسیون
- در دسترس
- میانگین
- در انتظار
- مطلع
- AWS
- به عقب
- ستون فقرات
- بخش مدیریت
- زمینه
- بدی
- برج میزان
- بار
- پایه
- مستقر
- خط مقدم
- بر هم زدن
- اساسی
- مبانی
- BCG
- BE
- ساحل
- خرس
- زیرا
- بوده
- قبل از
- شروع
- رفتار
- پشت سر
- پشت صحنه
- بودن
- در زیر
- محک
- مفید
- بهترین
- بهتر
- میان
- خارج از
- بزرگترین
- لایحه
- بیل گیتس
- اتصال
- بینگ
- بیت
- سیاه پوست
- سیاه چاله
- مسدود کردن
- انسداد
- بلاک ها
- بلاگ
- فریب
- خود راه انداز
- متولد
- ربات
- هر دو
- پایین
- شاخه
- شکستن
- نسیم
- بطور خلاصه
- گسترده تر
- قهوهای
- مرورگر
- بافر
- ساختن
- سازنده
- بنا
- ساخته
- بار
- کسب و کار
- اما
- by
- محاسبه
- محاسبه می کند
- محاسبه
- محاسبه
- صدا
- تماس با ما
- نام
- فراخوانی
- تماس ها
- CAN
- می توانید دریافت کنید
- Canada
- قابلیت های
- توانا
- ظرفیت
- گرفتن
- ضبط
- مورد
- موارد
- CAT
- تهیه کنید
- غذا
- باعث می شود
- گربه ها
- احتیاط
- محتاط
- محور
- معین
- زنجیر
- زنجیر
- چالش ها
- تبادل
- شخصیت
- chatbot
- chatbots
- بررسی
- چک
- را انتخاب کنید
- برگزیده
- موقعیت
- شهر:
- کلاس
- کلاس ها
- مشتری
- ابر
- رمز
- برنامه نویسی
- کشت
- منسجم
- منسجم
- همکاری
- سقوط - فروپاشی - اضمحلال
- مجموعه
- رنگارنگ
- ستون
- ستون ها
- COM
- ترکیب
- ترکیب شده
- ترکیب
- ترکیب
- بیا
- می آید
- راحت
- مشترک
- ارتباط
- شرکت
- مقايسه كردن
- مقایسه
- سازگاری
- سازگار
- کامل
- به طور کامل
- اتمام
- پیچیده
- پیچیدگی ها
- جزء
- اجزاء
- مرکب
- ترکیب
- جامع
- شامل
- مفهوم
- مختصر
- رقیب
- شرط
- پیکر بندی
- تلاقی
- اتصال
- اتصال
- اتصال
- منفی
- در نظر بگیرید
- همواره
- تشکیل شده است
- کنسول
- به طور مداوم
- می سازد
- شامل
- شامل
- محتوا
- زمینه
- زمینه ها
- متنی
- ادامه دادن
- به طور مداوم
- کنتراست
- کنترل
- گروه شاهد
- مناسب
- گفتگو
- محاورهای
- هوش مصنوعی محاوره ای
- گفتگو
- تبدیل
- مبدل
- تبدیل
- هسته
- گوشه
- اصلاح
- متناظر
- میتوانست
- با احتساب
- کشور
- زن و شوهر
- پوشش
- پوشش داده شده
- ایجاد
- ایجاد شده
- ایجاد
- ایجاد
- ایجاد
- مجوزها و اعتبارات
- ضوابط
- منقد
- CRM
- بسیار سخت
- جاری
- در حال حاضر
- سفارشی
- مشتریان
- سفارشی سازی
- سفارشی
- سفارشی
- لبه برش
- داده ها
- ساختار داده ها
- پایگاه داده
- پایگاه های داده
- تاریخ
- زمان قرار
- مقدار
- معامله
- دسامبر
- تصمیم گیری
- تصمیم گیری
- تصمیم گیری
- رمز گشایی
- اختصاصی
- عمیق تر
- به طور پیش فرض
- تعريف كردن
- مشخص
- تعریف کردن
- تعاریف
- تحویل
- ارائه
- غرق کردن
- نسخه ی نمایشی
- نشان دادن
- نشان
- نشان دادن
- بستگی دارد
- بستگی دارد
- بستگی دارد
- گسترش
- مستقر
- استقرار
- گسترش
- مستقر می کند
- توصیف
- شرح
- طرح
- تعیین شده
- طراحی
- مطلوب
- جزئیات
- دقیق
- جزئیات
- مشخص کردن
- تعیین می کند
- توسعه
- توسعه دهنده
- توسعه دهندگان
- در حال توسعه
- پروژه
- نمودارها
- DICT
- DID
- متفاوت است
- مختلف
- متفاوت است
- مشکل
- بعد
- ابعاد
- دستورات
- مستقیما
- بحث و تبادل نظر
- بحث کردیم
- نمایش
- متمایز
- شیرجه رفتن
- مختلف
- DM
- do
- سند
- مستندات
- اسناد و مدارک
- میکند
- ندارد
- عمل
- دان
- انجام شده
- دو برابر
- پایین
- دانلود
- دانلود
- پیش نویس
- راندن
- دو
- در طی
- پویا
- بطور پویا
- e
- هر
- پیش از آن
- در اوایل
- سهولت
- راحتی در استفاده
- آسان تر
- به آسانی
- ساده
- آسان برای استفاده
- از دست
- اکوسیستم
- موثر
- به طور موثر
- بهره وری
- موثر
- موثر
- زحمت
- هر دو
- عنصر
- عناصر
- الون
- Elon مشک
- دیگر
- پست الکترونیک
- جاسازی کردن
- جاسازی شده
- تعبیه کردن
- به کار گرفته شده
- کارکنان
- کار می کند
- قدرت دادن
- قادر ساختن
- را قادر می سازد
- را قادر می سازد
- کپسوله می کند
- روبرو شدن
- پشت سر هم
- نقطه پایانی
- جذاب
- موتور
- موتورهای حرفه ای
- انگلستان
- انگلیسی
- انگلیسی لیگ برتر
- بالا بردن
- افزایش
- افزایش
- اطمینان حاصل شود
- تضمین می کند
- حصول اطمینان از
- سرمایه گذاری
- اشخاص
- موجودیت
- محیط
- محیط
- معادل
- عصر
- خطا
- خطاهای
- به خصوص
- ضروری است
- خفه شده
- و غیره
- ارزیابی
- ارزیابی
- حتی
- حوادث
- هر
- مثال
- مثال ها
- تجاوز
- جز
- اجرا کردن
- اجرا شده
- اجرا می کند
- اجرا کردن
- اعدام
- نمونه
- ورزش
- وجود داشته باشد
- انتظار
- انتظارات
- انتظار می رود
- انتظار می رود
- تجربه
- تجربی
- کارشناسان
- توضیح داده شده
- توضیح می دهد
- به صراحت
- اکتشاف
- اکتشاف
- کشف
- صادرات
- بیان
- گسترش
- گسترش
- وسیع
- خارجی
- اضافی
- عصاره
- استخراج
- عصاره ها
- چهره
- تسهیل کردن
- تسهیل می کند
- کارخانه
- حقایق
- بسیار
- FAST
- محبوب
- ویژگی
- امکانات
- باز خورد
- کمی از
- رشته
- زمینه
- فیگما
- شکل
- پرونده
- فایل ها
- پر کردن
- پر شده
- پر كردن
- فیلتر
- فیلتر
- نهایی
- سرانجام
- پیدا کردن
- پیدا کردن
- نام خانوادگی
- پنج
- انعطاف پذیری
- قابل انعطاف
- جریان
- تمرکز
- متمرکز شده است
- تمرکز
- تمرکز
- به دنبال
- پیروی
- به دنبال آن است
- غذا
- برای
- فرم
- قالب
- تشکیل
- خوشبختانه
- یافت
- چارچوب
- چارچوب
- غالبا
- دوست
- دوستان
- از جانب
- کامل
- تمام عیار
- تابع
- ویژگی های
- قابلیت
- توابع
- اساسی
- خنده دار
- بیشتر
- آینده
- افزایش
- بازیها
- گیتس
- سوالات عمومی
- عموما
- تولید می کنند
- تولید
- تولید می کند
- مولد
- نسل
- ژانر
- آلمان
- دریافت کنید
- گرفتن
- GIF
- GitHub
- داده
- GMT
- Go
- می رود
- رفتن
- خوب
- گوگل
- دانه ای
- گراف
- بزرگ
- بیشتر
- راهنمایی
- راهنمایی
- دستورالعمل ها
- هکاتون
- دسته
- دستگیره
- اداره
- سیار
- سخت
- صدمه
- تسمه
- آیا
- داشتن
- به شدت
- برگزار شد
- کمک
- مفید
- کمک می کند
- او
- اینجا کلیک نمایید
- hi
- زیاد
- در سطح بالا
- با کیفیت بالا
- بالاترین
- خیلی
- تاریخی
- تاریخ
- سوراخ
- کاپوت
- میزبان
- چگونه
- چگونه
- اما
- HTML
- HTTP
- HTTPS
- قطب
- انسان
- صدها نفر
- i
- ID
- اندیشه
- دلخواه
- شناسه
- if
- ii
- III
- نشان دادن
- نشان می دهد
- تصاویر
- فوری
- انجام
- پیاده سازی
- پیاده سازی ها
- اجرا
- واردات
- ارتقاء
- بهبود
- in
- در عمق
- شامل
- مشمول
- شامل
- از جمله
- ترکیب کردن
- گنجاندن
- بطور باور نکردنی
- شاخص
- فهرستها
- نشان دادن
- نشان می دهد
- به طور جداگانه
- افراد
- اطلاعات
- اول
- وارد کردن
- ابتکاری
- ورودی
- ورودی
- بینش
- نصب
- نصب شده
- نصب کردن
- نمونه
- فوری
- در عوض
- دستورالعمل
- انتگرال
- ادغام
- یکپارچه
- ادغام
- ادغام
- ادغام
- یکپارچگی
- هوشمند
- مورد نظر
- تعامل
- اثر متقابل
- فعل و انفعالات
- تعاملی
- در ارتباط بودن
- رابط
- رابط
- داخلی
- اینترنت
- به
- معرفی
- معرفی می کند
- حسی
- شامل
- نیست
- موضوع
- مسائل
- IT
- اقلام
- تکرار
- ITS
- خود
- جکسون
- جاوا اسکریپت
- کار
- اردن
- سفر
- json
- جولای
- تنها
- عدالت
- نگاه داشتن
- نگه می دارد
- کلید
- کلید
- نوع
- دانستن
- دانش
- نمودار دانش
- شناخته شده
- برچسب
- برچسب ها
- زمین
- زبان
- زبان ها
- بزرگ
- بزرگتر
- نام
- تاخیر
- بعد
- آخرین
- اتحادیه
- یاد گرفتن
- یادگیری
- ترک کرد
- میراث
- طول
- کمتر
- اجازه
- اجازه می دهد تا
- نامه
- سطح
- سطح
- قدرت نفوذ
- اهرم ها
- بهره برداری
- کتابخانه ها
- کتابخانه
- پسندیدن
- احتمالا
- محدود
- محدودیت
- محدود شده
- محدود کردن
- محدودیت
- لینک ها
- فهرست
- گوش دادن
- لیست
- زنده
- ll
- LLM
- بار
- بارکننده
- واقع شده
- محل
- ورود به سیستم
- سیستم وارد
- ورود به سیستم
- منطق
- طولانی
- دیگر
- نگاه کنيد
- به دنبال
- مطالب
- مراجعه
- آنها
- لس آنجلس
- کم
- دستگاه
- فراگیری ماشین
- ساخته
- حفظ
- قابل نگهداری
- حفظ
- حفظ
- ساخت
- باعث می شود
- ساخت
- مدیریت
- مدیریت
- مدیر
- مدیریت
- منچستر
- منچستر یونایتد
- دست کاری
- روش
- کتابچه راهنمای
- سازنده
- بسیاری
- بسیاری از مردم
- نقشه
- نقشه برداری
- نقشه ها
- مسابقه
- مطابق
- ریاضی
- ریاضی
- مسائل
- بیشترین
- ممکن است..
- me
- متوسط
- معنی
- به معنی
- اندازه
- رسانه ها
- نشست
- ملاقات
- خاطرات
- حافظه
- ذکر شده
- ادغام کردن
- ادغام
- پیام
- پیام
- پیام
- متاداده
- روش
- روش
- متریک
- قدرت
- میلیون ها نفر
- حداقل
- خردسال
- گم
- اشتباهات
- خلط
- MLB
- موبایل
- مدل
- مدل
- اعتدال
- ماژول ها
- ماژول ها
- لحظه
- MongoDB
- مانیتور
- نظارت بر
- ماه
- بیش
- اکثر
- محبوبترین
- حرکت
- سینما
- بسیار
- چندگانه
- زنجیره های متعدد
- مشک
- باید
- my
- نام
- تحت عنوان
- نام
- ملی
- طبیعی
- پردازش زبان طبیعی
- هدایت
- پیمایش
- نزدیک
- لازم
- نیاز
- ضروری
- نیازهای
- منفی
- جدید
- نیویورک
- نیویورک تایمز
- بعد
- نه
- هیچ
- هیچ چی
- ایده
- اکنون
- عدد
- اوباما
- هدف
- هدف
- اشیاء
- مشاهده
- گرفتن
- بدست آوردن
- OCR
- of
- ارائه
- ارائه
- پیشنهادات
- غالبا
- oh
- خوب
- بازی های المپیک
- on
- یک بار
- ONE
- فقط
- منبع باز
- OpenAI
- عملیات
- اپراتور
- بهینه
- بهینه سازی می کند
- گزینه
- or
- سفارش
- سازمانی
- سازمان های
- اصلی
- OS
- دیگر
- دیگران
- در غیر این صورت
- ما
- خارج
- تولید
- خروجی
- روی
- باطل کردن
- مروری
- خود
- بسته
- بسته
- با ما
- صفحات
- جفت
- پانداها
- مقاله
- موازی
- پارامتر
- پارامترهای
- پارک
- بخش
- ویژه
- بخش
- عبور
- گذشت
- عبور می کند
- عبور
- گذشته
- مسیر
- راه ها
- الگوهای
- حقوق و دستمزد
- مردم
- برای
- کامل
- کاملا
- انجام
- کارایی
- انجام
- انجام می دهد
- مجوز
- اصرار
- شخص
- شخصی
- چشم انداز
- فیزیک
- قطعه
- خط لوله
- پیتزا
- حفره یا سوراخ
- سکو
- افلاطون
- هوش داده افلاطون
- PlatoData
- بازی
- زمین بازی
- نقش
- لطفا
- به علاوه
- نقطه
- سیاست
- سیاست
- سیاسی
- استخر
- محبوب
- پر جمعیت
- مثبت
- ممکن
- پست
- پست ها
- پتانسیل
- قدرت
- صفحه اصلی
- قوی
- عملی
- تمرین
- ترجیح می دهند
- نخست وزیر
- در حال حاضر
- رئيس جمهور
- جلوگیری از
- جلوگیری
- قبلی
- در درجه اول
- اصلی
- نخستین
- خصوصی
- مشکل
- مشکلات
- ادامه
- روند
- فرآوری شده
- فرآیندهای
- در حال پردازش
- تولید کردن
- محصول
- تولید
- معلم
- برنامه نويسي
- زبانهای برنامه نویسی
- پروژه
- پروژه ها
- املاک
- ویژگی
- مثبت
- نمونه اولیه
- نمونه سازی
- ارائه
- ارائه
- ارائه دهنده
- ارائه دهندگان
- فراهم می کند
- ارائه
- عمومی
- هدف
- اهداف
- قرار دادن
- پــایتــون
- پرسش و پاسخ
- کیفیت
- نمایش ها
- سوال
- سوالات
- سریع
- به سرعت
- نقل قول
- R
- بالا بردن
- محدوده
- اعم
- نسبتا
- رتبه
- خام
- RE
- رسیدن به
- واکنش نشان می دهند
- خواندن
- مطالعه
- اماده
- واقعی
- زمان واقعی
- داده های زمان واقعی
- قلمرو
- دلیل
- دلایل
- اخیر
- توصیه می شود
- ثبت
- سوابق
- بهبود یافتن
- كاهش دادن
- را کاهش می دهد
- کاهش
- کاهش
- مرجع
- ارجاع
- خالص کردن
- پالایش
- مناطق
- روابط
- منتشر شد
- ربط
- مربوط
- قابلیت اطمینان
- قابل اعتماد
- تکیه
- تکیه بر
- بقایای
- به یاد داشته باشید
- یادآور
- دور
- محصول
- تکرار
- به طور مکرر
- بازنویسی
- جایگزین کردن
- گزارش
- مخزن
- نمایندگی
- نمایندگی
- نشان دهنده
- درخواست
- درخواست
- نیاز
- ضروری
- مورد نیاز
- نیاز
- نجات
- تحقیق
- تصمیم
- منابع
- پاسخ
- پاسخ دادن
- پاسخ
- پاسخ
- مسئوليت
- پاسخگو
- REST
- نتیجه
- نتیجه
- نتایج
- حفظ
- نگهداری
- برگشت
- عودت
- بازده
- قابل استفاده مجدد
- این فایل نقد می نویسید:
- می چرخد
- برنج
- غنی
- ربات ها
- نقش
- نقش
- ریشه
- مسیریابی
- ROW
- دویدن
- در حال اجرا
- اجرا می شود
- زمان اجرا
- s
- پادمان
- حراجی
- salesforce
- سام
- همان
- ذخیره
- گفتن
- می گوید:
- مقیاس پذیر
- مقیاس
- سناریو
- سناریوها
- صحنه های
- برنامه
- نمره
- خراش
- بدون درز
- یکپارچه
- جستجو
- موتور جستجو
- جستجو
- جستجو
- بخش
- بخش
- امن
- تیم امنیت لاتاری
- دیدن
- انتخاب شد
- انتخاب
- فروش
- ارسال
- حساس
- احساس
- احساسات
- جداگانه
- سپتامبر
- دنباله
- سلسله
- خدمت
- سرور
- خدمت
- خدمات
- تنظیم
- مجموعه
- محیط
- تنظیمات
- برپایی
- هفت
- چند
- اشتراک گذاری
- به اشتراک گذاشته شده
- صدف
- درخشان است
- حمل
- باید
- نشان
- نمایشگاه
- نشان داده شده
- نشان می دهد
- سیگما
- قابل توجه
- مشابه
- ساده
- ساده شده
- ساده کردن
- ساده
- به سادگی
- پس از
- تنها
- اندازه
- شل
- کوچک
- کوچکتر
- هوشمند
- قطعه
- So
- تا حالا
- فوتبال
- آگاهی
- رسانه های اجتماعی
- پیام های رسانه های اجتماعی
- فقط
- جامد
- راه حل
- حل
- برخی از
- چیزی
- گاهی
- مصنوعی
- برای تلفن های موبایل
- منبع
- منابع
- فضا
- اسپانیایی
- تخصصی
- خاص
- به طور خاص
- جزئیات
- مشخص شده
- سرعت
- صرف
- انشعاب
- تقسیم می کند
- ورزش ها
- مربع
- ایستادن
- مستقل
- استاندارد
- شروع
- آغاز شده
- راه افتادن
- دولت
- اظهارات
- ایستا
- گام
- مراحل
- هنوز
- توقف
- متوقف کردن
- توقف
- ذخیره سازی
- opbevare
- ذخیره شده
- پرده
- ذخیره سازی
- داستان
- ساده
- جریان
- جریان
- ساده کردن
- ساده
- نقاط قوت
- اعتصاب
- رشته
- ساختار
- ساخت یافته
- ساختار
- ساختار
- سبک
- موضوع
- متعاقب
- موفقیت
- چنین
- کت و شلوار
- مناسب
- دنباله
- خلاصه کردن
- خلاصه
- غروب
- پشتیبانی
- پشتیبانی
- پشتیبانی از
- مطمئن
- پایداری
- هماهنگ سازی
- خلاصه
- نحو
- سیستم
- سیستم های
- جدول
- خیاط
- طراحی شده
- گرفتن
- طول می کشد
- اهداف
- کار
- وظایف
- تیم
- تیم ها
- گفتن
- قالب
- قالب
- پایانه
- واژه شناسی
- قوانین و مقررات
- آزمون
- تست
- متن
- نسبت به
- با تشکر
- که
- La
- مبانی
- هاب
- اطلاعات
- نیویورک تایمز
- پروژه ها
- منبع
- جهان
- شان
- آنها
- سپس
- آنجا.
- اینها
- آنها
- اشیاء
- این
- کسانی که
- اگر چه؟
- از طریق
- سراسر
- زمان
- زمان بر
- بار
- عنوان
- به
- با هم
- رمز
- از Tokenization
- نشانه
- هم
- ابزار
- ابزار
- ابزار
- بالا
- موضوع
- تاپیک
- جمع
- شهر
- ردیابی
- مسیر
- سنتی
- آموزش
- دگرگون کردن
- تحولات
- ترانسفورماتور
- ترانسفورماتور
- انتقال
- محاکمه
- درست
- صادقانه
- امتحان
- میزان سازی
- دور زدن
- عطف
- آموزش
- دو برابر
- دو
- نوع
- انواع
- حروفچینی
- به طور معمول
- ui
- در نهایت
- بی تأثیر
- زیر
- اساسی
- فهمیدن
- درک
- درک می کند
- یکپارچه
- منحصر به فرد
- متحد
- جهانی
- بر خلاف
- تا
- بروزرسانی
- به روز رسانی
- آپلود شده
- URL
- us
- قابلیت استفاده
- استفاده
- استفاده کنید
- مورد استفاده
- استفاده
- کاربر
- رابط کاربری
- کاربران
- استفاده
- با استفاده از
- آب و برق
- استفاده کنید
- استفاده
- استفاده می کند
- با استفاده از
- v1
- اعتبار سنجی
- تأیید اعتبار
- ارزشمند
- ارزش
- ارزشها
- متغیر
- تنوع
- مختلف
- Ve
- همه کاره
- نسخه
- بسیار
- از طريق
- تصویری
- چشم انداز
- نقض
- قابل رویت
- تجسم
- حیاتی
- vs
- راه رفتن
- خرید
- می خواهم
- بود
- تماشا کردن
- مسیر..
- راه
- we
- هوا
- وب
- مرورگر وب
- خدمات وب
- وب سایت
- خوب
- معروف
- بود
- چی
- چه شده است
- چه
- چه زمانی
- چه
- که
- در حین
- WHO
- تمام
- چرا
- وسیع
- به طور گسترده ای
- ویدجت
- ویکیپدیا
- اراده
- پنجره
- برنده
- با
- در داخل
- بدون
- کلمه
- مهاجرت کاری
- مشغول به کار
- گردش کار
- گردش کار
- کارگر
- با این نسخهها کار
- جهان
- خواهد بود
- نوشتن
- نوشته
- X
- هنوز
- نیویورک
- شما
- شما
- خودت
- یوتیوب
- Zendesk
- زفیرنت
- زیپ