في الصميم، لانجشين هو إطار عمل مبتكر مصمم لصياغة التطبيقات التي تستفيد من قدرات النماذج اللغوية. إنها مجموعة أدوات مصممة للمطورين لإنشاء تطبيقات تدرك السياق وتكون قادرة على التفكير المتطور.
وهذا يعني أن تطبيقات LangChain يمكنها فهم السياق، مثل التعليمات السريعة أو الاستجابات الأساسية للمحتوى واستخدام نماذج اللغة لمهام التفكير المعقدة، مثل تحديد كيفية الاستجابة أو الإجراءات التي يجب اتخاذها. تمثل LangChain نهجًا موحدًا لتطوير التطبيقات الذكية، وتبسيط الرحلة من المفهوم إلى التنفيذ بمكوناتها المتنوعة.
فهم لانجشين
يعد LangChain أكثر من مجرد إطار عمل؛ إنه نظام بيئي متكامل يتكون من عدة أجزاء متكاملة.
- أولاً، هناك مكتبات LangChain، المتوفرة في كل من Python وJavaScript. تمثل هذه المكتبات العمود الفقري لـ LangChain، حيث تقدم واجهات وعمليات تكامل لمختلف المكونات. وهي توفر وقت تشغيل أساسيًا لدمج هذه المكونات في سلاسل ووكلاء متماسكين، إلى جانب تطبيقات جاهزة للاستخدام الفوري.
- بعد ذلك، لدينا قوالب LangChain. هذه عبارة عن مجموعة من البنى المرجعية القابلة للنشر والمصممة خصيصًا لمجموعة واسعة من المهام. سواء كنت تقوم بإنشاء برنامج دردشة آلي أو أداة تحليلية معقدة، فإن هذه القوالب توفر نقطة بداية قوية.
- تدخل LangServe كمكتبة متعددة الاستخدامات لنشر سلاسل LangChain كواجهات برمجة تطبيقات 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. يتم تثبيته جنبًا إلى جنب مع LangChain CLI.
غالبًا ما يتطلب LangChain عمليات تكامل مع موفري النماذج ومخازن البيانات وواجهات برمجة التطبيقات وما إلى ذلك. في هذا المثال، سنستخدم واجهات برمجة التطبيقات النموذجية الخاصة بـ 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 بإنشاء تطبيقات نماذج اللغة من خلال الوحدات النمطية. يمكن لهذه الوحدات أن تكون مستقلة أو مكونة لحالات استخدام معقدة. هذه الوحدات هي -
- نموذج I / O: يسهل التفاعل مع نماذج اللغة المختلفة والتعامل مع مدخلاتها ومخرجاتها بكفاءة.
- استرجاع: يتيح الوصول إلى البيانات الخاصة بالتطبيق والتفاعل معها، وهو أمر بالغ الأهمية لاستخدام البيانات الديناميكية.
- وسيط عقاري: تمكين التطبيقات من اختيار الأدوات المناسبة بناءً على توجيهات عالية المستوى، مما يعزز قدرات اتخاذ القرار.
- السلاسل: يقدم تركيبات محددة مسبقًا وقابلة لإعادة الاستخدام والتي تعمل كعناصر أساسية لتطوير التطبيقات.
- مكبر الصوت : يدعم، مع دعم ميكروفون مدمج لمنع الضوضاء : يحافظ على حالة التطبيق عبر عمليات تنفيذ متسلسلة متعددة، وهو أمر ضروري للتفاعلات المدركة للسياق.
تستهدف كل وحدة احتياجات تطوير محددة، مما يجعل LangChain مجموعة أدوات شاملة لإنشاء تطبيقات نماذج اللغة المتقدمة.
جنبا إلى جنب مع المكونات المذكورة أعلاه، لدينا أيضا لغة التعبير LangChain (LCEL)، وهي طريقة تعريفية لتكوين الوحدات معًا بسهولة، وهذا يمكّن من تسلسل المكونات باستخدام واجهة عالمية قابلة للتشغيل.
يبدو 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 لتصحيح الأخطاء والاختبار والمراقبة.
هيا بنا نبدأ!
الوحدة الأولى: نموذج الإدخال/الإخراج
في LangChain، يتمحور العنصر الأساسي لأي تطبيق حول نموذج اللغة. توفر هذه الوحدة اللبنات الأساسية للتفاعل بفعالية مع أي نموذج لغة، مما يضمن التكامل والتواصل السلس.
المكونات الرئيسية لنموذج الإدخال/الإخراج
- LLMs ونماذج الدردشة (تُستخدم بالتبادل):
- ماجستير في القانون:
- تعريف: نماذج إكمال النص الخالص.
- الإدخال / الإخراج: خذ سلسلة نصية كمدخل وأرجع سلسلة نصية كمخرجات.
- نماذج الدردشة
- ماجستير في القانون:
- تعريف: النماذج التي تستخدم نموذج اللغة كقاعدة ولكنها تختلف في تنسيقات الإدخال والإخراج.
- الإدخال / الإخراج: قبول قائمة رسائل الدردشة كمدخلات وإرجاع رسالة دردشة.
- يطالبك: تصميم مدخلات النموذج وتحديدها ديناميكيًا وإدارتها. يسمح بإنشاء مطالبات مرنة ومحددة السياق لتوجيه استجابات نموذج اللغة.
- موزعي الإخراج: استخراج المعلومات وتنسيقها من مخرجات النموذج. مفيد لتحويل المخرجات الأولية لنماذج اللغة إلى بيانات منظمة أو تنسيقات محددة يحتاجها التطبيق.
ماجستير
يعد تكامل LangChain مع نماذج اللغات الكبيرة (LLMs) مثل OpenAI وCohere وHugging Face جانبًا أساسيًا من وظائفها. لا تستضيف LangChain نفسها LLMs ولكنها تقدم واجهة موحدة للتفاعل مع LLMs المختلفة.
يقدم هذا القسم نظرة عامة على استخدام غلاف OpenAI LLM في LangChain، والذي ينطبق على أنواع LLM الأخرى أيضًا. لقد قمنا بالفعل بتثبيت هذا في قسم "البدء". دعونا تهيئة LLM.
from langchain.llms import OpenAI
llm = OpenAI()
- LLMs تنفذ واجهة قابلة للتشغيل، اللبنة الأساسية لل لغة التعبير LangChain (LCEL). وهذا يعني أنهم يدعمون
invoke
,ainvoke
,stream
,astream
,batch
,abatch
,astream_log
المكالمات. - تقبل LLMs سلاسل كمدخلات، أو كائنات يمكن إجبارها على سلسلة من المطالبات، بما في ذلك
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)
بالنسبة لنماذج الدردشة، تكون المطالبات أكثر تنظيمًا، وتتضمن رسائل ذات أدوار محددة. عروض لانجشين 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 Expression Language (LCEL)، مما يمكنهم من أن يكونوا جزءًا من سير عمل أكبر وأكثر تعقيدًا. سنناقش المزيد حول هذا لاحقًا.
تعد قوالب المطالبة المخصصة ضرورية في بعض الأحيان للمهام التي تتطلب تنسيقًا فريدًا أو تعليمات محددة. يتضمن إنشاء قالب موجه مخصص تحديد متغيرات الإدخال وطريقة التنسيق المخصصة. تسمح هذه المرونة لشركة LangChain بتلبية مجموعة واسعة من المتطلبات الخاصة بالتطبيقات. اقرأ المزيد هنا.
يدعم LangChain أيضًا المطالبة بعدد قليل من اللقطات، مما يمكّن النموذج من التعلم من الأمثلة. تعتبر هذه الميزة حيوية للمهام التي تتطلب فهمًا سياقيًا أو أنماطًا محددة. يمكن إنشاء قوالب سريعة قليلة من مجموعة من الأمثلة أو من خلال استخدام كائن محدد الأمثلة. اقرأ المزيد هنا.
موزعي الإخراج
يلعب موزعو المخرجات دورًا حاسمًا في Langchain، مما يمكّن المستخدمين من هيكلة الاستجابات الناتجة عن نماذج اللغة. في هذا القسم، سوف نستكشف مفهوم موزعي المخرجات ونقدم أمثلة التعليمات البرمجية باستخدام PydanticOutputParser من Langchain، وSimpleJsonOutputParser، وCommaSeparatedListOutputParser، وDatetimeOutputParser، وXMLOutputParser.
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 دورًا حاسمًا في التطبيقات التي تتطلب بيانات خاصة بالمستخدم، وغير مدرجة في مجموعة تدريب النموذج. تتضمن هذه العملية، المعروفة باسم الجيل المعزز للاسترجاع (RAG)، جلب البيانات الخارجية ودمجها في عملية إنشاء نموذج اللغة. توفر LangChain مجموعة شاملة من الأدوات والوظائف لتسهيل هذه العملية، وتلبية كل من التطبيقات البسيطة والمعقدة.
يحقق LangChain عملية الاسترجاع من خلال سلسلة من المكونات التي سنناقشها واحدًا تلو الآخر.
محمل الوثائق
تتيح أدوات تحميل المستندات في LangChain استخراج البيانات من مصادر مختلفة. مع توفر أكثر من 100 أداة تحميل، فإنها تدعم مجموعة من أنواع المستندات والتطبيقات والمصادر (مجموعات s3 الخاصة ومواقع الويب العامة وقواعد البيانات).
يمكنك اختيار أداة تحميل المستندات بناءً على متطلباتك هنا.
كل هذه اللوادر تستوعب البيانات وثيقة الطبقات. سنتعلم كيفية استخدام البيانات التي تم استيعابها في فئات المستندات لاحقًا.
محمل الملف النصي: تحميل بسيط .txt
الملف في مستند.
from langchain.document_loaders import TextLoader loader = TextLoader("./sample.txt")
document = loader.load()
محمل CSV: قم بتحميل ملف 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 في 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()
يستخدم AmazonTextractPDFarser 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.
القائمة الكاملة هي هنا.
فيما يلي بعض الأمثلة لتوضيح ذلك -
المثال الأول - الركود
يمكن دمج Slack، وهو نظام أساسي للمراسلة الفورية واسع الاستخدام، في سير عمل وتطبيقات LLM.
- انتقل إلى صفحة إدارة مساحة عمل Slack الخاصة بك.
- انتقل إلى
{your_slack_domain}.slack.com/services/export
. - حدد النطاق الزمني المطلوب وابدأ عملية التصدير.
- يقوم Slack بإعلامك عبر البريد الإلكتروني والرسالة المباشرة بمجرد أن يصبح التصدير جاهزًا.
- نتائج التصدير في
.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)
المثال الثاني - الشكل
تقدم Figma، وهي أداة شائعة لتصميم الواجهة، واجهة REST API لتكامل البيانات.
- احصل على مفتاح ملف Figma من تنسيق URL:
https://www.figma.com/file/{filekey}/sampleFilename
. - تم العثور على معرفات العقدة في معلمة URL
?node-id={node_id}
. - قم بإنشاء رمز وصول باتباع التعليمات الموجودة على مركز مساعدة فيجما.
- •
FigmaFileLoader
فئة منlangchain.document_loaders.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()
- •
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)
- •
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 تحتوي على معلومات حول نماذج التعرف الضوئي على الحروف واستخلاص البيانات المختلفة –
دعونا نستخدم 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 Code Splitter وJavaScript Code Splitter:
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
في لانجشين، ال 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 في قسم عمليات التكامل موردًا قيمًا.
متاجر المتجهات
تدعم متاجر المتجهات في LangChain التخزين الفعال والبحث في تضمينات النص. يتكامل LangChain مع أكثر من 50 متجرًا متجهًا، مما يوفر واجهة موحدة لسهولة الاستخدام.
مثال: تخزين التضمينات والبحث فيها
بعد تضمين النصوص، يمكننا تخزينها في متجر المتجهات مثل Chroma
وإجراء عمليات بحث التشابه:
from langchain.vectorstores import Chroma db = Chroma.from_texts(embedded_texts)
similar_texts = db.similarity_search("search query")
دعونا بدلاً من ذلك نستخدم متجر FAISS Vector لإنشاء فهارس لمستنداتنا.
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS pdfstore = FAISS.from_documents(pdfpages, embedding=OpenAIEmbeddings()) airtablestore = FAISS.from_documents(airtabledocs, embedding=OpenAIEmbeddings())
المستردون
المستردون في LangChain عبارة عن واجهات تقوم بإرجاع المستندات استجابةً لاستعلام غير منظم. وهي أكثر عمومية من مخازن المتجهات، حيث تركز على الاسترجاع بدلاً من التخزين. على الرغم من أنه يمكن استخدام مخازن المتجهات كعمود فقري للمسترد، إلا أن هناك أنواعًا أخرى من المستردات أيضًا.
لإعداد جهاز استرداد Chroma، عليك أولاً تثبيته باستخدام pip install chromadb
. بعد ذلك، يمكنك تحميل المستندات وتقسيمها وتضمينها واستردادها باستخدام سلسلة من أوامر Python. فيما يلي مثال على التعليمات البرمجية لإعداد جهاز استرداد 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 على ضغط المستندات المستردة باستخدام سياق الاستعلام، مما يضمن إرجاع المعلومات ذات الصلة فقط. يتضمن ذلك تقليل المحتوى وتصفية المستندات الأقل صلة. يوضح مثال التعليمات البرمجية التالي كيفية استخدام مسترد الضغط السياقي:
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)))
يعد برنامج استرداد المستندات الأصلية بمثابة برنامج استرداد آخر يحقق التوازن بين دقة التضمين والاحتفاظ بالسياق عن طريق تخزين أجزاء صغيرة واسترداد المستندات الأصلية الأكبر حجمًا. وتنفيذه هو كما يلي:
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")
يقوم المسترد ذو الاستعلام الذاتي بإنشاء استعلامات منظمة من مدخلات اللغة الطبيعية ويطبقها على 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")
بالنسبة لأمثلتنا، يمكننا أيضًا استخدام المسترد القياسي الذي تم تنفيذه بالفعل كجزء من كائن مخزن المتجهات الخاص بنا على النحو التالي -
يمكننا الآن الاستعلام عن المستردون. ستكون نتائج استعلامنا عبارة عن كائنات مستندية ذات صلة بالاستعلام. سيتم استخدامها في النهاية لإنشاء ردود ذات صلة في أقسام أخرى.
يمكنك أتمتة المهام اليدوية ومسارات العمل باستخدام أداة إنشاء سير العمل المستندة إلى الذكاء الاصطناعي، والتي صممتها Nanonets لك ولفرقك.
الوحدة الثالثة : الوكلاء
تقدم LangChain مفهومًا قويًا يسمى "الوكلاء" يأخذ فكرة السلاسل إلى مستوى جديد تمامًا. يستفيد الوكلاء من نماذج اللغة لتحديد تسلسل الإجراءات المطلوب تنفيذها ديناميكيًا، مما يجعلها متعددة الاستخدامات وقابلة للتكيف بشكل لا يصدق. على عكس السلاسل التقليدية، حيث يتم ترميز الإجراءات ضمن التعليمات البرمجية، يستخدم الوكلاء نماذج اللغة كمحركات منطقية لتحديد الإجراءات التي يجب اتخاذها وبأي ترتيب.
العميل هو العنصر الأساسي المسؤول عن اتخاذ القرار. إنه يسخر قوة نموذج اللغة والمطالبة بتحديد الخطوات التالية لتحقيق هدف محدد. تتضمن المدخلات إلى الوكيل عادةً ما يلي:
- الأدوات: أوصاف الأدوات المتاحة (المزيد حول هذا لاحقًا).
- إدخال المستخدم: الهدف أو الاستعلام عالي المستوى من المستخدم.
- الخطوات الوسيطة: تاريخ أزواج (الإجراء، مخرجات الأداة) التي تم تنفيذها للوصول إلى إدخال المستخدم الحالي.
يمكن أن يكون إخراج الوكيل هو التالي عمل لاتخاذ الإجراءات (إجراءات الوكيل) أو النهائي استجابة لإرسالها إلى المستخدم (AgentFinish). ل عمل يحدد أ أداة و إدخال لتلك الأداة.
الأدوات
الأدوات هي واجهات يمكن للوكيل استخدامها للتفاعل مع العالم. فهي تمكن الوكلاء من أداء مهام مختلفة، مثل البحث في الويب، أو تشغيل أوامر shell، أو الوصول إلى واجهات برمجة التطبيقات الخارجية. في 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>"
بمجرد تعيين بيانات الاعتماد الخاصة بك، يمكنك إنشاء ملف DataForSeoAPIWrapper
أداة للوصول إلى API:
from langchain.utilities.dataforseo_api_search import DataForSeoAPIWrapper wrapper = DataForSeoAPIWrapper() result = wrapper.run("Weather in Los Angeles")
• 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 عن طريق تحديد أنواع النتائج والحقول والحد من عدد النتائج.
يمكنك أيضًا تحديد الموقع واللغة لنتائج البحث الخاصة بك عن طريق تمرير معلمات إضافية إلى مجمّع واجهة برمجة التطبيقات:
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 للوكلاء إمكانية الوصول إلى بيئة shell، مما يسمح لهم بتنفيذ أوامر shell. هذه الميزة قوية ولكن يجب استخدامها بحذر، خاصة في البيئات المعزولة. إليك كيفية استخدام أداة Shell:
from langchain.tools import ShellTool shell_tool = ShellTool() result = shell_tool.run({"commands": ["echo 'Hello World!'", "time"]})
في هذا المثال، تقوم أداة Shell بتشغيل أمرين من أوامر 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، إلا أن هناك أوقات تشغيل تجريبية أخرى مدعومة، بما في ذلك:
- وكيل التخطيط والتنفيذ
- طفل AGI
- GPT تلقائي
للحصول على فهم أفضل لإطار عمل الوكيل، دعونا نبني وكيلًا أساسيًا من الصفر، ثم ننتقل لاستكشاف الوكلاء المبنيين مسبقًا.
قبل أن نتعمق في بناء الوكيل، من الضروري إعادة النظر في بعض المصطلحات والمخططات الرئيسية:
- عمل الوكيل: هذه فئة بيانات تمثل الإجراء الذي يجب على الوكيل اتخاذه. يتكون من أ
tool
الخاصية (اسم الأداة التي سيتم استدعاءها) و أtool_input
الخاصية (المدخل لتلك الأداة). - إنهاء الوكيل: تشير فئة البيانات هذه إلى أن الوكيل قد أنهى مهمته ويجب عليه إرجاع استجابة للمستخدم. ويتضمن عادةً قاموسًا لقيم الإرجاع، غالبًا مع "مخرج" رئيسي يحتوي على نص الاستجابة.
- الخطوات الوسيطة: هذه هي سجلات إجراءات الوكيل السابقة والمخرجات المقابلة. إنها ضرورية لتمرير السياق إلى التكرارات المستقبلية للوكيل.
في مثالنا، سوف نستخدم استدعاء دالة OpenAI لإنشاء وكيلنا. هذا النهج يمكن الاعتماد عليه لإنشاء الوكيل. سنبدأ بإنشاء أداة بسيطة تحسب طول الكلمة. هذه الأداة مفيدة لأن النماذج اللغوية يمكن أن ترتكب أحيانًا أخطاء بسبب الترميز عند حساب أطوال الكلمات.
أولاً، لنقم بتحميل نموذج اللغة الذي سنستخدمه للتحكم في الوكيل:
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 أنواعًا مختلفة من الوكلاء، كل منها مناسب لحالات استخدام محددة. فيما يلي بعض الوكلاء المتاحين:
- رد الفعل الصفري: يستخدم هذا الوكيل إطار عمل ReAct لاختيار الأدوات بناءً على أوصافها فقط. يتطلب وصفًا لكل أداة وهو متعدد الاستخدامات للغاية.
- رد فعل المدخلات المنظمة: يتعامل هذا الوكيل مع أدوات الإدخال المتعددة وهو مناسب للمهام المعقدة مثل التنقل في متصفح الويب. يستخدم مخطط وسيطة الأدوات للإدخال المنظم.
- وظائف OpenAI: تم تصميم هذا العامل خصيصًا للنماذج التي تم ضبطها بدقة لاستدعاء الوظائف، وهو متوافق مع نماذج مثل gpt-3.5-turbo-0613 وgpt-4-0613. لقد استخدمنا هذا لإنشاء وكيلنا الأول أعلاه.
- تحادثي: يستخدم هذا الوكيل، المصمم لإعدادات المحادثة، ReAct لاختيار الأداة ويستخدم الذاكرة لتذكر التفاعلات السابقة.
- السؤال الذاتي مع البحث: يعتمد هذا الوكيل على أداة واحدة، "الإجابة المتوسطة"، والتي تبحث عن إجابات واقعية للأسئلة. إنه يعادل السؤال الذاتي الأصلي مع ورقة البحث.
- مخزن مستندات ReAct: يتفاعل هذا الوكيل مع مخزن المستندات باستخدام إطار عمل ReAct. فهو يتطلب أدوات "بحث" و"بحث" وهو مشابه لمثال ويكيبيديا في ورقة ReAct الأصلية.
استكشف أنواع الوكلاء هذه للعثور على النوع الذي يناسب احتياجاتك في LangChain. تسمح لك هذه العوامل بربط مجموعة من الأدوات بداخلها للتعامل مع الإجراءات وإنشاء الاستجابات. تعلم المزيد عن كيفية بناء الوكيل الخاص بك باستخدام الأدوات هنا.
وكلاء مسبقة الصنع
دعونا نواصل استكشافنا للوكلاء، مع التركيز على الوكلاء المُنشأين مسبقًا والمتوفرين في LangChain.
جوجل
تقدم LangChain مجموعة أدوات Gmail التي تسمح لك بربط بريدك الإلكتروني على LangChain بواجهة برمجة تطبيقات 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,
)
فيما يلي بعض الأمثلة حول كيفية استخدام هذه الأدوات:
- قم بإنشاء مسودة Gmail لتحريرها:
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 الخاصة بك، خاصة إذا كانت تحتوي على ملايين الصفوف.
- غالبًا ما تدعم قواعد البيانات الموجهة لمستودع البيانات الحصص النسبية على مستوى المستخدم للحد من استخدام الموارد.
يمكنك أن تطلب من الوكيل وصف جدول، مثل جدول "playlisttrack". فيما يلي مثال لكيفية القيام بذلك:
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
يقدم هذا القسم وكيلًا مصممًا للتفاعل مع Pandas DataFrames لأغراض الإجابة على الأسئلة. يرجى ملاحظة أن هذا الوكيل يستخدم وكيل Python تحت الغطاء لتنفيذ كود Python الذي تم إنشاؤه بواسطة نموذج اللغة (LLM). توخي الحذر عند استخدام هذا الوكيل لمنع الضرر المحتمل من كود Python الضار الذي تم إنشاؤه بواسطة 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 صفًا في إطار البيانات".
يمكنك أيضًا أن تطلب من الوكيل تصفية الصفوف بناءً على معايير محددة، مثل العثور على عدد الأشخاص الذين لديهم أكثر من 3 أشقاء:
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())
بعد ذلك، يمكنك تهيئة الوكيل باستخدام كل من DataFrames وطرح سؤال عليه:
agent = create_pandas_dataframe_agent(OpenAI(temperature=0), [df, df1], verbose=True)
agent.run("how many rows in the age column are different?")
سيقوم الوكيل بمقارنة أعمدة العمر في كل من DataFrames وتقديم الإجابة، مثل "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 هي أداة مصممة لاستخدام نماذج اللغات الكبيرة (LLMs) في التطبيقات المعقدة. فهو يوفر أطرًا لإنشاء سلاسل من المكونات، بما في ذلك LLMs وأنواع أخرى من المكونات. إطارين أساسيين
- لغة التعبير 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 لتكوين المكونات. مثال LLMChain هو كما يلي:
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 أيضًا التكامل مع واجهات برمجة التطبيقات لاستدعاء الوظائف الخاصة بـ 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 وضمان الجودة مع الاستشهادات.
في سياق الاستخراج، تشبه العملية سلسلة المخرجات المنظمة ولكنها تركز على استخراج المعلومات أو الكيان. بالنسبة لوضع العلامات، تتمثل الفكرة في تسمية مستند بفئات مثل المشاعر أو اللغة أو الأسلوب أو الموضوعات المغطاة أو الاتجاه السياسي.
يمكن توضيح مثال لكيفية عمل العلامات في LangChain باستخدام كود Python. تبدأ العملية بتثبيت الحزم الضرورية وتهيئة البيئة:
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 بإنشاء سلاسل غير حتمية حيث يحدد ناتج الخطوة السابقة الخطوة التالية. وهذا يساعد في هيكلة والحفاظ على الاتساق في التفاعلات مع LLMs. على سبيل المثال، إذا كان لديك نموذجين محسّنين لأنواع مختلفة من الأسئلة، فيمكنك اختيار القالب بناءً على إدخال المستخدم.
إليك كيفية تحقيق ذلك باستخدام 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
يسجل كل استجابة مستندة إلى المستند ويختار الإجابة التي حصلت على أعلى الدرجات.
فيما يلي مثال لكيفية إعداد MapReduceDocumentsChain
باستخدام إل سي إي إل:
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 لك ولفرقك.
الوحدة الخامسة : الذاكرة
في 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 بتخزين الذكريات في متجر متجه ويستعلم عن المستندات الأكثر "بروزًا" في كل مرة يتم استدعاؤها. لا يتتبع نوع الذاكرة هذا ترتيب التفاعلات بشكل صريح ولكنه يستخدم استرجاع المتجهات لجلب الذكريات ذات الصلة.
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 طرقًا مختلفة لإدارة واسترجاع المعلومات من المحادثات، مما يعزز قدرات نماذج الذكاء الاصطناعي في فهم استعلامات المستخدم والسياق والرد عليها. يمكن تحديد كل نوع من أنواع الذاكرة بناءً على المتطلبات المحددة للتطبيق الخاص بك.
الآن سوف نتعلم كيفية استخدام الذاكرة مع LLMChain. تسمح الذاكرة في LLMChain للنموذج بتذكر التفاعلات والسياق السابقين لتوفير استجابات أكثر تماسكًا وإدراكًا للسياق.
لإعداد الذاكرة في 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، أداة قوية لتكوين سلاسل معالجة اللغة. لقد تم تصميمه خصيصًا لدعم الانتقال من النماذج الأولية إلى الإنتاج بسلاسة، دون الحاجة إلى تغييرات واسعة النطاق في التعليمات البرمجية. سواء كنت تقوم ببناء سلسلة بسيطة "موجه + LLM" أو خط أنابيب معقد يحتوي على مئات الخطوات، فإن LCEL ستلبي احتياجاتك.
فيما يلي بعض الأسباب لاستخدام LCEL في مشاريع معالجة اللغة الخاصة بك:
- تدفق سريع للرموز: توفر LCEL الرموز المميزة من نموذج اللغة إلى محلل الإخراج في الوقت الفعلي، مما يؤدي إلى تحسين الاستجابة والكفاءة.
- واجهات برمجة التطبيقات متعددة الاستخدامات: يدعم LCEL كلاً من واجهات برمجة التطبيقات المتزامنة وغير المتزامنة للنماذج الأولية واستخدام الإنتاج، ومعالجة الطلبات المتعددة بكفاءة.
- الموازاة التلقائية: تعمل LCEL على تحسين التنفيذ المتوازي عندما يكون ذلك ممكنًا، مما يقلل زمن الوصول في كل من واجهات المزامنة وغير المتزامنة.
- تكوينات موثوقة: قم بتكوين عمليات إعادة المحاولة والاحتياطيات لتعزيز موثوقية السلسلة على نطاق واسع، مع دعم البث قيد التطوير.
- دفق النتائج المتوسطة: يمكنك الوصول إلى النتائج المتوسطة أثناء المعالجة لتحديثات المستخدم أو لأغراض تصحيح الأخطاء.
- إنشاء المخطط: يقوم LCEL بإنشاء مخططات Pydantic وJSONSchema للتحقق من صحة الإدخال والإخراج.
- التتبع الشامل: يقوم LangSmith تلقائيًا بتتبع جميع الخطوات في السلاسل المعقدة من أجل إمكانية المراقبة وتصحيح الأخطاء.
- سهولة النشر: يمكنك نشر السلاسل التي تم إنشاؤها بواسطة LCEL بسهولة باستخدام LangServe.
الآن، دعونا نتعمق في أمثلة التعليمات البرمجية العملية التي توضح قوة LCEL. سنستكشف المهام والسيناريوهات الشائعة التي يتألق فيها LCEL.
موجه + ماجستير
يتضمن التكوين الأساسي الجمع بين الموجه ونموذج اللغة لإنشاء سلسلة تأخذ مدخلات المستخدم، وتضيفها إلى الموجه، وتمررها إلى نموذج، وترجع مخرجات النموذج الخام. هنا مثال:
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)
يتضمن هذا المثال معلومات استدعاء الوظيفة لإنشاء نكتة.
موجه + 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)
يقوم هذا المثال بتوزيع مخرجات الدالة "joke" مباشرةً.
هذه مجرد أمثلة قليلة لكيفية تبسيط 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) هو كتابة كود Python لحل مشاكل المستخدم. فيما يلي مثال لكيفية استخدام 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 لحل المشكلة. يتم بعد ذلك تنفيذ التعليمات البرمجية باستخدام Python REPL، ويتم إرجاع كود Python الناتج بتنسيق 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 من السهل دمج الأدوات والخدمات الخارجية المتنوعة في مسارات معالجة اللغة لديك، مما يعزز قدراتها ووظائفها.
إضافة الإشراف إلى تطبيق 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
تحسب الوظيفة تشابه جيب التمام بين إدخال المستخدم وقوالب المطالبة المحددة مسبقًا لأسئلة الفيزياء والرياضيات. استنادًا إلى درجة التشابه، تختار السلسلة ديناميكيًا قالب المطالبة الأكثر صلة، مما يضمن استجابة برنامج الدردشة الآلية بشكل مناسب لسؤال المستخدم.
استخدام الوكلاء والعناصر القابلة للتشغيل
يتيح لك LangChain إنشاء وكلاء من خلال الجمع بين العناصر القابلة للتشغيل والمطالبات والنماذج والأدوات. فيما يلي مثال لبناء وكيل واستخدامه:
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 المطورين على نشر عناصر وسلاسل LangChain القابلة للتشغيل كواجهة برمجة تطبيقات REST. تم دمج هذه المكتبة مع FastAPI وتستخدم pydantic للتحقق من صحة البيانات. بالإضافة إلى ذلك، فهو يوفر عميلاً يمكن استخدامه للاتصال بالعناصر القابلة للتشغيل المنشورة على الخادم، ويتوفر عميل JavaScript في LangChainJS.
المميزات
- يتم استنتاج مخططات الإدخال والإخراج تلقائيًا من كائن LangChain الخاص بك ويتم فرضها على كل استدعاء لواجهة برمجة التطبيقات (API)، مع ظهور رسائل خطأ غنية.
- تتوفر صفحة مستندات API مع JSONSchema وSwagger.
- نقاط نهاية /استدعاء و/دفعة و/دفق فعالة مع دعم للعديد من الطلبات المتزامنة على خادم واحد.
- /stream_log نقطة النهاية لدفق جميع (أو بعض) الخطوات المتوسطة من السلسلة/الوكيل الخاص بك.
- صفحة الملعب في /playground مع إخراج البث والخطوات المتوسطة.
- تتبع مدمج (اختياري) إلى LangSmith؛ ما عليك سوى إضافة مفتاح API الخاص بك (راجع التعليمات).
- تم تصميم كل ذلك باستخدام مكتبات Python مفتوحة المصدر التي تم اختبارها في المعركة مثل FastAPI وPydantic وuvloop وasyncio.
القيود
- لا يتم حتى الآن دعم عمليات رد اتصال العميل للأحداث التي تنشأ على الخادم.
- لن يتم إنشاء مستندات OpenAPI عند استخدام Pydantic V2. لا يدعم 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، ونموذج دردشة إنسانيًا، وسلسلة تستخدم النموذج الإنساني لإخبار نكتة حول موضوع ما.
#!/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 (يتطلب الإصدار 0.0.166 من LangChain.js أو إصدار أحدث):
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/invention - استدعاء العنصر القابل للتشغيل على إدخال واحد
- 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 لتكوين العنصر القابل للتشغيل
يمكنك العثور على صفحة ملعب للتشغيل الخاص بك على /my_runnable/playground. يعرض هذا واجهة مستخدم بسيطة لتكوين واستدعاء قابلية التشغيل الخاصة بك من خلال إخراج البث والخطوات المتوسطة.
لكل من العميل والخادم:
pip install "langserve[all]"
أو تثبيت النقطة "langserve[client]" لرمز العميل، وتثبيت النقطة "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 مع بعض القيود. لن يتم إنشاء مستندات OpenAPI للاستدعاء/الدفعة/الدفق/stream_log عند استخدام Pydantic V2. لا تدعم واجهة برمجة التطبيقات السريعة خلط مساحات الأسماء pydantic v1 وv2. يستخدم LangChain مساحة الاسم v1 في Pydantic v2. يرجى قراءة الإرشادات التالية لضمان التوافق مع LangChain. باستثناء هذه القيود، نتوقع أن تعمل نقاط نهاية واجهة برمجة التطبيقات (API) والملعب وأي ميزات أخرى كما هو متوقع.
غالبًا ما تتعامل تطبيقات LLM مع الملفات. هناك بنيات مختلفة يمكن إجراؤها لتنفيذ معالجة الملفات؛ على مستوى عال:
- يمكن تحميل الملف إلى الخادم عبر نقطة نهاية مخصصة ومعالجته باستخدام نقطة نهاية منفصلة.
- يمكن تحميل الملف إما بقيمة (بايت من الملف) أو مرجع (على سبيل المثال، عنوان URL s3 لمحتوى الملف).
- قد تكون نقطة نهاية المعالجة محظورة أو غير محظورة.
- إذا كانت هناك حاجة إلى معالجة كبيرة، فقد يتم إلغاء تحميل المعالجة إلى مجموعة عمليات مخصصة.
يجب عليك تحديد ما هي البنية المناسبة لتطبيقك. حاليًا، لتحميل الملفات حسب القيمة إلى ملف قابل للتشغيل، استخدم تشفير 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)
يمكنك الوراثة من CustomUserType إذا كنت تريد إلغاء تسلسل البيانات في نموذج pydantic بدلاً من تمثيل الإملاء المكافئ. في الوقت الحالي، يعمل هذا النوع فقط من جانب الخادم ويستخدم لتحديد سلوك فك التشفير المطلوب. في حالة الوراثة من هذا النوع، سيحتفظ الخادم بالنوع الذي تم فك تشفيره كنموذج 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;
};
يسمح بإنشاء إدخال تحميل ملف في ساحة لعب واجهة المستخدم للملفات التي تم تحميلها كسلاسل مشفرة باستخدام 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 لمكون واحد، قم بتشغيل سلسلة معينة عدة مرات عبر مجموعة بيانات للتأكد من أنها تلبي باستمرار شريط الجودة، أو التقط آثار الاستخدام واستخدم LLMs أو مسارات التحليلات لإنشاء رؤى.
المتطلبات الأساسية:
- قم بإنشاء حساب LangSmith وقم بإنشاء مفتاح API (انظر الزاوية اليسرى السفلية).
- تعرف على النظام الأساسي من خلال الاطلاع على المستندات.
الآن ، لنبدأ!
أولاً، قم بتكوين متغيرات البيئة الخاصة بك لإخبار LangChain بتسجيل التتبعات. يتم ذلك عن طريق ضبط متغير البيئة LANGCHAIN_TRACING_V2 على القيمة true. يمكنك إخبار LangChain بالمشروع الذي تريد تسجيل الدخول إليه عن طريق تعيين متغير البيئة LANGCHAIN_PROJECT (إذا لم يتم تعيينه، فسيتم تسجيل عمليات التشغيل إلى المشروع الافتراضي). سيؤدي هذا إلى إنشاء المشروع لك تلقائيًا إذا لم يكن موجودًا. يجب عليك أيضًا تعيين متغيرات البيئة LANGCHAIN_ENDPOINT وLANGCHAIN_API_KEY.
ملاحظة: يمكنك أيضًا استخدام مدير السياق في python لتسجيل التتبعات باستخدام:
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 للتفاعل مع واجهة برمجة التطبيقات:
from langsmith import Client client = Client()
قم بإنشاء مكون LangChain وقم بتشغيل السجل إلى النظام الأساسي. في هذا المثال، سنقوم بإنشاء وكيل بنمط ReAct مع إمكانية الوصول إلى أداة البحث العامة (DuckDuckGo). يمكن الاطلاع على مطالبة الوكيل في المركز هنا:
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
)
نحن نقوم بتشغيل الوكيل بشكل متزامن على مدخلات متعددة لتقليل زمن الوصول. يتم تسجيل عمليات التشغيل في LangSmith في الخلفية، لذلك لا يتأثر زمن الوصول للتنفيذ:
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 تقييم أي ماجستير في إدارة الأعمال أو سلسلة أو وكيل أو حتى وظيفة مخصصة. وكلاء المحادثة ذوو حالة (لديهم ذاكرة)؛ لضمان عدم مشاركة هذه الحالة بين عمليات تشغيل مجموعة البيانات، سنمرر في 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 هي أداة قيمة لدمج نماذج اللغة (LLMs) مع تطبيقاتك، إلا أنها قد تواجه قيودًا عندما يتعلق الأمر بحالات الاستخدام المؤسسي. دعونا نستكشف كيف تتجاوز شبكات النانو نطاق LangChain لمعالجة هذه التحديات:
1. اتصال البيانات الشامل:
توفر LangChain موصلات، ولكنها قد لا تغطي جميع تطبيقات مساحة العمل وتنسيقات البيانات التي تعتمد عليها الشركات. توفر Nanonets موصلات بيانات لأكثر من 100 تطبيق من تطبيقات مساحة العمل المستخدمة على نطاق واسع، بما في ذلك Slack وNotion وGoogle Suite وSalesforce وZendesk وغيرها الكثير. كما أنه يدعم جميع أنواع البيانات غير المنظمة مثل ملفات PDF وTXTs والصور والملفات الصوتية وملفات الفيديو، بالإضافة إلى أنواع البيانات المنظمة مثل ملفات CSV وجداول البيانات وقواعد بيانات MongoDB وSQL.
2. أتمتة المهام لتطبيقات مساحة العمل:
في حين أن إنشاء النص/الاستجابة يعمل بشكل رائع، فإن قدرات LangChain محدودة عندما يتعلق الأمر باستخدام اللغة الطبيعية لأداء المهام في التطبيقات المختلفة. توفر Nanonets عوامل التشغيل/الإجراء لتطبيقات مساحة العمل الأكثر شيوعًا، مما يسمح لك بإعداد مهام سير العمل التي تستمع إلى الأحداث وتنفذ الإجراءات. على سبيل المثال، يمكنك أتمتة استجابات البريد الإلكتروني وإدخالات CRM واستعلامات SQL والمزيد، كل ذلك من خلال أوامر اللغة الطبيعية.
3. مزامنة البيانات في الوقت الحقيقي:
تقوم LangChain بجلب البيانات الثابتة باستخدام موصلات البيانات، والتي قد لا تواكب تغييرات البيانات في قاعدة البيانات المصدر. في المقابل، تضمن Nanonets المزامنة في الوقت الفعلي مع مصادر البيانات، مما يضمن أنك تعمل دائمًا مع أحدث المعلومات.
3. التكوين المبسط:
يمكن أن يكون تكوين عناصر خط أنابيب LangChain، مثل المستردات وأجهزة المزج، عملية معقدة وتستغرق وقتًا طويلاً. تعمل شبكات النانو على تبسيط ذلك من خلال توفير استيعاب البيانات وفهرستها بشكل محسّن لكل نوع من أنواع البيانات، ويتم التعامل معها جميعًا في الخلفية بواسطة مساعد الذكاء الاصطناعي. وهذا يقلل من عبء الضبط الدقيق ويسهل الإعداد والاستخدام.
4. الحل الموحد:
على عكس LangChain، الذي قد يتطلب تطبيقات فريدة لكل مهمة، تعمل Nanonets كحل شامل لربط بياناتك مع LLMs. سواء كنت بحاجة إلى إنشاء تطبيقات LLM أو سير عمل الذكاء الاصطناعي، فإن Nanonets توفر منصة موحدة لتلبية احتياجاتك المتنوعة.
سير عمل الذكاء الاصطناعي لشبكات النانو
يعد Nanonets Workflows مساعدًا آمنًا ومتعدد الأغراض للذكاء الاصطناعي يعمل على تبسيط تكامل معرفتك وبياناتك مع LLMs ويسهل إنشاء تطبيقات وسير عمل بدون تعليمات برمجية. وهو يوفر واجهة مستخدم سهلة الاستخدام، مما يجعله في متناول الأفراد والمنظمات على حد سواء.
للبدء، يمكنك جدولة مكالمة مع أحد خبراء الذكاء الاصطناعي لدينا، والذي يمكنه تقديم عرض توضيحي مخصص وتجربة لسير عمل Nanonets المصمم خصيصًا لحالة الاستخدام المحددة الخاصة بك.
بمجرد الإعداد، يمكنك استخدام اللغة الطبيعية لتصميم وتنفيذ التطبيقات وسير العمل المعقدة التي تدعمها LLMs، والتكامل بسلاسة مع تطبيقاتك وبياناتك.
قم بتعزيز فرقك باستخدام Nanonets AI لإنشاء تطبيقات ودمج بياناتك مع التطبيقات وسير العمل المستندة إلى الذكاء الاصطناعي، مما يسمح لفرقك بالتركيز على ما يهم حقًا.
يمكنك أتمتة المهام اليدوية ومسارات العمل باستخدام أداة إنشاء سير العمل المستندة إلى الذكاء الاصطناعي، والتي صممتها Nanonets لك ولفرقك.
- محتوى مدعوم من تحسين محركات البحث وتوزيع العلاقات العامة. تضخيم اليوم.
- PlatoData.Network Vertical Generative Ai. تمكين نفسك. الوصول هنا.
- أفلاطونايستريم. ذكاء Web3. تضخيم المعرفة. الوصول هنا.
- أفلاطون كربون، كلينتك ، الطاقة، بيئة، شمسي، إدارة المخلفات. الوصول هنا.
- أفلاطون هيلث. التكنولوجيا الحيوية وذكاء التجارب السريرية. الوصول هنا.
- المصدر https://nanonets.com/blog/langchain/
- :لديها
- :يكون
- :ليس
- :أين
- $ UP
- 1
- 10
- 100
- 114
- 13
- 15%
- 2000
- 2012
- 2023
- 25
- 30
- 32
- 36
- 40
- 400
- 408
- 50
- 500
- 7
- 8
- a
- ايه بي سي
- القدرة
- ماهرون
- من نحن
- حوله
- فوق
- استمر
- يقبل
- الوصول
- يمكن الوصول
- الوصول
- إنجاز
- وفقا لذلك
- حسابي
- دقة
- دقيق
- بدقة
- التأهيل
- تحقق
- يحقق
- في
- عمل
- اكشن
- الإجراءات
- نشط
- التكيف
- على التكيف
- تضيف
- وأضاف
- مضيفا
- إضافة
- إضافي
- وبالإضافة إلى ذلك
- العنوان
- يضيف
- يعترف
- متقدم
- مغامرة
- بعد
- مرة أخرى
- السن
- الوكيل
- عملاء
- AI
- مساعد AI
- نماذج الذكاء الاصطناعى
- مساعدة
- تهدف
- خوارزميات
- محاذاة
- يحاذي
- الكل
- السماح
- السماح
- يسمح
- وحده
- على طول
- جنبا إلى جنب
- سابقا
- أيضا
- بالرغم ان
- دائما
- an
- تحليل
- تحليلية
- تحليلات
- و
- لوس
- أعلن
- سنوي
- آخر
- إجابة
- الأجوبة
- نشيد وطني
- أنثروبي
- أي وقت
- اى شى
- API
- مفاتيح API
- واجهات برمجة التطبيقات
- التطبيق
- ذو صلة
- تطبيق
- تطوير التطبيقات
- التطبيقات
- تطبيقي
- ينطبق
- نهج
- اقتراب
- مناسب
- بشكل مناسب
- التطبيقات
- هندسة معمارية
- هي
- حجة
- الحجج
- ارمسترونغ
- حول
- مجموعة
- الفنانين
- AS
- تطلب
- جانب
- الجوانب
- مساعدة
- المساعد
- أسوشيتد
- At
- يرفق
- اهتمام
- سمعي
- المعزز
- التحقّق من المُستخدم
- أتمتة
- الآلي
- الأتمتة
- تلقائيا
- أتمتة
- متاح
- المتوسط
- ترقب
- علم
- AWS
- الى الخلف
- العمود الفقري
- الخلفية
- خلفية
- بشكل سيئ
- الرصيد
- شريط
- قاعدة
- على أساس
- خط الأساس
- سحق
- الأساسية
- الأساسيات
- BCG
- BE
- شاطئ
- تتحمل
- لان
- كان
- قبل
- بدأ
- سلوك
- وراء
- خلف الكواليس
- يجري
- أقل من
- مؤشر
- مفيد
- أفضل
- أفضل
- ما بين
- Beyond
- أكبر
- مشروع قانون
- بيل غيتس
- ربط
- بنج
- قطعة
- اسود
- الثقب الأسود
- حظر
- حجب
- Blocks
- المدونة
- بوب
- التمهيد
- مولود
- أحذية طويلة
- على حد سواء
- الملابس السفلية
- الفرع
- استراحة
- نسيم
- موجز
- أوسع
- بنى
- المتصفح
- العازلة
- نساعدك في بناء
- باني
- ابني
- بنيت
- عبء
- الأعمال
- لكن
- by
- حساب
- تحسب
- حساب
- حساب
- دعوة
- الاسترجاعات
- تسمى
- دعوة
- دعوات
- CAN
- يستطيع الحصول على
- كندا
- قدرات
- قادر على
- الطاقة الإنتاجية
- أسر
- اسر
- حقيبة
- الحالات
- قط
- تلبية
- التموين
- يلبي
- القطط
- الحذر
- حذر
- مركز
- معين
- سلسلة
- السلاسل
- التحديات
- التغييرات
- حرف
- chatbot
- chatbots
- التحقق
- الشيكات
- اختار
- اختيار
- ظروف
- المدينة
- فئة
- فصول
- زبون
- سحابة
- الكود
- البرمجة
- قهوة
- متماسك
- متماسك
- تعاون
- انهيار
- مجموعة شتاء XNUMX
- ملونة
- عمود
- الأعمدة
- COM
- دمج
- الجمع بين
- يجمع بين
- الجمع بين
- تأتي
- يأتي
- مريح
- مشترك
- Communication
- حول الشركة
- قارن
- مقارنة
- التوافق
- متوافق
- إكمال
- تماما
- إكمال
- مجمع
- التعقيدات
- عنصر
- مكونات
- تتألف
- تركيب
- شامل
- تضم
- مفهوم
- مختصرا
- منافس
- حالة
- الاعداد
- احتشاد
- التواصل
- الرابط
- الإتصال
- سلبيات
- نظر
- باتساق
- يتكون
- كنسولات
- باستمرار
- يبني
- تحتوي على
- يحتوي
- محتوى
- سياق الكلام
- السياقات
- قريني
- استمر
- بشكل متواصل
- تباين
- مراقبة
- ضوابط
- مناسب
- محادثة
- تحادثي
- محادثة منظمة العفو الدولية
- المحادثات
- تحويل
- تحويلها
- التحول
- جوهر
- زاوية
- تصحيح
- المقابلة
- استطاع
- عد
- البلد
- زوجان
- بهيكل
- مغطى
- خلق
- خلق
- يخلق
- خلق
- خلق
- أوراق اعتماد
- المعايير
- الناقد
- CRM
- حاسم
- حالياًّ
- حاليا
- على
- العملاء
- التخصيص
- تصميم
- حسب الطلب
- المتطور والحديث
- البيانات
- هيكل البيانات
- قاعدة البيانات
- قواعد البيانات
- التاريخ
- التاريخ والوقت
- صفقة
- تعامل
- ديسمبر
- تقرر
- اتخاذ القرار
- اتخاذ القرار
- فك
- مخصصة
- أعمق
- الترتيب
- حدد
- تعريف
- تحديد
- التعاريف
- تقديم
- يسلم
- الخوض
- عرض
- شرح
- تظاهر
- التظاهر
- تعتمد
- اعتمادا
- يعتمد
- نشر
- نشر
- نشر
- نشر
- ينشر
- وصف
- وصف
- تصميم
- محدد
- تصميم
- مطلوب
- التفاصيل
- مفصلة
- تفاصيل
- حدد
- يحدد
- تطوير
- المطور
- المطورين
- تطوير
- التطوير التجاري
- الرسوم البيانية
- DICT
- فعل
- اختلف
- مختلف
- بشكل مختلف
- صعبة
- بعد
- الأبعاد
- توجيهات
- مباشرة
- بحث
- ناقش
- عرض
- خامد
- غطس
- عدة
- DM
- do
- وثيقة
- توثيق
- وثائق
- هل
- لا توجد الآن
- فعل
- دون
- فعل
- مضاعفة
- إلى أسفل
- بإمكانك تحميله
- التنزيلات
- مسودة
- قيادة
- اثنان
- أثناء
- ديناميكي
- حيوي
- e
- كل
- في وقت سابق
- في وقت مبكر
- سهولة
- سهولة الاستخدام
- أسهل
- بسهولة
- سهل
- سهلة الاستخدام
- صدى
- النظام الإيكولوجي
- الطُرق الفعّالة
- على نحو فعال
- كفاءة
- فعال
- بكفاءة
- جهد
- إما
- العنصر
- عناصر
- ايلون
- إيلون ماسك
- آخر
- البريد الإلكتروني
- تضمين
- جزءا لا يتجزأ من
- تضمين
- يعمل
- الموظفين
- توظف
- تمكين
- تمكين
- تمكن
- تمكين
- يغلف
- لقاء
- النهائي إلى نهاية
- نقطة النهاية
- جذاب
- محرك
- محركات
- إنكلترا
- انجليزي
- الدوري الإنجليزي
- تعزيز
- تعزيز
- تعزيز
- ضمان
- يضمن
- ضمان
- مشروع
- الكيانات
- كيان
- البيئة
- البيئات
- معادل
- عصر
- خطأ
- أخطاء
- خاصة
- أساسي
- المبعدة
- إلخ
- تقييم
- تقييم
- حتى
- أحداث
- كل
- مثال
- أمثلة
- تجاوز
- إلا
- تنفيذ
- أعدم
- ينفذ
- تنفيذ
- يجسد
- ممارسة
- يوجد
- توقع
- التوقعات
- متوقع
- تتوقع
- الخبره في مجال الغطس
- تجريبي
- خبرائنا
- شرح
- ويوضح
- صراحة
- استكشاف
- اكتشف
- استكشاف
- تصدير
- التعبير
- مد
- إطالة
- واسع
- خارجي
- احتفل على
- استخراج
- استخلاص
- مقتطفات
- الوجه
- تسهيل
- يسهل
- مصنع
- حقائق
- بعيدا
- FAST
- المفضلة—الحقيبة
- الميزات
- المميزات
- ردود الفعل
- قليل
- حقل
- مجال
- التين
- الشكل
- قم بتقديم
- ملفات
- شغل
- معبأ
- حشوة
- تصفية
- تصفية
- نهائي
- أخيرا
- العثور على
- الاسم الأول
- خمسة
- مرونة
- مرن
- تدفق
- تركز
- ركز
- ويركز
- التركيز
- اتباع
- متابعيك
- متابعات
- طعام
- في حالة
- النموذج المرفق
- شكل
- شكلت
- لحسن الحظ
- وجدت
- الإطار
- الأطر
- كثيرا
- صديق
- الاصدقاء
- تبدأ من
- بالإضافة إلى
- كامل الأهلية
- وظيفة
- وظائف
- وظيفة
- وظائف
- أساسي
- مضحك
- إضافي
- مستقبل
- ربح
- ألعاب
- البوابات و حواجز اللعب
- العلاجات العامة
- على العموم
- توليد
- ولدت
- يولد
- توليد
- جيل
- نوع
- ألمانيا
- دولار فقط واحصل على خصم XNUMX% على جميع
- الحصول على
- GIF
- GitHub جيثب:
- معطى
- GMT
- Go
- يذهب
- الذهاب
- خير
- شراء مراجعات جوجل
- حبيبي
- رسم بياني
- عظيم
- أكبر
- توجيه
- توجيه
- المبادئ التوجيهية
- hackathon
- مقبض
- مقابض
- معالجة
- في المتناول
- الثابت
- ضرر
- أحزمة
- يملك
- وجود
- بشكل كبير
- عقد
- مساعدة
- مفيد
- يساعد
- لها
- هنا
- hi
- مرتفع
- رفيع المستوى
- عالي الجودة
- أعلى
- جدا
- تاريخي
- تاريخ
- حفرة
- غطاء محرك السيارة
- مضيف
- كيفية
- كيفية
- لكن
- HTML
- HTTP
- HTTPS
- محور
- الانسان
- مئات
- i
- ID
- فكرة
- المثالي
- IDS
- if
- ii
- ثالثا
- توضيح
- يوضح
- صور
- فوري
- تنفيذ
- التنفيذ
- تطبيقات
- نفذت
- استيراد
- تحسينات
- تحسين
- in
- في العمق
- تتضمن
- شامل
- يشمل
- بما فيه
- دمج
- دمج
- لا يصدق
- مؤشر
- الفهارس
- تشير
- يشير
- بشكل فردي
- الأفراد
- معلومات
- في البداية
- بدء
- مبتكرة
- إدخال
- المدخلات
- رؤى
- تثبيت
- تثبيت
- تركيب
- مثل
- لحظة
- بدلًا من ذلك
- تعليمات
- متكامل
- دمج
- المتكاملة
- يدمج
- دمج
- التكامل
- التكاملات
- ذكي
- معد
- تفاعل
- تفاعل
- التفاعلات
- التفاعلية
- يتفاعل
- السطح البيني
- واجهات
- داخليا
- Internet
- إلى
- أدخلت
- يدخل
- حدسي
- تنطوي
- يسن
- قضية
- مسائل
- IT
- العناصر
- التكرارات
- انها
- نفسها
- جاكسون
- جافا سكريبت
- وظيفة
- الأردن
- رحلة
- جسون
- يوليو
- م
- الاجتماعية
- احتفظ
- يحتفظ
- القفل
- مفاتيح
- نوع
- علم
- المعرفة
- الرسم البياني المعرفة
- معروف
- تُشير
- ملصقات
- البلد
- لغة
- اللغات
- كبير
- أكبر
- اسم العائلة
- كمون
- الى وقت لاحق
- آخر
- الدوري
- تعلم
- تعلم
- اليسار
- إرث
- الطول
- أقل
- اسمحوا
- يتيح
- خطاب
- مستوى
- ومستوياتها
- الرافعة المالية
- روافع
- الاستفادة من
- المكتبات
- المكتبة
- مثل
- على الأرجح
- مما سيحدث
- القيود
- محدود
- الحد من
- حدود
- وصلات
- قائمة
- استمع
- قوائم
- حي
- ll
- LLM
- تحميل
- محمل
- تقع
- موقع
- سجل
- تسجيل الدخول
- تسجيل
- منطق
- طويل
- يعد
- بحث
- أبحث
- تبدو
- بحث
- ال
- لوس أنجلوس
- منخفض
- آلة
- آلة التعلم
- صنع
- المحافظة
- يمكن الحفاظ عليها
- الحفاظ على
- تحتفظ
- جعل
- يصنع
- القيام ب
- إدارة
- إدارة
- مدير
- إدارة
- مانشستر
- مانشستر يونايتد
- تلاعب
- أسلوب
- كتيب
- الشركة المصنعة
- كثير
- كثير من الناس
- رسم خريطة
- رسم الخرائط
- برنامج Maps
- مباراة
- مطابقة
- الرياضيات
- رياضي
- المسائل
- أقصى
- مايو..
- me
- تعني
- معنى
- يعني
- قياس
- الوسائط
- الاجتماع
- يجتمع
- ذكريات
- مكبر الصوت : يدعم، مع دعم ميكروفون مدمج لمنع الضوضاء
- المذكورة
- دمج
- دمج
- الرسالة
- رسائل
- الرسائل
- البيانات الوصفية
- طريقة
- طرق
- المقاييس
- ربما
- ملايين
- أدنى
- قاصر
- مفقود
- الأخطاء
- خلط
- MLB
- الجوال
- نموذج
- عارضات ازياء
- الاعتدال
- وحدة
- الوحدات
- لحظة
- MongoDB
- مراقبة
- مراقبة
- قمر
- الأكثر من ذلك
- أكثر
- الاكثر شهره
- خطوة
- فيلم
- كثيرا
- متعدد
- سلاسل متعددة
- مسك
- يجب
- my
- الاسم
- عين
- أسماء
- محليات
- طبيعي
- معالجة اللغات الطبيعية
- التنقل
- التنقل
- قرب
- ضروري
- حاجة
- بحاجة
- إحتياجات
- سلبي
- جديد
- نيويورك
- نيويورك تايمز
- التالي
- لا
- بدون اضاءة
- لا شى
- Notion
- الآن
- عدد
- أوباما
- موضوع
- موضوعي
- الأجسام
- ملاحظة
- تحصل
- الحصول على
- التعرف الضوئي على الحروف
- of
- عرض
- الوهب
- عروض
- غالبا
- oh
- حسنا
- الألعاب الأولمبية
- on
- مرة
- ONE
- فقط
- المصدر المفتوح
- OpenAI
- عمليات
- عامل
- الأمثل
- المثلى
- خيار
- or
- طلب
- عضوي
- المنظمات
- أصلي
- OS
- أخرى
- أخرى
- وإلا
- لنا
- خارج
- الناتج
- النتائج
- على مدى
- تجاوز
- نظرة عامة
- الخاصة
- صفقة
- حزم
- صفحة
- صفحات
- أزواج
- الباندا
- ورق
- موازية
- المعلمة
- المعلمات
- متنزهات
- جزء
- خاصة
- أجزاء
- pass
- مرت
- يمر
- مرور
- الماضي
- مسار
- مسارات
- أنماط
- كشف رواتب
- مجتمع
- إلى
- تماما
- نفذ
- أداء
- أداء
- ينفذ
- أذونات
- إصرار
- شخص
- مخصصه
- منظور
- فيزياء
- قطعة
- خط أنابيب
- البيتزا
- النائب
- المنصة
- أفلاطون
- الذكاء افلاطون البيانات
- أفلاطون داتا
- بلايستشن
- ملعب
- يلعب
- من فضلك
- المزيد
- البوينت
- سياسات الخصوصية والبيع
- سياسة
- سياسي
- تجمع
- الرائج
- مأهول
- إيجابي
- ممكن
- منشور
- المنشورات
- محتمل
- قوة
- مدعوم
- قوي
- عملية
- ممارسة
- تفضل
- رئيس الوزراء
- يقدم
- رئيس
- منع
- منع
- سابق
- في المقام الأول
- ابتدائي
- رئيسي
- خاص
- المشكلة
- مشاكل
- والمضي قدما
- عملية المعالجة
- معالجتها
- العمليات
- معالجة
- إنتاج
- المنتج
- الإنتــاج
- البروفيسور
- برمجة وتطوير
- لغات البرمجة
- تنفيذ المشاريع
- مشروع ناجح
- HAS
- الملكية
- الإيجابيات
- النموذج
- النماذج
- تزود
- المقدمة
- مزود
- مقدمي
- ويوفر
- توفير
- جمهور
- غرض
- أغراض
- وضع
- بايثون
- سؤال وجواب
- جودة
- الاستفسارات
- سؤال
- الأسئلة المتكررة
- سريع
- بسرعة
- يقتبس
- R
- رفع
- نطاق
- تتراوح
- بدلا
- تصنيف
- الخام
- RE
- الوصول
- رد فعل
- عرض
- نادي القراءة
- استعداد
- حقيقي
- في الوقت الحقيقي
- معلومات الوقت الحقيقي
- مملكة
- سبب
- الأسباب
- الأخيرة
- موصى به
- مسجل
- تسجيل
- استعادة
- تخفيض
- يقلل
- تقليص
- تخفيض
- مرجع
- الرجوع
- صقل
- تنقية
- المناطق
- العلاقات
- صدر
- مدى صلة
- ذات الصلة
- الموثوقية
- الخدمة الموثوقة
- اعتمد
- الاعتماد
- بقايا
- تذكر
- تذكير
- عن بعد
- محصول
- كرر
- مرارا وتكرارا
- إعادة الصياغة
- يحل محل
- تقرير
- مستودع
- التمثيل
- تمثل
- يمثل
- طلب
- طلبات
- تطلب
- مطلوب
- المتطلبات الأساسية
- يتطلب
- إنقاذ
- بحث
- حل
- مورد
- الرد
- الاستجابة
- استجابة
- ردود
- مسؤول
- استجابة
- REST
- نتيجة
- مما أدى
- النتائج
- الاحتفاظ
- استبقاء
- عائد أعلى
- عودة
- عائدات
- قابلة لإعادة الاستخدام
- مراجعة
- يدور
- أرز
- النوادي الثرية
- الروبوتات
- النوع
- الأدوار
- جذر
- التوجيه
- صف
- يجري
- تشغيل
- يدير
- وقت التشغيل
- s
- الضمانات
- الأملاح
- SALESFORCE
- سام
- نفسه
- حفظ
- قول
- يقول
- تحجيم
- حجم
- سيناريو
- سيناريوهات
- مشاهد
- جدول
- أحرز هدفاً
- خدش
- سلس
- بسلاسة
- بحث
- محرك البحث
- البحث
- البحث
- القسم
- أقسام
- تأمين
- أمن
- انظر تعريف
- مختار
- اختيار
- بيع
- إرسال
- حساس
- عاطفة
- مشاعر
- مستقل
- سبتمبر
- تسلسل
- مسلسلات
- خدمة
- الخادم
- يخدم
- خدماتنا
- طقم
- باكجات
- ضبط
- إعدادات
- الإعداد
- سبعة
- عدة
- مشاركة
- شاركت
- قذيفة
- يضيء
- تم شحنه
- ينبغي
- إظهار
- عرض
- أظهرت
- يظهر
- Sigma
- هام
- مماثل
- الاشارات
- مبسط
- تبسيط
- تبسيط
- ببساطة
- منذ
- عزباء
- المقاس
- تثاقل
- صغير
- الأصغر
- سمارت
- قصاصة
- So
- حتى الآن
- كرة القدم
- العدالة
- وسائل التواصل الاجتماعي
- منشورات مواقع التواصل الاجتماعي
- فقط
- الصلبة
- حل
- حل
- بعض
- شيء
- أحيانا
- متطور
- الأصوات
- مصدر
- مصادر
- الفضاء
- الإسبانية
- متخصص
- محدد
- على وجه التحديد
- تفاصيل
- محدد
- سرعة
- قضى
- انقسم
- الإنشقاقات
- رياضة
- مربع
- موقف
- مستقل
- معيار
- بداية
- بدأت
- ابتداء
- الولايه او المحافظه
- البيانات
- ساكن
- خطوة
- خطوات
- لا يزال
- قلة النوم
- وقف
- توقف
- تخزين
- متجر
- تخزين
- فروعنا
- تخزين
- قصتنا
- صريح
- مجرى
- متدفق
- تبسيط
- تبسيط
- نقاط القوة
- الضربات
- خيط
- بناء
- منظم
- الهياكل
- الهيكلة
- نمط
- موضوع
- لاحق
- بنجاح
- هذه
- بدلة
- مناسب
- جناح
- تلخيص
- ملخص
- غروب
- الدعم
- مدعومة
- الدعم
- بالتأكيد
- الاستدامة
- تزامن
- ملخص
- بناء الجملة
- نظام
- أنظمة
- جدول
- خياط
- تناسب
- أخذ
- يأخذ
- الأهداف
- مهمة
- المهام
- فريق
- فريق
- اقول
- قالب
- النماذج
- محطة
- المصطلح
- سياسة الحجب وتقييد الوصول
- تجربه بالعربي
- الاختبار
- نص
- من
- شكر
- أن
- •
- أساسيات
- المحور
- المعلومات
- نيو يورك تايمز
- المشاريع
- المصدر
- العالم
- من مشاركة
- منهم
- then
- هناك.
- تشبه
- هم
- الأشياء
- هؤلاء
- على الرغم من؟
- عبر
- طوال
- الوقت
- استهلاك الوقت
- مرات
- عنوان
- إلى
- سويا
- رمز
- Tokenization
- الرموز
- جدا
- أداة
- أدوات
- أدوات
- تيشرت
- موضوع
- المواضيع
- الإجمالي
- بلدة
- البحث عن المفقودين
- مسار
- تقليدي
- قادة الإيمان
- تحول
- التحولات
- محول
- محولات
- انتقال
- محاكمة
- صحيح
- حقا
- محاولة
- ضبط
- منعطف أو دور
- تحول
- البرنامج التعليمي
- مرتين
- اثنان
- نوع
- أنواع
- نسخة مطبوعة على الآلة الكاتبة
- عادة
- ui
- في النهاية
- لم تتأثر
- مع
- التي تقوم عليها
- فهم
- فهم
- يفهم
- موحد
- فريد من نوعه
- متحد
- عالمي
- مختلف
- حتى
- تحديث
- آخر التحديثات
- تم التحميل
- URL
- us
- قابليتها للاستخدام
- الأستعمال
- تستخدم
- حالة الاستخدام
- مستعمل
- مستخدم
- واجهة المستخدم
- المستخدمين
- يستخدم
- استخدام
- خدمات
- الاستفادة من
- تستخدم
- يستخدم
- استخدام
- v1
- التحقق من صحة
- المصادقة
- القيمة
- قيمنا
- القيم
- متغير
- تشكيلة
- مختلف
- Ve
- متعدد الجوانب
- الإصدار
- جدا
- بواسطة
- فيديو
- المزيد
- انتهاكات
- مرئي
- تصور
- حيوي
- vs
- سير
- تجول
- تريد
- وكان
- شاهد
- طريق..
- طرق
- we
- الطقس
- الويب
- متصفح الويب
- خدمات ويب
- المواقع
- حسن
- معروف
- كان
- ابحث عن
- ما هي تفاصيل
- ما
- متى
- سواء
- التي
- في حين
- من الذى
- كامل
- لماذا
- واسع
- على نحو واسع
- القطعة
- ويكيبيديا
- سوف
- نافذة
- يفوز
- مع
- في غضون
- بدون
- كلمة
- للعمل
- عمل
- سير العمل
- سير العمل
- عامل
- أعمال
- العالم
- سوف
- اكتب
- جاري الكتابة
- X
- حتى الآن
- نيويورك
- أنت
- حل متجر العقارات الشامل الخاص بك في جورجيا
- نفسك
- موقع YouTube
- Zendesk
- زفيرنت
- الرمز البريدي