בבסיס שלו, LangChain היא מסגרת חדשנית המותאמת ליצירת יישומים הממנפים את היכולות של מודלים של שפה. זוהי ערכת כלים שנועדה למפתחים ליצור יישומים מודעים להקשר ומסוגלים לנמק מתוחכם.
משמעות הדבר היא שיישומי LangChain יכולים להבין את ההקשר, כגון הוראות מיידיות או תגובות בסיס לתוכן ולהשתמש במודלים של שפה למשימות חשיבה מורכבות, כמו החלטה כיצד להגיב או אילו פעולות לנקוט. LangChain מייצגת גישה מאוחדת לפיתוח יישומים חכמים, המפשטת את המסע מהרעיון לביצוע עם מרכיביו המגוונים.
הבנת LangChain
LangChain הוא הרבה יותר מסתם מסגרת; זוהי מערכת אקולוגית מן המניין הכוללת מספר חלקים אינטגרליים.
- ראשית, יש את ספריות LangChain, הזמינות גם ב-Python וגם ב-JavaScript. ספריות אלו הן עמוד השדרה של LangChain, ומציעות ממשקים ואינטגרציות לרכיבים שונים. הם מספקים זמן ריצה בסיסי לשילוב רכיבים אלה לרשתות וסוכנים מגובשים, יחד עם יישומים מוכנים לשימוש מיידי.
- לאחר מכן, יש לנו תבניות LangChain. אלו הם אוסף של ארכיטקטורות ייחוס הניתנות לפריסה המותאמות למגוון רחב של משימות. בין אם אתה בונה צ'אט בוט או כלי אנליטי מורכב, תבניות אלו מציעות נקודת התחלה מוצקה.
- LangServe נכנס בתור ספרייה רב-תכליתית לפריסת רשתות LangChain כ- REST APIs. כלי זה חיוני להפיכת פרויקטי LangChain שלך לשירותי אינטרנט נגישים וניתנים להרחבה.
- לבסוף, LangSmith משמשת כפלטפורמת מפתחים. זה נועד לנפות באגים, לבדוק, להעריך ולנטר רשתות הבנויות על כל מסגרת LLM. האינטגרציה החלקה עם LangChain הופכת אותו לכלי הכרחי עבור מפתחים שמטרתם לחדד ולשכלל את היישומים שלהם.
יחד, רכיבים אלה מחזקים אותך לפתח, לייצר ולפרוס יישומים בקלות. עם LangChain, אתה מתחיל בכתיבת היישומים שלך באמצעות הספריות, תוך התייחסות לתבניות להדרכה. לאחר מכן, LangSmith עוזרת לך בבדיקה, בדיקה ובקרה של הרשתות שלך, ומבטיחה שהיישומים שלך משתפרים כל הזמן ומוכנים לפריסה. לבסוף, עם LangServe, אתה יכול בקלות להפוך כל שרשרת ל-API, מה שהופך את הפריסה לפשוטה.
בסעיפים הבאים, נעמיק כיצד להגדיר את LangChain ולהתחיל את המסע שלך ביצירת יישומים אינטליגנטיים המופעלים על ידי מודל שפה.
הפוך משימות וזרימות עבודה ידניות לאוטומטיות עם בונה זרימת העבודה המונעת בינה מלאכותית שלנו, שתוכנן על ידי Nanonets עבורך ועבור הצוותים שלך.
התקנה והתקנה
האם אתה מוכן לצלול לתוך העולם של LangChain? ההגדרה שלו פשוטה, והמדריך הזה ידריך אותך בתהליך שלב אחר שלב.
השלב הראשון במסע LangChain שלך הוא להתקין אותו. אתה יכול לעשות זאת בקלות באמצעות pip או conda. הפעל את הפקודה הבאה בטרמינל שלך:
pip install langchain
למי שמעדיף את התכונות העדכניות ביותר ונוח עם קצת יותר הרפתקאות, אתה יכול להתקין את LangChain ישירות מהמקור. שכפל את המאגר ונווט אל langchain/libs/langchain
מַדרִיך. לאחר מכן, הרץ:
pip install -e .
לתכונות ניסיוניות, שקול התקנה langchain-experimental
. זוהי חבילה המכילה קוד חדשני ומיועדת למטרות מחקר וניסוי. התקן אותו באמצעות:
pip install langchain-experimental
LangChain CLI הוא כלי שימושי לעבודה עם תבניות LangChain ופרויקטים של LangServe. כדי להתקין את LangChain CLI, השתמש ב:
pip install langchain-cli
LangServe חיוני לפריסת שרשראות LangChain שלך בתור REST API. הוא מותקן לצד LangChain CLI.
LangChain דורשת לעתים קרובות אינטגרציות עם ספקי מודלים, מאגרי נתונים, APIs וכו'. לדוגמא זו, נשתמש בממשקי ה-API של המודל של OpenAI. התקן את חבילת OpenAI Python באמצעות:
pip install openai
כדי לגשת ל-API, הגדר את מפתח ה-API של OpenAI כמשתנה סביבה:
export OPENAI_API_KEY="your_api_key"
לחלופין, העבר את המפתח ישירות בסביבת הפיתון שלך:
import os
os.environ['OPENAI_API_KEY'] = 'your_api_key'
LangChain מאפשרת יצירת יישומי מודל שפה באמצעות מודולים. מודולים אלה יכולים לעמוד בפני עצמם או להיות מורכבים עבור מקרי שימוש מורכבים. מודולים אלה הם -
- דגם I/O: מקל על אינטראקציה עם מודלים שונים של שפות, טיפול בתשומות ובפלטים שלהם ביעילות.
- אחזור: מאפשר גישה ואינטראקציה עם נתונים ספציפיים ליישום, חיוניים לניצול נתונים דינמי.
- סוכנים: העצמת יישומים לבחור כלים מתאימים בהתבסס על הנחיות ברמה גבוהה, תוך שיפור יכולות קבלת ההחלטות.
- רשתות: מציע קומפוזיציות מוגדרות מראש לשימוש חוזר המשמשות כאבני בניין לפיתוח יישומים.
- זכרון: שומר על מצב יישום על פני מספר ביצועי שרשרת, חיוני לאינטראקציות מודעות להקשר.
כל מודול מכוון לצרכי פיתוח ספציפיים, מה שהופך את LangChain לערכת כלים מקיפה ליצירת יישומי מודל שפה מתקדמים.
יחד עם הרכיבים לעיל, יש לנו גם LangChain Expression Language (LCEL), שהיא דרך הצהרתית להרכיב בקלות מודולים יחד, וזו מאפשרת שרשור של רכיבים באמצעות ממשק Runnable אוניברסלי.
LCEL נראה בערך כך -
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import BaseOutputParser # Example chain
chain = ChatPromptTemplate() | ChatOpenAI() | CustomOutputParser()
כעת, לאחר שכיסינו את היסודות, נמשיך ל:
- חפרו עמוק יותר לתוך כל מודול Langchain בפירוט.
- למד כיצד להשתמש בשפת LangChain Expression.
- חקור מקרי שימוש נפוצים ויישם אותם.
- פרוס יישום מקצה לקצה עם LangServe.
- בדוק את LangSmith עבור איתור באגים, בדיקה וניטור.
בואו נתחיל!
מודול I: דגם I/O
ב-LangChain, מרכיב הליבה של כל אפליקציה סובב סביב מודל השפה. מודול זה מספק את אבני הבניין החיוניות להתממשקות יעילה עם כל מודל שפה, ומבטיח אינטגרציה ותקשורת חלקה.
רכיבי מפתח של מודל I/O
- LLMs ומודלים צ'אט (המשמשים לסירוגין):
- לימודי תואר שני:
- הַגדָרָה: מודלים של השלמת טקסט טהורים.
- פלט קלט: קח מחרוזת טקסט כקלט והחזר מחרוזת טקסט כפלט.
- דגמי צ'אט
- לימודי תואר שני:
- הַגדָרָה: מודלים המשתמשים במודל שפה כבסיס אך שונים בתבניות הקלט והפלט.
- פלט קלט: קבל רשימה של הודעות צ'אט כקלט והחזר הודעת צ'אט.
- הנחיות: עיצוב תבנית, בחירה דינמית וניהול קלט של מודלים. מאפשר יצירת הנחיות גמישות וספציפיות להקשר המנחות את התגובות של מודל השפה.
- מנתחי פלט: חלץ ועצב מידע מפלטי הדגם. שימושי להמרת הפלט הגולמי של מודלים של שפה לנתונים מובנים או פורמטים ספציפיים הדרושים לאפליקציה.
לימודי תואר שני
השילוב של LangChain עם מודלים של שפה גדולה (LLMs) כמו OpenAI, Cohere ו-Huging Face הוא היבט בסיסי של הפונקציונליות שלה. LangChain עצמה אינה מארחת LLMs אך מציעה ממשק אחיד לאינטראקציה עם LLMs שונים.
סעיף זה מספק סקירה כללית של השימוש בעטיפת OpenAI LLM ב-LangChain, החלה גם על סוגי LLM אחרים. כבר התקנו את זה בסעיף "תחילת העבודה". תן לנו לאתחל את ה-LLM.
from langchain.llms import OpenAI
llm = OpenAI()
- LLMs מיישמים את ממשק רץ, אבן הבניין הבסיסית של LangChain Expression Language (LCEL). זה אומר שהם תומכים
invoke
,ainvoke
,stream
,astream
,batch
,abatch
,astream_log
שיחות. - לימודי תואר שני מקבלים מחרוזות כקלט, או אובייקטים שניתן לאלץ אותם להודעות מחרוזת, כולל
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, טיפול בהנחיות יכול להיות תהליך יעיל מאוד, הודות למספר מחלקות ופונקציות ייעודיות.
של LangChain PromptTemplate
class הוא כלי רב תכליתי ליצירת הנחיות מחרוזות. הוא משתמש ב-Python's str.format
תחביר, המאפשר יצירת הנחיה דינמית. ניתן להגדיר תבנית עם מצייני מיקום ולמלא אותם בערכים ספציפיים לפי הצורך.
from langchain.prompts import PromptTemplate # Simple prompt with placeholders
prompt_template = PromptTemplate.from_template( "Tell me a {adjective} joke about {content}."
) # Filling placeholders to create a prompt
filled_prompt = prompt_template.format(adjective="funny", content="robots")
print(filled_prompt)
עבור מודלים של צ'אט, ההנחיות מובנות יותר, וכוללות הודעות עם תפקידים ספציפיים. LangChain מציעה ChatPromptTemplate
למטרה זו.
from langchain.prompts import ChatPromptTemplate # Defining a chat prompt with various roles
chat_template = ChatPromptTemplate.from_messages( [ ("system", "You are a helpful AI bot. Your name is {name}."), ("human", "Hello, how are you doing?"), ("ai", "I'm doing well, thanks!"), ("human", "{user_input}"), ]
) # Formatting the chat prompt
formatted_messages = chat_template.format_messages(name="Bob", user_input="What is your name?")
for message in formatted_messages: print(message)
גישה זו מאפשרת יצירת צ'אטבוטים אינטראקטיביים ומרתקים עם תגובות דינמיות.
שניהם PromptTemplate
ו ChatPromptTemplate
להשתלב בצורה חלקה עם שפת הביטוי LangChain (LCEL), המאפשרת להם להיות חלק מזרימות עבודה גדולות ומורכבות יותר. נדון יותר על כך בהמשך.
תבניות הנחיות מותאמות אישית הן לפעמים חיוניות למשימות הדורשות עיצוב ייחודי או הוראות ספציפיות. יצירת תבנית הנחיה מותאמת אישית כוללת הגדרת משתני קלט ושיטת עיצוב מותאמת אישית. גמישות זו מאפשרת ל-LangChain לתת מענה למגוון רחב של דרישות ספציפיות ליישום. קראו עוד כאן.
LangChain תומך גם בהנחיה של מספר יריות, מה שמאפשר למודל ללמוד מדוגמאות. תכונה זו חיונית למשימות הדורשות הבנה הקשרית או דפוסים ספציפיים. ניתן לבנות תבניות הנחיה של כמה תמונות מסט של דוגמאות או על ידי שימוש באובייקט בורר לדוגמה. קראו עוד כאן.
מנתחי פלט
מנתחי פלט ממלאים תפקיד מכריע ב-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 עבורך ועבור הצוותים שלך.
מודול II: אחזור
אחזור ב-LangChain ממלא תפקיד מכריע ביישומים הדורשים נתונים ספציפיים למשתמש, שאינם כלולים בערכת ההדרכה של המודל. תהליך זה, המכונה Retrieval Augmented Generation (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()
AmazonTextractPDFParser משתמש ב-AWS Textract עבור OCR ותכונות מתקדמות אחרות של ניתוח PDF.
from langchain.document_loaders import AmazonTextractPDFLoader # Requires AWS account and configuration
loader = AmazonTextractPDFLoader("example_data/complex-layout.pdf")
documents = loader.load()
PDFMinerPDFasHTMLLoader יוצר HTML מ-PDF לניתוח סמנטי.
from langchain.document_loaders import PDFMinerPDFasHTMLLoader loader = PDFMinerPDFasHTMLLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
PDFPlumberLoader מספק מטא נתונים מפורטים ותומך במסמך אחד בכל עמוד.
from langchain.document_loaders import PDFPlumberLoader loader = PDFPlumberLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
מעמיסים משולבים: LangChain מציעה מגוון רחב של מעמיסים מותאמים אישית לטעינה ישירה של נתונים מהאפליקציות שלך (כגון Slack, Sigma, Notion, Confluence, Google Drive ועוד רבים) וממסדי נתונים ולהשתמש בהם ביישומי LLM.
הרשימה המלאה היא כאן.
להלן כמה דוגמאות כדי להמחיש זאת -
דוגמה I – Slack
Slack, פלטפורמת הודעות מיידיות בשימוש נרחב, ניתנת לשילוב בתהליכי עבודה ויישומים של LLM.
- עבור לדף ניהול סביבת העבודה של Slack.
- נווט אל
{your_slack_domain}.slack.com/services/export
. - בחר את טווח התאריכים הרצוי והתחל את הייצוא.
- Slack מודיע באמצעות דואר אלקטרוני ו-DM ברגע שהייצוא מוכן.
- היצוא מביא ל- א
.zip
הקובץ הממוקם בתיקיית ההורדות או בנתיב ההורדה המיועד. - הקצה את הנתיב של ההורדה
.zip
הקובץ אלLOCAL_ZIPFILE
. - השתמש
SlackDirectoryLoader
מlangchain.document_loaders
חֲבִילָה.
from langchain.document_loaders import SlackDirectoryLoader SLACK_WORKSPACE_URL = "https://xxx.slack.com" # Replace with your Slack URL
LOCAL_ZIPFILE = "" # Path to the Slack zip file loader = SlackDirectoryLoader(LOCAL_ZIPFILE, SLACK_WORKSPACE_URL)
docs = loader.load()
print(docs)
דוגמה ב' - Figma
Figma, כלי פופולרי לעיצוב ממשק, מציע REST API לשילוב נתונים.
- השג את מפתח הקובץ Figma מפורמט כתובת האתר:
https://www.figma.com/file/{filekey}/sampleFilename
. - מזהי צומת נמצאים בפרמטר כתובת האתר
?node-id={node_id}
. - צור אסימון גישה לפי ההוראות ב- מרכז העזרה של Figma.
- השמיים
FigmaFileLoader
כיתה מlangchain.document_loaders.figma
משמש לטעינת נתוני Figma. - מודולים שונים של LangChain כמו
CharacterTextSplitter
,ChatOpenAI
, וכו', מועסקים לעיבוד.
import os
from langchain.document_loaders.figma import FigmaFileLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.chat_models import ChatOpenAI
from langchain.indexes import VectorstoreIndexCreator
from langchain.chains import ConversationChain, LLMChain
from langchain.memory import ConversationBufferWindowMemory
from langchain.prompts.chat import ChatPromptTemplate, SystemMessagePromptTemplate, AIMessagePromptTemplate, HumanMessagePromptTemplate figma_loader = FigmaFileLoader( os.environ.get("ACCESS_TOKEN"), os.environ.get("NODE_IDS"), os.environ.get("FILE_KEY"),
) index = VectorstoreIndexCreator().from_loaders([figma_loader])
figma_doc_retriever = index.vectorstore.as_retriever()
- השמיים
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 המכיל מידע על מודלים שונים של OCR ושליפת נתונים -
תן לנו להשתמש ב-AirtableLoader בשביל זה, שנמצא ברשימת המעמיסים המשולבים.
from langchain.document_loaders import AirtableLoader api_key = "XXXXX"
base_id = "XXXXX"
table_id = "XXXXX" loader = AirtableLoader(api_key, table_id, base_id)
airtabledocs = loader.load()
כעת נמשיך ונלמד כיצד להשתמש בשיעורי מסמכים אלה.
רובאי מסמכים
שנאי מסמכים ב-LangChain הם כלים חיוניים שנועדו לתפעל מסמכים, שיצרנו בתת-סעיף הקודם שלנו.
הם משמשים למשימות כמו פיצול מסמכים ארוכים לנתחים קטנים יותר, שילוב וסינון, שהם חיוניים להתאמת מסמכים לחלון ההקשר של המודל או לענות על צרכי יישום ספציפיים.
כלי אחד כזה הוא RecursiveCharacterTextSplitter, מפצל טקסט רב-תכליתי שמשתמש ברשימת תווים לפיצול. זה מאפשר פרמטרים כמו גודל נתח, חפיפה ואינדקס התחלתי. הנה דוגמה לאופן השימוש בו ב-Python:
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 ומפצל הקוד של JavaScript:
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 ו-Huging Face. מודלים אלה הופכים טקסט לייצוגים וקטוריים, ומאפשרים פעולות כמו חיפוש סמנטי באמצעות דמיון טקסט במרחב הווקטורי.
כדי להתחיל עם מודלים של הטבעת טקסט, אתה בדרך כלל צריך להתקין חבילות ספציפיות ולהגדיר מפתחות API. כבר עשינו זאת עבור OpenAI
ב-LangChain, ה embed_documents
השיטה משמשת להטמעת טקסטים מרובים, ומספקת רשימה של ייצוגים וקטוריים. לדוגמה:
from langchain.embeddings import OpenAIEmbeddings # Initialize the model
embeddings_model = OpenAIEmbeddings() # Embed a list of texts
embeddings = embeddings_model.embed_documents( ["Hi there!", "Oh, hello!", "What's your name?", "My friends call me World", "Hello World!"]
)
print("Number of documents embedded:", len(embeddings))
print("Dimension of each embedding:", len(embeddings[0]))
להטמעת טקסט בודד, כגון שאילתת חיפוש, ה- embed_query
נעשה שימוש בשיטה. זה שימושי להשוואת שאילתה לקבוצה של הטמעות מסמכים. לדוגמה:
from langchain.embeddings import OpenAIEmbeddings # Initialize the model
embeddings_model = OpenAIEmbeddings() # Embed a single query
embedded_query = embeddings_model.embed_query("What was the name mentioned in the conversation?")
print("First five dimensions of the embedded query:", embedded_query[:5])
הבנת ההטבעות הללו היא חיונית. כל פיסת טקסט מומרת לוקטור, שהמימד שלו תלוי במודל שבו נעשה שימוש. לדוגמה, מודלים של OpenAI מייצרים בדרך כלל וקטורים בעלי 1536 מימדים. ההטבעות הללו משמשות לאחר מכן לאחזור מידע רלוונטי.
פונקציונליות ההטמעה של LangChain אינה מוגבלת ל-OpenAI אלא מיועדת לעבוד עם ספקים שונים. ההגדרה והשימוש עשויים להשתנות מעט בהתאם לספק, אבל הרעיון המרכזי של הטבעת טקסטים במרחב וקטור נשאר זהה. לשימוש מפורט, כולל תצורות ואינטגרציות מתקדמות עם ספקי מודל הטמעה שונים, תיעוד LangChain בסעיף האינטגרציות הוא משאב רב ערך.
חנויות וקטור
חנויות וקטור ב-LangChain תומכות באחסון וחיפוש יעילים של הטבעות טקסט. LangChain משתלבת עם למעלה מ-50 חנויות וקטוריות, ומספקת ממשק סטנדרטי לקלות שימוש.
דוגמה: אחסון וחיפוש הטמעות
לאחר הטבעת טקסטים, נוכל לאחסן אותם בחנות וקטורית כמו Chroma
ובצע חיפושי דמיון:
from langchain.vectorstores import Chroma db = Chroma.from_texts(embedded_texts)
similar_texts = db.similarity_search("search query")
תן לנו לחילופין להשתמש בחנות הווקטורית של FAISS כדי ליצור אינדקסים עבור המסמכים שלנו.
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS pdfstore = FAISS.from_documents(pdfpages, embedding=OpenAIEmbeddings()) airtablestore = FAISS.from_documents(airtabledocs, embedding=OpenAIEmbeddings())
רטריברים
ריטריברים ב-LangChain הם ממשקים המחזירים מסמכים בתגובה לשאילתה לא מובנית. הן כלליות יותר מחנויות וקטוריות, ומתמקדות באחזור ולא באחסון. למרות שמאגרי וקטורים יכולים לשמש כעמוד השדרה של רטריבר, ישנם גם סוגים אחרים של רטריבר.
כדי להגדיר Chroma Retriver, תחילה תתקין אותו באמצעות pip install chromadb
. לאחר מכן, אתה טוען, מפצל, מטמיע ומחזיר מסמכים באמצעות סדרה של פקודות Python. הנה דוגמה לקוד להגדרת Chroma Retriver:
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma full_text = open("state_of_the_union.txt", "r").read()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
texts = text_splitter.split_text(full_text) embeddings = OpenAIEmbeddings()
db = Chroma.from_texts(texts, embeddings)
retriever = db.as_retriever() retrieved_docs = retriever.invoke("What did the president say about Ketanji Brown Jackson?")
print(retrieved_docs[0].page_content)
ה-MultiQueryRetriever הופך אוטומציה של כוונון מהיר על ידי יצירת שאילתות מרובות עבור שאילתת קלט משתמש ומשלב את התוצאות. הנה דוגמה לשימוש הפשוט שלו:
from langchain.chat_models import ChatOpenAI
from langchain.retrievers.multi_query import MultiQueryRetriever question = "What are the approaches to Task Decomposition?"
llm = ChatOpenAI(temperature=0)
retriever_from_llm = MultiQueryRetriever.from_llm( retriever=db.as_retriever(), llm=llm
) unique_docs = retriever_from_llm.get_relevant_documents(query=question)
print("Number of unique documents:", len(unique_docs))
דחיסה קונטקסטואלית ב-LangChain דוחסת מסמכים שאוחזרו תוך שימוש בהקשר של השאילתה, מה שמבטיח שרק מידע רלוונטי מוחזר. זה כולל הפחתת תוכן וסינון מסמכים פחות רלוונטיים. דוגמא הקוד הבאה מראה כיצד להשתמש ב-Contextual Compression Retriever:
from langchain.llms import OpenAI
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor llm = OpenAI(temperature=0)
compressor = LLMChainExtractor.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(base_compressor=compressor, base_retriever=retriever) compressed_docs = compression_retriever.get_relevant_documents("What did the president say about Ketanji Jackson Brown")
print(compressed_docs[0].page_content)
ה-EnsembleRetriever משלב אלגוריתמי אחזור שונים כדי להשיג ביצועים טובים יותר. דוגמה לשילוב BM25 ו-FAISS רטריברים מוצגת בקוד הבא:
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 הבא:
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 עבורך ועבור הצוותים שלך.
מודול III: סוכנים
LangChain מציגה קונספט רב עוצמה בשם "סוכנים" שלוקח את הרעיון של רשתות לרמה חדשה לגמרי. סוכנים ממנפים מודלים של שפה כדי לקבוע באופן דינמי רצפים של פעולות לביצוע, מה שהופך אותם למגוון להפליא ומסתגלים. בניגוד לרשתות מסורתיות, שבהן פעולות מקודדות בקוד, סוכנים משתמשים במודלים של שפה כמנועי חשיבה כדי להחליט אילו פעולות לנקוט ובאיזה סדר.
הסוכן הוא מרכיב הליבה האחראי על קבלת ההחלטות. הוא רותם את הכוח של מודל שפה והנחיה לקבוע את הצעדים הבאים להשגת מטרה ספציפית. התשומות לסוכן כוללות בדרך כלל:
- כלים: תיאורים של כלים זמינים (עוד על כך בהמשך).
- קלט משתמש: המטרה או השאילתה ברמה גבוהה מהמשתמש.
- שלבי ביניים: היסטוריה של זוגות (פעולה, פלט כלי) שבוצעו כדי להגיע לקלט המשתמש הנוכחי.
הפלט של סוכן יכול להיות הבא פעולה לנקוט בפעולות (Agent Actions) או הגמר תגובה לשלוח למשתמש (AgentFinish). א פעולה מציין א כלי ו קלט עבור הכלי הזה.
כלים
כלים הם ממשקים שסוכן יכול להשתמש בהם כדי ליצור אינטראקציה עם העולם. הם מאפשרים לסוכנים לבצע משימות שונות, כגון חיפוש באינטרנט, הפעלת פקודות מעטפת או גישה לממשקי API חיצוניים. ב-LangChain, כלים חיוניים להרחבת היכולות של סוכנים ולאפשר להם לבצע משימות מגוונות.
כדי להשתמש בכלים ב-LangChain, אתה יכול לטעון אותם באמצעות הקטע הבא:
from langchain.agents import load_tools tool_names = [...]
tools = load_tools(tool_names)
כלים מסוימים עשויים לדרוש מודל שפה בסיסי (LLM) כדי לאתחל. במקרים כאלה, אתה יכול לעבור גם LLM:
from langchain.agents import load_tools tool_names = [...]
llm = ...
tools = load_tools(tool_names, llm=llm)
הגדרה זו מאפשרת לך לגשת למגוון כלים ולשלב אותם בזרימות העבודה של הסוכן שלך. הרשימה המלאה של כלים עם תיעוד שימוש היא כאן.
הבה נסתכל על כמה דוגמאות של כלים.
DuckDuckGo
הכלי DuckDuckGo מאפשר לך לבצע חיפושים באינטרנט באמצעות מנוע החיפוש שלו. הנה איך להשתמש בו:
from langchain.tools import DuckDuckGoSearchRun
search = DuckDuckGoSearchRun()
search.run("manchester united vs luton town match summary")
DataForSeo
ערכת הכלים של DataForSeo מאפשרת לך להשיג תוצאות של מנוע החיפוש באמצעות ה-API של DataForSeo. כדי להשתמש בערכת כלים זו, תצטרך להגדיר את אישורי ה-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 על ידי ציון סוגי תוצאות, שדות והגבלת מספר התוצאות.
תוכל גם לציין את המיקום והשפה עבור תוצאות החיפוש שלך על ידי העברת פרמטרים נוספים למעטפת ה-API:
customized_wrapper = DataForSeoAPIWrapper( top_count=10, json_result_types=["organic", "local_pack"], json_result_fields=["title", "description", "type"], params={"location_name": "Germany", "language_code": "en"},
) customized_result = customized_wrapper.results("coffee near me")
על ידי מתן פרמטרים של מיקום ושפה, תוכל להתאים את תוצאות החיפוש שלך לאזורים ולשפות ספציפיים.
יש לך את הגמישות לבחור את מנוע החיפוש שבו אתה רוצה להשתמש. כל שעליך לעשות הוא לציין את מנוע החיפוש הרצוי:
customized_wrapper = DataForSeoAPIWrapper( top_count=10, json_result_types=["organic", "local_pack"], json_result_fields=["title", "description", "type"], params={"location_name": "Germany", "language_code": "en", "se_name": "bing"},
) customized_result = customized_wrapper.results("coffee near me")
בדוגמה זו, החיפוש מותאם אישית לשימוש ב-Bing כמנוע החיפוש.
עטיפת ה-API מאפשרת לך גם לציין את סוג החיפוש שברצונך לבצע. לדוגמה, אתה יכול לבצע חיפוש במפות:
maps_search = DataForSeoAPIWrapper( top_count=10, json_result_fields=["title", "value", "address", "rating", "type"], params={ "location_coordinate": "52.512,13.36,12z", "language_code": "en", "se_type": "maps", },
) maps_search_result = maps_search.results("coffee near me")
פעולה זו מתאימה אישית את החיפוש כדי לאחזר מידע הקשור למפות.
מעטפת (באש)
ערכת הכלים של Shell מספקת לסוכנים גישה לסביבת המעטפת, ומאפשרת להם לבצע פקודות מעטפת. תכונה זו חזקה אך יש להשתמש בה בזהירות, במיוחד בסביבות עם ארגז חול. כך תוכל להשתמש בכלי Shell:
from langchain.tools import ShellTool shell_tool = ShellTool() result = shell_tool.run({"commands": ["echo 'Hello World!'", "time"]})
בדוגמה זו, הכלי Shell מריץ שתי פקודות מעטפת: מהדהד "Hello World!" והצגת השעה הנוכחית.
אתה יכול לספק את הכלי Shell לסוכן כדי לבצע משימות מורכבות יותר. הנה דוגמה לסוכן שמביא קישורים מדף אינטרנט באמצעות הכלי Shell:
from langchain.agents import AgentType, initialize_agent
from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(temperature=0.1) shell_tool.description = shell_tool.description + f"args {shell_tool.args}".replace( "{", "{{"
).replace("}", "}}")
self_ask_with_search = initialize_agent( [shell_tool], llm, agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)
self_ask_with_search.run( "Download the langchain.com webpage and grep for all urls. Return only a sorted list of them. Be sure to use double quotes."
)
בתרחיש זה, הסוכן משתמש בכלי Shell כדי לבצע רצף של פקודות כדי לאחזר, לסנן ולמיין כתובות URL מדף אינטרנט.
הדוגמאות שסופקו מדגימות כמה מהכלים הזמינים ב-LangChain. כלים אלה בסופו של דבר מרחיבים את היכולות של סוכנים (שנבדקו בסעיף המשנה הבא) ומעצימים אותם לבצע משימות שונות ביעילות. בהתאם לדרישות שלך, אתה יכול לבחור את הכלים וערכות הכלים המתאימים ביותר לצרכי הפרויקט שלך ולשלב אותם בזרימות העבודה של הסוכן שלך.
חזרה לסוכנים
בוא נעבור לסוכנים עכשיו.
AgentExecutor היא סביבת זמן הריצה של סוכן. היא אחראית להתקשר לסוכן, לבצע את הפעולות שהוא בוחר, להעביר את פלטי הפעולה בחזרה לסוכן ולחזור על התהליך עד שהסוכן מסיים. בפסאודוקוד, ה- AgentExecutor עשוי להיראות בערך כך:
next_action = agent.get_action(...)
while next_action != AgentFinish: observation = run(next_action) next_action = agent.get_action(..., next_action, observation)
return next_action
ה- AgentExecutor מטפל במורכבויות שונות, כגון טיפול במקרים בהם הסוכן בוחר בכלי שאינו קיים, טיפול בטעויות בכלים, ניהול פלטים שיוצרו על ידי סוכן ומתן רישום וצפייה בכל הרמות.
בעוד שמחלקת AgentExecutor היא זמן הריצה העיקרי של הסוכן ב-LangChain, יש זמני ריצה אחרים, ניסיוניים יותר נתמכים, כולל:
- סוכן תכנון וביצוע
- בייבי AGI
- GPT אוטומטי
כדי לקבל הבנה טובה יותר של מסגרת הסוכן, בואו נבנה סוכן בסיסי מאפס, ולאחר מכן נמשיך לחקור סוכנים שנבנו מראש.
לפני שאנחנו צוללים לתוך בניית הסוכן, חיוני לעיין מחדש בכמה מינוחים וסכימה מרכזיים:
- AgentAction: זוהי מחלקת נתונים המייצגת את הפעולה שעל סוכן לבצע. הוא מורכב מא
tool
מאפיין (שם הכלי להפעלתו) ואtool_input
מאפיין (הקלט עבור הכלי הזה). - AgentFinish: מחלקת נתונים זו מציינת שהסוכן סיים את משימתו ועליו להחזיר תגובה למשתמש. הוא כולל בדרך כלל מילון של ערכי החזרה, לרוב עם "פלט" מפתח המכיל את טקסט התגובה.
- שלבי ביניים: אלו הם הרשומות של פעולות סוכן קודמות והפלטים התואמים. הם חיוניים להעברת הקשר לאיטרציות עתידיות של הסוכן.
בדוגמה שלנו, נשתמש ב-OpenAI Function Calling כדי ליצור את הסוכן שלנו. גישה זו אמינה ליצירת סוכן. נתחיל ביצירת כלי פשוט שמחשב את אורך המילה. כלי זה שימושי מכיוון שמודלים של שפה יכולים לפעמים לעשות טעויות עקב אסימון בעת ספירת אורכי מילים.
ראשית, בואו נטען את מודל השפה שבו נשתמש כדי לשלוט בסוכן:
from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
בואו נבדוק את המודל עם חישוב אורך מילה:
llm.invoke("how many letters in the word educa?")
התגובה צריכה לציין את מספר האותיות במילה "educa".
לאחר מכן, נגדיר פונקציית Python פשוטה לחישוב אורך מילה:
from langchain.agents import tool @tool
def get_word_length(word: str) -> int: """Returns the length of a word.""" return len(word)
יצרנו כלי בשם get_word_length
שלוקח מילה כקלט ומחזיר את אורכה.
כעת, בואו ניצור את ההנחיה עבור הסוכן. ההנחיה מורה לסוכן כיצד לנמק ולעצב את הפלט. במקרה שלנו, אנו משתמשים ב-OpenAI Function Calling, הדורש הוראות מינימליות. נגדיר את ההנחיה עם מצייני מיקום עבור קלט משתמש ופנקס סוכן:
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder prompt = ChatPromptTemplate.from_messages( [ ( "system", "You are a very powerful assistant but not great at calculating word lengths.", ), ("user", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]
)
עכשיו, איך הסוכן יודע באילו כלים הוא יכול להשתמש? אנו מסתמכים על מודלים של שפות קורא לפונקציות OpenAI, הדורשות העברת פונקציות בנפרד. כדי לספק את הכלים שלנו לסוכן, אנו נעצב אותם כקריאות לפונקציות OpenAI:
from langchain.tools.render import format_tool_to_openai_function llm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools])
כעת, נוכל ליצור את הסוכן על ידי הגדרת מיפויי קלט וחיבור הרכיבים:
זוהי שפת LCEL. נדון בכך בהמשך בהרחבה.
from langchain.agents.format_scratchpad import format_to_openai_function_messages
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai _function_messages( x["intermediate_steps"] ), } | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser()
)
יצרנו את הסוכן שלנו, שמבין את קלט המשתמש, משתמש בכלים זמינים ופורמט פלט. עכשיו, בואו נתקשר איתו:
agent.invoke({"input": "how many letters in the word educa?", "intermediate_steps": []})
הסוכן צריך להגיב עם AgentAction, המציין את הפעולה הבאה שיש לנקוט.
יצרנו את הסוכן, אבל עכשיו אנחנו צריכים לכתוב לו זמן ריצה. זמן הריצה הפשוט ביותר הוא זה שמתקשר ברציפות לסוכן, מבצע פעולות וחוזר על עצמו עד שהסוכן מסיים. הנה דוגמה:
from langchain.schema.agent import AgentFinish user_input = "how many letters in the word educa?"
intermediate_steps = [] while True: output = agent.invoke( { "input": user_input, "intermediate_steps": intermediate_steps, } ) if isinstance(output, AgentFinish): final_result = output.return_values["output"] break else: print(f"TOOL NAME: {output.tool}") print(f"TOOL INPUT: {output.tool_input}") tool = {"get_word_length": get_word_length}[output.tool] observation = tool.run(output.tool_input) intermediate_steps.append((output, observation)) print(final_result)
בלולאה זו, אנו מתקשרים שוב ושוב לסוכן, מבצעים פעולות ומעדכנים את שלבי הביניים עד שהסוכן מסיים. אנחנו גם מטפלים באינטראקציות עם כלים בתוך הלולאה.
כדי לפשט את התהליך הזה, LangChain מספקת את מחלקת AgentExecutor, המקופלת את ביצוע הסוכן ומציעה טיפול בשגיאות, עצירה מוקדמת, מעקב ושיפורים אחרים. בואו נשתמש ב- AgentExecutor כדי ליצור אינטראקציה עם הסוכן:
from langchain.agents import AgentExecutor agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) agent_executor.invoke({"input": "how many letters in the word educa?"})
AgentExecutor מפשט את תהליך הביצוע ומספק דרך נוחה ליצור אינטראקציה עם הסוכן.
זיכרון נדון בפירוט גם בהמשך.
הסוכן שיצרנו עד כה הוא חסר מדינה, כלומר אינו זוכר אינטראקציות קודמות. כדי לאפשר שאלות ושיחות המשך, עלינו להוסיף זיכרון לסוכן. זה כולל שני שלבים:
- הוסף משתנה זיכרון בהנחיה לאחסון היסטוריית הצ'אט.
- עקוב אחר היסטוריית הצ'אט במהלך אינטראקציות.
נתחיל בהוספת מציין זיכרון בפקודה:
from langchain.prompts import MessagesPlaceholder MEMORY_KEY = "chat_history"
prompt = ChatPromptTemplate.from_messages( [ ( "system", "You are a very powerful assistant but not great at calculating word lengths.", ), MessagesPlaceholder(variable_name=MEMORY_KEY), ("user", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]
)
כעת, צור רשימה כדי לעקוב אחר היסטוריית הצ'אט:
from langchain.schema.messages import HumanMessage, AIMessage chat_history = []
בשלב יצירת הסוכן, נכלול גם את הזיכרון:
agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai_function_messages( x["intermediate_steps"] ), "chat_history": lambda x: x["chat_history"], } | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser()
)
כעת, בעת הפעלת הסוכן, הקפד לעדכן את היסטוריית הצ'אט:
input1 = "how many letters in the word educa?"
result = agent_executor.invoke({"input": input1, "chat_history": chat_history})
chat_history.extend([ HumanMessage(content=input1), AIMessage(content=result["output"]),
])
agent_executor.invoke({"input": "is that a real word?", "chat_history": chat_history})
זה מאפשר לסוכן לשמור על היסטוריית שיחות ולענות על שאלות המשך המבוססות על אינטראקציות קודמות.
מזל טוב! יצרת וביצעת בהצלחה את הסוכן הראשון שלך מקצה לקצה ב-LangChain. כדי להעמיק ביכולות של LangChain, אתה יכול לחקור:
- סוגי סוכנים שונים נתמכים.
- סוכנים בנויים מראש
- כיצד לעבוד עם כלים ושילובי כלים.
סוגי סוכנים
LangChain מציעה סוגי סוכנים שונים, כל אחד מתאים למקרי שימוש ספציפיים. להלן כמה מהסוכנים הזמינים:
- Zero-shot React: סוכן זה משתמש במסגרת ReAct כדי לבחור כלים על סמך התיאורים שלהם בלבד. זה דורש תיאורים עבור כל כלי והוא רב תכליתי.
- ReAct קלט מובנה: סוכן זה מטפל בכלי ריבוי קלט ומתאים למשימות מורכבות כמו ניווט בדפדפן אינטרנט. הוא משתמש בסכימת ארגומנטים של כלים עבור קלט מובנה.
- פונקציות OpenAI: סוכן זה תוכנן במיוחד עבור דגמים שהותאמו לקריאת פונקציות, והוא תואם לדגמים כמו gpt-3.5-turbo-0613 ו-gpt-4-0613. השתמשנו בזה כדי ליצור את הסוכן הראשון שלנו למעלה.
- שיחה: עוצב עבור הגדרות שיחה, סוכן זה משתמש ב-ReAct לבחירת כלים ומנצל את הזיכרון כדי לזכור אינטראקציות קודמות.
- שאל עצמי עם חיפוש: סוכן זה מסתמך על כלי יחיד, "תשובה ביניים", אשר מחפש תשובות עובדתיות לשאלות. זה שווה ערך לשאלה העצמית המקורית עם נייר חיפוש.
- חנות מסמכים של ReAct: סוכן זה מקיים אינטראקציה עם מאגר מסמכים באמצעות מסגרת ReAct. זה דורש כלים "חיפוש" ו-"חיפוש" והוא דומה לדוגמא המקורית של מאמר ReAct בוויקיפדיה.
חקור סוגי סוכנים אלה כדי למצוא את הגורם המתאים ביותר לצרכים שלך ב-LangChain. סוכנים אלה מאפשרים לך לאגד בתוכם סט כלים לטיפול בפעולות ויצירת תגובות. למידע נוסף על איך לבנות סוכן משלך עם כלים כאן.
סוכנים שנבנו מראש
בואו נמשיך בחיפוש אחר סוכנים, תוך התמקדות בסוכנים שנבנו מראש הזמינים ב-LangChain.
gmail
LangChain מציעה ערכת כלים של Gmail המאפשרת לך לחבר את האימייל של LangChain ל-Gmail API. כדי להתחיל, תצטרך להגדיר את האישורים שלך, המוסברים בתיעוד 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 שלך, במיוחד אם הוא מכיל מיליוני שורות.
- מסדי נתונים מוכווני מחסני נתונים תומכים לרוב במכסות ברמת המשתמש כדי להגביל את השימוש במשאבים.
אתה יכול לבקש מהסוכן לתאר טבלה, כגון טבלת "רצועת הפלייליסט". הנה דוגמה כיצד לעשות זאת:
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 האמנים הנמכרים ביותר.
סוכן DataFrame Pandas
סעיף זה מציג סוכן שנועד ליצור אינטראקציה עם 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, המאפשרת לסוכנים ליצור אינטראקציה עם מופע של Jira. אתה יכול לבצע פעולות שונות כגון חיפוש בעיות ויצירת בעיות באמצעות ערכת כלים זו. הוא משתמש בספריית atlassian-python-api. כדי להשתמש בערכת כלים זו, עליך להגדיר משתני סביבה עבור מופע Jira שלך, כולל JIRA_API_TOKEN, JIRA_USERNAME ו-JIRA_INSTANCE_URL. בנוסף, ייתכן שיהיה עליך להגדיר את מפתח ה-API של OpenAI כמשתנה סביבה.
כדי להתחיל, התקן את ספריית 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 עבורך ועבור הצוותים שלך.
מודול IV: שרשראות
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 יכולות להיות מצביות גם על ידי שילוב של אובייקט Memory. זה מאפשר התמדה של נתונים לאורך שיחות, כפי שמוצג בדוגמה זו:
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory conversation = ConversationChain(llm=chat, memory=ConversationBufferMemory())
conversation.run("Answer briefly. What are the first 3 colors of a rainbow?")
conversation.run("And the next 4?")
LangChain תומך גם באינטגרציה עם ממשקי ה-API של OpenAI קורא פונקציות, דבר שימושי להשגת פלטים מובנים וביצוע פונקציות בתוך שרשרת. לקבלת פלטים מובנים, אתה יכול לציין אותם באמצעות מחלקות Pydantic או JsonSchema, כפי שמוצג להלן:
from langchain.pydantic_v1 import BaseModel, Field
from langchain.chains.openai_functions import create_structured_output_runnable
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate class Person(BaseModel): name: str = Field(..., description="The person's name") age: int = Field(..., description="The person's age") fav_food: Optional[str] = Field(None, description="The person's favorite food") llm = ChatOpenAI(model="gpt-4", temperature=0)
prompt = ChatPromptTemplate.from_messages([ # Prompt messages here
]) runnable = create_structured_output_runnable(Person, llm, prompt)
runnable.invoke({"input": "Sally is 13"})
לתפוקות מובנות, זמינה גם גישה מדור קודם באמצעות LLMChain:
from langchain.chains.openai_functions import create_structured_output_chain class Person(BaseModel): name: str = Field(..., description="The person's name") age: int = Field(..., description="The person's age") chain = create_structured_output_chain(Person, llm, prompt, verbose=True)
chain.run("Sally is 13")
LangChain ממנפת פונקציות OpenAI ליצירת רשתות ספציפיות שונות למטרות שונות. אלה כוללים שרשראות לחילוץ, תיוג, OpenAPI ו-QA עם ציטוטים.
בהקשר של מיצוי, התהליך דומה לשרשרת הפלט המובנית אך מתמקד במיצוי מידע או ישות. לתיוג, הרעיון הוא לתייג מסמך עם כיתות כגון סנטימנט, שפה, סגנון, נושאים מכוסים או נטייה פוליטית.
ניתן להדגים דוגמה כיצד תיוג עובד ב-LangChain באמצעות קוד 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)
ניתן להשתמש בסכמות פיידנטיות גם להגדרת קריטריוני תיוג, המספקות דרך פייתונית לציון מאפיינים וסוגים נדרשים:
from enum import Enum
from pydantic import BaseModel, Field class Tags(BaseModel): # Class fields here chain = create_tagging_chain_pydantic(Tags, llm)
בנוסף, ניתן להשתמש בשנאי מסמכי תיוג המטא-נתונים של LangChain כדי לחלץ מטא-נתונים מ-LangChain Documents, המציע פונקציונליות דומה לשרשרת התיוג אך מיושם על מסמך 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 עדיין מתועדת בשל תאימותה לאחור.
כדי להמחיש זאת, הבה נשקול תרחיש שבו אנו יוצרים תחילה תקציר מחזה ולאחר מכן סקירה המבוססת על תקציר זה. משתמש ב-Python's 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
באמצעות LCEL:
from functools import partial
from langchain.chains.combine_documents import collapse_docs, split_list_of_docs
from langchain.schema import Document, StrOutputParser
from langchain.schema.prompt_template import format_document
from langchain.schema.runnable import RunnableParallel, RunnablePassthrough llm = ChatAnthropic()
document_prompt = PromptTemplate.from_template("{page_content}")
partial_format_document = partial(format_document, prompt=document_prompt) map_chain = ( {"context": partial_format_document} | PromptTemplate.from_template("Summarize this content:nn{context}") | llm | StrOutputParser()
) map_as_doc_chain = ( RunnableParallel({"doc": RunnablePassthrough(), "content": map_chain}) | (lambda x: Document(page_content=x["content"], metadata=x["doc"].metadata))
).with_config(run_name="Summarize (return doc)") def format_docs(docs): return "nn".join(partial_format_document(doc) for doc in docs) collapse_chain = ( {"context": format_docs} | PromptTemplate.from_template("Collapse this content:nn{context}") | llm | StrOutputParser()
) reduce_chain = ( {"context": format_docs} | PromptTemplate.from_template("Combine these summaries:nn{context}") | llm | StrOutputParser()
).with_config(run_name="Reduce") map_reduce = (map_as_doc_chain.map() | collapse | reduce_chain).with_config(run_name="Map reduce")
תצורה זו מאפשרת ניתוח מפורט ומקיף של תוכן המסמך, תוך מינוף נקודות החוזק של LCEL ומודל השפה הבסיסי.
הפוך משימות וזרימות עבודה ידניות לאוטומטיות עם בונה זרימת העבודה המונעת בינה מלאכותית שלנו, שתוכנן על ידי Nanonets עבורך ועבור הצוותים שלך.
מודול V: זיכרון
ב-LangChain, זיכרון הוא היבט בסיסי של ממשקי שיחה, המאפשר למערכות להתייחס לאינטראקציות בעבר. זה מושג באמצעות אחסון ושאילתה של מידע, עם שתי פעולות עיקריות: קריאה וכתיבה. מערכת הזיכרון מקיימת אינטראקציה עם שרשרת פעמיים במהלך הריצה, מגדילה את כניסות המשתמש ומאחסנת את הכניסות והיציאות לעיון עתידי.
בניית זיכרון למערכת
- אחסון הודעות צ'אט: מודול הזיכרון LangChain משלב שיטות שונות לאחסון הודעות צ'אט, החל מרשימות בזיכרון ועד לבסיסי נתונים. זה מבטיח שכל אינטראקציות הצ'אט מתועדות לעיון עתידי.
- שאילתת הודעות צ'אט: מעבר לאחסון הודעות צ'אט, LangChain משתמשת במבני נתונים ואלגוריתמים כדי ליצור תצוגה שימושית של הודעות אלו. מערכות זיכרון פשוטות עשויות להחזיר הודעות אחרונות, בעוד שמערכות מתקדמות יותר יכולות לסכם אינטראקציות מהעבר או להתמקד בישויות המוזכרות באינטראקציה הנוכחית.
כדי להדגים את השימוש בזיכרון ב-LangChain, שקול את ConversationBufferMemory
class, טופס זיכרון פשוט המאחסן הודעות צ'אט במאגר. הנה דוגמה:
from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory()
memory.chat_memory.add_user_message("Hello!")
memory.chat_memory.add_ai_message("How can I assist you?")
בעת שילוב זיכרון בשרשרת, חשוב להבין את המשתנים המוחזרים מהזיכרון וכיצד הם משמשים בשרשרת. למשל, ה load_memory_variables
השיטה עוזרת ליישר את המשתנים הנקראים מהזיכרון עם הציפיות של השרשרת.
דוגמה מקצה לקצה עם LangChain
שקול להשתמש ConversationBufferMemory
בתוך LLMChain
. השרשרת, בשילוב עם תבנית הנחיה מתאימה והזיכרון, מספקת חווית שיחה חלקה. הנה דוגמה פשוטה:
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory llm = OpenAI(temperature=0)
template = "Your conversation template here..."
prompt = PromptTemplate.from_template(template)
memory = ConversationBufferMemory(memory_key="chat_history")
conversation = LLMChain(llm=llm, prompt=prompt, memory=memory) response = conversation({"question": "What's the weather like?"})
דוגמה זו ממחישה כיצד מערכת הזיכרון של LangChain משתלבת עם השרשראות שלה כדי לספק חווית שיחה קוהרנטית ומודעת להקשר.
סוגי זיכרון ב-Langchain
Langchain מציעה סוגי זיכרון שונים שניתן להשתמש בהם כדי לשפר את האינטראקציות עם דגמי הבינה המלאכותית. לכל סוג זיכרון יש פרמטרים וסוגי החזרה משלו, מה שהופך אותם למתאימים לתרחישים שונים. בואו נחקור כמה מסוגי הזיכרון הזמינים ב-Langchain יחד עם דוגמאות קוד.
1. זיכרון מאגר שיחה
סוג זיכרון זה מאפשר לך לאחסן ולחלץ הודעות משיחות. אתה יכול לחלץ את ההיסטוריה כמחרוזת או כרשימה של הודעות.
from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory()
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.load_memory_variables({}) # Extract history as a string
{'history': 'Human: hinAI: whats up'} # Extract history as a list of messages
{'history': [HumanMessage(content='hi', additional_kwargs={}), AIMessage(content='whats up', additional_kwargs={})]}
אתה יכול גם להשתמש בזיכרון מאגר שיחה בשרשרת לאינטראקציות דמויות צ'אט.
2. זיכרון חלון מאגר שיחה
סוג זיכרון זה שומר רשימה של אינטראקציות אחרונות ומשתמש באינטראקציות K האחרונות, ומונע מהמאגר להיות גדול מדי.
from langchain.memory import ConversationBufferWindowMemory memory = ConversationBufferWindowMemory(k=1)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context({"input": "not much you"}, {"output": "not much"})
memory.load_memory_variables({}) {'history': 'Human: not much younAI: not much'}
כמו זיכרון מאגר שיחה, אתה יכול גם להשתמש בסוג זיכרון זה בשרשרת לאינטראקציות דמויות צ'אט.
3. זיכרון ישות שיחה
סוג זיכרון זה זוכר עובדות על ישויות ספציפיות בשיחה ומחלץ מידע באמצעות LLM.
from langchain.memory import ConversationEntityMemory
from langchain.llms import OpenAI llm = OpenAI(temperature=0)
memory = ConversationEntityMemory(llm=llm)
_input = {"input": "Deven & Sam are working on a hackathon project"}
memory.load_memory_variables(_input)
memory.save_context( _input, {"output": " That sounds like a great project! What kind of project are they working on?"}
)
memory.load_memory_variables({"input": 'who is Sam'}) {'history': 'Human: Deven & Sam are working on a hackathon projectnAI: That sounds like a great project! What kind of project are they working on?', 'entities': {'Sam': 'Sam is working on a hackathon project with Deven.'}}
4. זיכרון גרף ידע שיחות
סוג זיכרון זה משתמש בגרף ידע כדי ליצור מחדש זיכרון. אתה יכול לחלץ ישויות נוכחיות ושלישיות ידע מהודעות.
from langchain.memory import ConversationKGMemory
from langchain.llms import OpenAI llm = OpenAI(temperature=0)
memory = ConversationKGMemory(llm=llm)
memory.save_context({"input": "say hi to sam"}, {"output": "who is sam"})
memory.save_context({"input": "sam is a friend"}, {"output": "okay"})
memory.load_memory_variables({"input": "who is sam"}) {'history': 'On Sam: Sam is friend.'}
אתה יכול גם להשתמש בסוג זיכרון זה בשרשרת לאחזור ידע מבוסס שיחה.
5. זיכרון סיכום שיחה
סוג זיכרון זה יוצר סיכום של השיחה לאורך זמן, שימושי לעיבוי מידע משיחות ארוכות יותר.
from langchain.memory import ConversationSummaryMemory
from langchain.llms import OpenAI llm = OpenAI(temperature=0)
memory = ConversationSummaryMemory(llm=llm)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.load_memory_variables({}) {'history': 'nThe human greets the AI, to which the AI responds.'}
6. זיכרון מאגר סיכום שיחה
סוג זיכרון זה משלב את סיכום השיחה והמאגר, שומר על איזון בין אינטראקציות אחרונות לסיכום. הוא משתמש באורך אסימון כדי לקבוע מתי לשטוף אינטראקציות.
from langchain.memory import ConversationSummaryBufferMemory
from langchain.llms import OpenAI llm = OpenAI()
memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=10)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context({"input": "not much you"}, {"output": "not much"})
memory.load_memory_variables({}) {'history': 'System: nThe human says "hi", and the AI responds with "whats up".nHuman: not much younAI: not much'}
אתה יכול להשתמש בסוגי זיכרון אלה כדי לשפר את האינטראקציות שלך עם מודלים של AI ב-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 מספקים דרכים שונות לנהל ולאחזר מידע משיחות, תוך שיפור היכולות של מודלים של AI בהבנה ותגובה לשאילתות המשתמש והקשרם. ניתן לבחור כל סוג זיכרון בהתבסס על הדרישות הספציפיות של האפליקציה שלך.
כעת נלמד כיצד להשתמש בזיכרון עם 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 מספקת אסימונים ממודל שפה למנתח פלט בזמן אמת, ומשפרת את ההיענות והיעילות.
- ממשקי API רב-תכליתיים: LCEL תומך בממשקי API סינכרוניים וגם לא-סינכרוניים עבור יצירת אב טיפוס וייצור, ומטפל ביעילות במספר בקשות.
- מקביל אוטומטי: LCEL מייעל ביצוע מקביל במידת האפשר, ומפחית את זמן ההשהיה בממשקי הסנכרון והאסינכרון כאחד.
- תצורות אמינות: הגדר ניסיונות חוזרים ונפילות לאמינות שרשרת משופרת בקנה מידה, עם תמיכה בסטרימינג בפיתוח.
- זרם תוצאות ביניים: גש לתוצאות ביניים במהלך העיבוד למטרות עדכוני משתמשים או ניפוי באגים.
- יצירת סכימה: LCEL מייצר סכימות Pydantic ו-JSONSchema לאימות קלט ופלט.
- מעקב מקיף: LangSmith עוקב אוטומטית אחר כל השלבים בשרשרות מורכבות לצורך צפייה וניפוי באגים.
- פריסה קלה: פרוס רשתות שנוצרו על ידי LCEL ללא מאמץ באמצעות LangServe.
כעת, בואו נצלול לדוגמאות קוד מעשיות המדגימות את הכוח של LCEL. נחקור משימות ותרחישים נפוצים שבהם LCEL זורח.
הנחיה + LLM
ההרכב הבסיסי ביותר כולל שילוב של הנחיה ומודל שפה כדי ליצור שרשרת שלוקחת קלט של המשתמש, מוסיפה אותו להנחיה, מעבירה אותו למודל ומחזירה את פלט המודל הגולמי. הנה דוגמה:
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI prompt = ChatPromptTemplate.from_template("tell me a joke about {foo}")
model = ChatOpenAI()
chain = prompt | model result = chain.invoke({"foo": "bears"})
print(result)
בדוגמה זו, השרשרת מייצרת בדיחה על דובים.
אתה יכול לצרף רצפי עצירה לשרשרת שלך כדי לשלוט כיצד היא מעבדת טקסט. לדוגמה:
chain = prompt | model.bind(stop=["n"])
result = chain.invoke({"foo": "bears"})
print(result)
תצורה זו מפסיקה את יצירת הטקסט כאשר תופס קו חדש.
LCEL תומך בצירוף מידע קריאת פונקציה לשרשרת שלך. הנה דוגמה:
functions = [ { "name": "joke", "description": "A joke", "parameters": { "type": "object", "properties": { "setup": {"type": "string", "description": "The setup for the joke"}, "punchline": { "type": "string", "description": "The punchline for the joke", }, }, "required": ["setup", "punchline"], }, }
]
chain = prompt | model.bind(function_call={"name": "joke"}, functions=functions)
result = chain.invoke({"foo": "bears"}, config={})
print(result)
דוגמה זו מצרף מידע על קריאת פונקציה כדי ליצור בדיחה.
הנחיה + LLM + OutputParser
אתה יכול להוסיף מנתח פלט כדי להפוך את פלט המודל הגולמי לפורמט נוח יותר. כך תוכל לעשות זאת:
from langchain.schema.output_parser import StrOutputParser chain = prompt | model | StrOutputParser()
result = chain.invoke({"foo": "bears"})
print(result)
הפלט כעת בפורמט מחרוזת, שהוא נוח יותר למשימות במורד הזרם.
כאשר מציינים פונקציה להחזיר, ניתן לנתח אותה ישירות באמצעות LCEL. לדוגמה:
from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser chain = ( prompt | model.bind(function_call={"name": "joke"}, functions=functions) | JsonOutputFunctionsParser()
)
result = chain.invoke({"foo": "bears"})
print(result)
דוגמה זו מנתחת את הפלט של הפונקציה "בדיחה" ישירות.
אלו הן רק כמה דוגמאות לאופן שבו LCEL מפשט משימות עיבוד שפה מורכבות. בין אם אתה בונה צ'אטבוטים, מייצר תוכן או מבצע טרנספורמציות מורכבות של טקסט, LCEL יכול לייעל את זרימת העבודה שלך ולהפוך את הקוד שלך לתחזוקה יותר.
RAG (דור מוגבר של אחזור)
ניתן להשתמש ב-LCEL ליצירת שרשראות דור מוגדלות באחזור, המשלבות שלבי אחזור ויצירת שפה. הנה דוגמה:
from operator import itemgetter from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough, RunnableLambda
from langchain.vectorstores import FAISS # Create a vector store and retriever
vectorstore = FAISS.from_texts( ["harrison worked at kensho"], embedding=OpenAIEmbeddings()
)
retriever = vectorstore.as_retriever() # Define templates for prompts
template = """Answer the question based only on the following context:
{context} Question: {question} """
prompt = ChatPromptTemplate.from_template(template) model = ChatOpenAI() # Create a retrieval-augmented generation chain
chain = ( {"context": retriever, "question": RunnablePassthrough()} | prompt | model | StrOutputParser()
) result = chain.invoke("where did harrison work?")
print(result)
בדוגמה זו, השרשרת שואבת מידע רלוונטי מההקשר ומייצרת תגובה לשאלה.
שרשרת אחזור שיחות
אתה יכול בקלות להוסיף היסטוריית שיחות לרשתות שלך. הנה דוגמה לשרשרת אחזור שיחה:
from langchain.schema.runnable import RunnableMap
from langchain.schema import format_document from langchain.prompts.prompt import PromptTemplate # Define templates for prompts
_template = """Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question, in its original language. Chat History:
{chat_history}
Follow Up Input: {question}
Standalone question:"""
CONDENSE_QUESTION_PROMPT = PromptTemplate.from_template(_template) template = """Answer the question based only on the following context:
{context} Question: {question} """
ANSWER_PROMPT = ChatPromptTemplate.from_template(template) # Define input map and context
_inputs = RunnableMap( standalone_question=RunnablePassthrough.assign( chat_history=lambda x: _format_chat_history(x["chat_history"]) ) | CONDENSE_QUESTION_PROMPT | ChatOpenAI(temperature=0) | StrOutputParser(),
)
_context = { "context": itemgetter("standalone_question") | retriever | _combine_documents, "question": lambda x: x["standalone_question"],
}
conversational_qa_chain = _inputs | _context | ANSWER_PROMPT | ChatOpenAI() result = conversational_qa_chain.invoke( { "question": "where did harrison work?", "chat_history": [], }
)
print(result)
בדוגמה זו, השרשרת מטפלת בשאלת המשך בהקשר של שיחה.
עם זיכרון והחזרת מסמכי מקור
LCEL תומך גם בזיכרון והחזרת מסמכי מקור. כך תוכל להשתמש בזיכרון בשרשרת:
from operator import itemgetter
from langchain.memory import ConversationBufferMemory # Create a memory instance
memory = ConversationBufferMemory( return_messages=True, output_key="answer", input_key="question"
) # Define steps for the chain
loaded_memory = RunnablePassthrough.assign( chat_history=RunnableLambda(memory.load_memory_variables) | itemgetter("history"),
) standalone_question = { "standalone_question": { "question": lambda x: x["question"], "chat_history": lambda x: _format_chat_history(x["chat_history"]), } | CONDENSE_QUESTION_PROMPT | ChatOpenAI(temperature=0) | StrOutputParser(),
} retrieved_documents = { "docs": itemgetter("standalone_question") | retriever, "question": lambda x: x["standalone_question"],
} final_inputs = { "context": lambda x: _combine_documents(x["docs"]), "question": itemgetter("question"),
} answer = { "answer": final_inputs | ANSWER_PROMPT | ChatOpenAI(), "docs": itemgetter("docs"),
} # Create the final chain by combining the steps
final_chain = loaded_memory | standalone_question | retrieved_documents | answer inputs = {"question": "where did harrison work?"}
result = final_chain.invoke(inputs)
print(result)
בדוגמה זו, הזיכרון משמש לאחסון ואחזור היסטוריית שיחות ומסמכי מקור.
שרשראות מרובות
אתה יכול לחבר שרשרות מרובות באמצעות Runnables. הנה דוגמה:
from operator import itemgetter from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import StrOutputParser prompt1 = ChatPromptTemplate.from_template("what is the city {person} is from?")
prompt2 = ChatPromptTemplate.from_template( "what country is the city {city} in? respond in {language}"
) model = ChatOpenAI() chain1 = prompt1 | model | StrOutputParser() chain2 = ( {"city": chain1, "language": itemgetter("language")} | prompt2 | model | StrOutputParser()
) result = chain2.invoke({"person": "obama", "language": "spanish"})
print(result)
בדוגמה זו, שתי שרשראות משולבות כדי ליצור מידע על עיר ועל המדינה שלה בשפה מוגדרת.
הסתעפות ומיזוג
LCEL מאפשר לך לפצל ולמזג שרשראות באמצעות RunnableMaps. הנה דוגמה להסתעפות ומיזוג:
from operator import itemgetter from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import StrOutputParser planner = ( ChatPromptTemplate.from_template("Generate an argument about: {input}") | ChatOpenAI() | StrOutputParser() | {"base_response": RunnablePassthrough()}
) arguments_for = ( ChatPromptTemplate.from_template( "List the pros or positive aspects of {base_response}" ) | ChatOpenAI() | StrOutputParser()
)
arguments_against = ( ChatPromptTemplate.from_template( "List the cons or negative aspects of {base_response}" ) | ChatOpenAI() | StrOutputParser()
) final_responder = ( ChatPromptTemplate.from_messages( [ ("ai", "{original_response}"), ("human", "Pros:n{results_1}nnCons:n{results_2}"), ("system", "Generate a final response given the critique"), ] ) | ChatOpenAI() | StrOutputParser()
) chain = ( planner | { "results_1": arguments_for, "results_2": arguments_against, "original_response": itemgetter("base_response"), } | final_responder
) result = chain.invoke({"input": "scrum"})
print(result)
בדוגמה זו, שרשרת הסתעפות ומיזוג משמשת ליצירת טיעון ולהערכת היתרונות והחסרונות שלו לפני יצירת תגובה סופית.
כתיבת קוד Python עם LCEL
אחד היישומים החזקים של LangChain Expression Language (LCEL) הוא כתיבת קוד Python כדי לפתור בעיות משתמש. להלן דוגמה כיצד להשתמש ב-LCEL כדי לכתוב קוד Python:
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 יכול להפעיל קוד שרירותי, אז השתמש בו בזהירות.
הוספת זיכרון לשרשרת
זיכרון חיוני ביישומי AI רבים לשיחה. כך מוסיפים זיכרון לשרשרת שרירותית:
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({})
בדוגמה זו, הזיכרון משמש לאחסון ואחזור היסטוריית שיחות, מה שמאפשר לצ'אטבוט לשמור על הקשר ולהגיב כראוי.
שימוש בכלים חיצוניים עם רכיבי ריצה
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 מאפשרת לך ליצור סוכנים על ידי שילוב של Runnables, הנחיות, מודלים וכלים. הנה דוגמה לבניית סוכן ושימוש בו:
from langchain.agents import XMLAgent, tool, AgentExecutor
from langchain.chat_models import ChatAnthropic model = ChatAnthropic(model="claude-2") @tool
def search(query: str) -> str: """Search things about current events.""" return "32 degrees" tool_list = [search] # Get prompt to use
prompt = XMLAgent.get_default_prompt() # Logic for going from intermediate steps to a string to pass into the model
def convert_intermediate_steps(intermediate_steps): log = "" for action, observation in intermediate_steps: log += ( f"<tool>{action.tool}</tool><tool_input>{action.tool_input}" f"</tool_input><observation>{observation}</observation>" ) return log # Logic for converting tools to a string to go in the prompt
def convert_tools(tools): return "n".join([f"{tool.name}: {tool.description}" for tool in tools]) agent = ( { "question": lambda x: x["question"], "intermediate_steps": lambda x: convert_intermediate_steps( x["intermediate_steps"] ), } | prompt.partial(tools=convert_tools(tool_list)) | model.bind(stop=["</tool_input>", "</final_answer>"]) | XMLAgent.get_default_output_parser()
) agent_executor = AgentExecutor(agent=agent, tools=tool_list, verbose=True) result = agent_executor.invoke({"question": "What's the weather in New York?"})
print(result)
בדוגמה זו, סוכן נוצר על ידי שילוב של מודל, כלים, הנחיה והיגיון מותאם אישית עבור שלבי ביניים והמרת כלי. לאחר מכן הסוכן מבוצע, ומספק מענה לשאילתה של המשתמש.
שאילתה של מסד נתונים של SQL
אתה יכול להשתמש ב-LangChain כדי לבצע שאילתות על מסד נתונים של SQL וליצור שאילתות SQL המבוססות על שאלות משתמשים. הנה דוגמה:
from langchain.prompts import ChatPromptTemplate template = """Based on the table schema below, write a SQL query that would answer the user's question:
{schema} Question: {question}
SQL Query:"""
prompt = ChatPromptTemplate.from_template(template) from langchain.utilities import SQLDatabase # Initialize the database (you'll need the Chinook sample DB for this example)
db = SQLDatabase.from_uri("sqlite:///./Chinook.db") def get_schema(_): return db.get_table_info() def run_query(query): return db.run(query) from langchain.chat_models import ChatOpenAI
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough model = ChatOpenAI() sql_response = ( RunnablePassthrough.assign(schema=get_schema) | prompt | model.bind(stop=["nSQLResult:"]) | StrOutputParser()
) result = sql_response.invoke({"question": "How many employees are there?"})
print(result) template = """Based on the table schema below, question, SQL query, and SQL response, write a natural language response:
{schema} Question: {question}
SQL Query: {query}
SQL Response: {response}"""
prompt_response = ChatPromptTemplate.from_template(template) full_chain = ( RunnablePassthrough.assign(query=sql_response) | RunnablePassthrough.assign( schema=get_schema, response=lambda x: db.run(x["query"]), ) | prompt_response | model
) response = full_chain.invoke({"question": "How many employees are there?"})
print(response)
בדוגמה זו, LangChain משמש ליצירת שאילתות SQL המבוססות על שאלות משתמשים ואחזור תגובות ממסד נתונים של SQL. ההנחיות והתגובות מעוצבות כדי לספק אינטראקציות בשפה טבעית עם מסד הנתונים.
הפוך משימות וזרימות עבודה ידניות לאוטומטיות עם בונה זרימת העבודה המונעת בינה מלאכותית שלנו, שתוכנן על ידי Nanonets עבורך ועבור הצוותים שלך.
LangServe & LangSmith
LangServe עוזר למפתחים לפרוס רכיבי ריצה ורשתות של LangChain בתור REST API. ספרייה זו משולבת עם FastAPI ומשתמשת ב-pydantic לאימות נתונים. בנוסף, הוא מספק לקוח שניתן להשתמש בו כדי להתקשר לרכיבי ריצה הפרוסים בשרת, ולקוח JavaScript זמין ב-LangChainJS.
תכונות
- סכימות קלט ופלט מוסקות אוטומטית מאובייקט LangChain שלך ונאכפות בכל קריאת API, עם הודעות שגיאה עשירות.
- דף מסמכי API עם JSONSchema ו-Swagger זמין.
- נקודות קצה /invoke, /batch ו-/stream יעילות עם תמיכה בבקשות רבות במקביל בשרת יחיד.
- נקודת קצה /stream_log להזרמת כל (או חלק) שלבי הביניים מהשרשרת/הסוכן שלך.
- דף מגרש משחקים ב- /מגרש משחקים עם פלט סטרימינג ושלבי ביניים.
- איתור מובנה (אופציונלי) אל 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 Templates. לדוגמאות נוספות, עיין באינדקס התבניות או בספריית הדוגמאות.
הנה שרת שפורס מודל צ'אט של 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 (דורש LangChain.js גרסה 0.0.166 ואילך):
import { RemoteRunnable } from "langchain/runnables/remote"; const chain = new RemoteRunnable({ url: `http://localhost:8000/chain/invoke/`,
});
const result = await chain.invoke({ topic: "cats",
});
פייתון באמצעות בקשות:
import requests
response = requests.post( "http://localhost:8000/chain/invoke/", json={'input': {'topic': 'cats'}}
)
response.json()
אתה יכול גם להשתמש בתלתל:
curl --location --request POST 'http://localhost:8000/chain/invoke/' --header 'Content-Type: application/json' --data-raw '{ "input": { "topic": "cats" } }'
הקוד הבא:
...
add_routes( app, runnable, path="/my_runnable",
)
מוסיף לשרת את נקודות הקצה האלה:
- POST /my_runnable/invoke - הפעל את ה-runnable בקלט בודד
- POST /my_runnable/batch - הפעל את ה-runnable על אצווה של קלט
- POST /my_runnable/stream - הפעל על קלט יחיד והזרם את הפלט
- POST /my_runnable/stream_log - הפעל על קלט בודד והזרם את הפלט, כולל פלט של שלבי ביניים כפי שהוא נוצר
- GET /my_runnable/input_schema - סכימת json לקלט ל-Runable
- GET /my_runnable/output_schema - סכימת json לפלט של ה-runnable
- GET /my_runnable/config_schema - סכימת json עבור התצורה של ה-runnable
אתה יכול למצוא דף מגרש משחקים עבור ה-runnable שלך ב- /my_runnable/playground. זה חושף ממשק משתמש פשוט להגדיר ולהפעיל את ההפעלה שלך עם פלט סטרימינג ושלבי ביניים.
גם ללקוח וגם לשרת:
pip install "langserve[all]"
או pip התקנת "langserve[client]" עבור קוד לקוח, ו-pip התקנת "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 לא ייווצרו עבור invoke/batch/stream/stream_log בעת שימוש ב- Pydantic V2. Fast API אינו תומך בערבוב מרחבי שמות של pydantic v1 ו-v2. LangChain משתמש במרחב השמות v1 ב- Pydantic v2. אנא קרא את ההנחיות הבאות כדי להבטיח תאימות עם LangChain. פרט למגבלות אלו, אנו מצפים שנקודות הקצה של ה-API, מגרש המשחקים וכל תכונות אחרות יפעלו כצפוי.
יישומי LLM עוסקים לעתים קרובות בקבצים. ישנן ארכיטקטורות שונות שניתן לבצע כדי ליישם עיבוד קבצים; ברמה גבוהה:
- ניתן להעלות את הקובץ לשרת דרך נקודת קצה ייעודית ולעבד אותו באמצעות נקודת קצה נפרדת.
- ניתן להעלות את הקובץ לפי ערך (בתים של קובץ) או הפניה (למשל, s3 url לתוכן הקובץ).
- ייתכן שנקודת הקצה של העיבוד חוסמת או לא חוסמת.
- אם נדרש עיבוד משמעותי, העיבוד עשוי להיות מוריד למאגר תהליכים ייעודי.
עליך לקבוע מהי הארכיטקטורה המתאימה ליישום שלך. נכון לעכשיו, כדי להעלות קבצים לפי ערך ל-Runable, השתמש בקידוד base64 עבור הקובץ (נתונים מרובי חלק/טופס אינם נתמכים עדיין).
הנה דוגמה שמראה כיצד להשתמש בקידוד base64 כדי לשלוח קובץ לריצה מרחוק. זכור, אתה תמיד יכול להעלות קבצים לפי הפניה (למשל, s3 url) או להעלות אותם כנתונים מרובי חלקים/טופס לנקודת קצה ייעודית.
סוגי קלט ופלט מוגדרים בכל רכיבי ההפעלה. אתה יכול לגשת אליהם דרך המאפיינים input_schema ו-out_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 ולא לייצוג dict המקביל. כרגע, סוג זה פועל רק בצד השרת ומשמש לציון התנהגות הפענוח הרצויה. אם יורש מסוג זה, השרת ישמור על הטיפוס המפוענח כמודל פיידנטי במקום להמיר אותו ל-dict.
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 של סוג הקלט. ווידג'ט חייב להכיל מפתח שנקרא type כשהערך הוא אחד מתוך רשימה ידועה של ווידג'טים. מפתחות ווידג'טים אחרים ישויכו לערכים המתארים נתיבים באובייקט 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 עבורך ועבור הצוותים שלך.
היכרות עם LangSmith
LangChain מקל על אבטיפוס של יישומי LLM וסוכנים. עם זאת, אספקת יישומי LLM לייצור יכולה להיות קשה בצורה מטעה. סביר להניח שתצטרך להתאים אישית ולחזור על ההנחיות, השרשראות ורכיבים אחרים שלך כדי ליצור מוצר באיכות גבוהה.
כדי לסייע בתהליך זה, LangSmith הוצגה, פלטפורמה מאוחדת לניפוי באגים, בדיקה וניטור יישומי ה-LLM שלך.
מתי זה עשוי להועיל? אתה עשוי למצוא את זה שימושי כאשר אתה רוצה לבצע ניפוי באגים במהירות בשרשרת, סוכן או סט כלים חדשים, לדמיין כיצד רכיבים (שרשרות, llms, רטריברים וכו') קשורים ומשמשים, להעריך הנחיות ו-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 לאינטראקציה עם ה-API:
from langsmith import Client client = Client()
צור רכיב LangChain ויומן ריצות לפלטפורמה. בדוגמה זו, ניצור סוכן בסגנון ReAct עם גישה לכלי חיפוש כללי (DuckDuckGo). ניתן לראות את ההנחיה של הסוכן ב-Hub כאן:
from langchain import hub
from langchain.agents import AgentExecutor
from langchain.agents.format_scratchpad import format_to_openai_function_messages
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser
from langchain.chat_models import ChatOpenAI
from langchain.tools import DuckDuckGoSearchResults
from langchain.tools.render import format_tool_to_openai_function # Fetches the latest version of this prompt
prompt = hub.pull("wfh/langsmith-agent-prompt:latest") llm = ChatOpenAI( model="gpt-3.5-turbo-16k", temperature=0,
) tools = [ DuckDuckGoSearchResults( name="duck_duck_go" ), # General internet search using DuckDuckGo
] llm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools]) runnable_agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai_function_messages( x["intermediate_steps"] ), } | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser()
) agent_executor = AgentExecutor( agent=runnable_agent, tools=tools, handle_parsing_errors=True
)
אנו מפעילים את הסוכן במקביל על מספר כניסות כדי להפחית את זמן ההשהיה. ריצות נרשמות ל-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 מאפשר לך להעריך כל LLM, רשת, סוכן, או אפילו פונקציה מותאמת אישית. סוכני שיחה הם ממלכתיים (יש להם זיכרון); כדי להבטיח שמצב זה אינו משותף בין ריצות של מערך נתונים, נעביר ב-chain_factory (
המכונה בנאי) פונקציה לאתחול עבור כל קריאה:
# Since chains can be stateful (e.g. they can have memory), we provide
# a way to initialize a new chain for each row in the dataset. This is done
# by passing in a factory function that returns a new chain for each row.
def agent_factory(prompt): llm_with_tools = llm.bind( functions=[format_tool_to_openai_function(t) for t in tools] ) runnable_agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai_function_messages( x["intermediate_steps"] ), } | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser() ) return AgentExecutor(agent=runnable_agent, tools=tools, handle_parsing_errors=True)
- הגדר הערכה:
השוואה ידנית של תוצאות רשתות בממשק המשתמש יעילה, אך היא עלולה לקחת זמן. זה יכול להיות מועיל להשתמש במדדים אוטומטיים ובמשוב בסיוע בינה מלאכותית כדי להעריך את הביצועים של הרכיב שלך:
from langchain.evaluation import EvaluatorType
from langchain.smith import RunEvalConfig evaluation_config = RunEvalConfig( evaluators=[ EvaluatorType.QA, EvaluatorType.EMBEDDING_DISTANCE, RunEvalConfig.LabeledCriteria("helpfulness"), RunEvalConfig.LabeledScoreString( { "accuracy": """
Score 1: The answer is completely unrelated to the reference.
Score 3: The answer has minor relevance but does not align with the reference.
Score 5: The answer has moderate relevance but contains inaccuracies.
Score 7: The answer aligns with the reference but has minor errors or omissions.
Score 10: The answer is completely accurate and aligns perfectly with the reference.""" }, normalize_by=10, ), ], custom_evaluators=[],
)
- הפעל את הסוכן והמעריכים:
השתמש בפונקציה run_on_dataset (או א-סינכרוני arun_on_dataset) כדי להעריך את המודל שלך. זה יהיה:
- אחזר שורות לדוגמה ממערך הנתונים שצוין.
- הפעל את הסוכן שלך (או כל פונקציה מותאמת אישית) על כל דוגמה.
- החל מעריכים על עקבות הריצה שהתקבלו ודוגמאות התייחסות מתאימות כדי ליצור משוב אוטומטי.
התוצאות יהיו גלויות באפליקציית LangSmith:
chain_results = run_on_dataset( dataset_name=dataset_name, llm_or_chain_factory=functools.partial(agent_factory, prompt=prompt), evaluation=evaluation_config, verbose=True, client=client, project_name=f"runnable-agent-test-5d466cbc-{unique_id}", tags=[ "testing-notebook", "prompt:5d466cbc", ],
)
כעת, לאחר שיש לנו את תוצאות הניסוי שלנו, אנו יכולים לבצע שינויים בסוכן שלנו ולהשוות אותם. בוא ננסה זאת שוב עם הנחיה אחרת ונראה את התוצאות:
candidate_prompt = hub.pull("wfh/langsmith-agent-prompt:39f3bbd0") chain_results = run_on_dataset( dataset_name=dataset_name, llm_or_chain_factory=functools.partial(agent_factory, prompt=candidate_prompt), evaluation=evaluation_config, verbose=True, client=client, project_name=f"runnable-agent-test-39f3bbd0-{unique_id}", tags=[ "testing-notebook", "prompt:39f3bbd0", ],
)
LangSmith מאפשר לייצא נתונים לפורמטים נפוצים כגון CSV או JSONL ישירות באפליקציית האינטרנט. אתה יכול גם להשתמש בלקוח כדי להביא ריצות לניתוח נוסף, לאחסון במסד הנתונים שלך, או כדי לשתף עם אחרים. בוא נביא את עקבות הריצה מהפעלת ההערכה:
runs = client.list_runs(project_name=chain_results["project_name"], execution_order=1) # After some time, these will be populated.
client.read_project(project_name=chain_results["project_name"]).feedback_stats
זה היה מדריך מהיר להתחיל, אבל יש עוד דרכים רבות להשתמש ב-LangSmith כדי להאיץ את זרימת המפתחים שלך ולהפיק תוצאות טובות יותר.
למידע נוסף על איך אתה יכול להפיק את המרב מ-LangSmith, עיין בתיעוד של LangSmith.
עלה רמה עם Nanonets
בעוד ש-LangChain הוא כלי רב ערך לשילוב מודלים של שפה (LLMs) עם היישומים שלך, הוא עשוי להתמודד עם מגבלות בכל הנוגע למקרי שימוש ארגוניים. הבה נחקור כיצד Nanonets עוברת מעבר ל-LangChain כדי להתמודד עם האתגרים האלה:
1. קישוריות נתונים מקיפה:
LangChain מציעה מחברים, אך ייתכן שהיא לא מכסה את כל אפליקציות סביבת העבודה ופורמטי הנתונים שעסקים מסתמכים עליהם. Nanonets מספקת מחברי נתונים עבור למעלה מ-100 אפליקציות סביבת עבודה בשימוש נרחב, כולל Slack, Notion, Google Suite, Salesforce, Zendesk ורבים נוספים. זה גם תומך בכל סוגי הנתונים הלא מובנים כמו קובצי PDF, TXT, תמונות, קבצי אודיו וקבצי וידאו, כמו גם סוגי נתונים מובנים כמו CSVs, גיליונות אלקטרוניים, MongoDB ומסדי נתונים של SQL.
2. אוטומציה של משימות עבור אפליקציות Workspace:
בעוד שיצירת טקסט/תגובות עובדת מצוין, היכולות של LangChain מוגבלות בכל הנוגע לשימוש בשפה טבעית לביצוע משימות ביישומים שונים. Nanonets מציעה סוכני טריגר/פעולה עבור אפליקציות סביבת העבודה הפופולריות ביותר, ומאפשרות לך להגדיר זרימות עבודה שמאזינות לאירועים ומבצעות פעולות. לדוגמה, אתה יכול להפוך תגובות דוא"ל לאוטומטיות, ערכי CRM, שאילתות SQL ועוד, הכל באמצעות פקודות שפה טבעית.
3. סנכרון נתונים בזמן אמת:
LangChain מביאה נתונים סטטיים עם מחברי נתונים, אשר עשויים שלא לעמוד בקצב של שינויים בנתונים במסד הנתונים של המקור. לעומת זאת, Nanonets מבטיח סנכרון בזמן אמת עם מקורות נתונים, ומבטיח שאתה תמיד עובד עם המידע העדכני ביותר.
3. תצורה פשוטה:
הגדרת האלמנטים של צינור LangChain, כגון רטריברים וסינתיסייזרים, יכולה להיות תהליך מורכב וגוזל זמן. Nanonets מייעלים זאת על ידי מתן אופטימיזציה של קליטת נתונים ואינדקס עבור כל סוג נתונים, הכל מטופל ברקע על ידי עוזר AI. זה מפחית את הנטל של כוונון עדין ומקל על ההגדרה והשימוש.
4. פתרון מאוחד:
בניגוד ל-LangChain, שעשויה לדרוש הטמעות ייחודיות לכל משימה, Nanonets משמשת כפתרון נקודתי לחיבור הנתונים שלך עם LLMs. בין אם אתה צריך ליצור יישומי LLM או זרימות עבודה של AI, Nanonets מציעה פלטפורמה מאוחדת לצרכים המגוונים שלך.
זרימות עבודה של Nanonets AI
Nanonets Workflows הוא עוזר AI מאובטח ורב-תכליתי המפשט את השילוב של הידע והנתונים שלך עם LLMs ומקל על יצירת יישומים וזרימות עבודה ללא קוד. הוא מציע ממשק משתמש קל לשימוש, מה שהופך אותו לנגיש עבור יחידים וארגונים כאחד.
כדי להתחיל, אתה יכול לקבוע שיחה עם אחד ממומחי הבינה המלאכותית שלנו, שיוכל לספק הדגמה אישית וניסיון של זרימות עבודה של Nanonets המותאמות למקרה השימוש הספציפי שלך.
לאחר ההגדרה, אתה יכול להשתמש בשפה טבעית כדי לעצב ולהפעיל יישומים וזרימות עבודה מורכבות המופעלות על ידי LLMs, תוך שילוב חלק עם האפליקציות והנתונים שלך.
הטעינו את הצוותים שלכם עם Nanonets AI כדי ליצור אפליקציות ולשלב את הנתונים שלכם עם יישומים וזרימות עבודה מונעות בינה מלאכותית, מה שמאפשר לצוותים שלכם להתמקד במה שחשוב באמת.
הפוך משימות וזרימות עבודה ידניות לאוטומטיות עם בונה זרימת העבודה המונעת בינה מלאכותית שלנו, שתוכנן על ידי Nanonets עבורך ועבור הצוותים שלך.
- הפצת תוכן ויחסי ציבור מופעל על ידי SEO. קבל הגברה היום.
- PlatoData.Network Vertical Generative Ai. העצים את עצמך. גישה כאן.
- PlatoAiStream. Web3 Intelligence. הידע מוגבר. גישה כאן.
- PlatoESG. פחמן, קלינטק, אנרגיה, סביבה, שמש, ניהול פסולת. גישה כאן.
- PlatoHealth. מודיעין ביוטכנולוגיה וניסויים קליניים. גישה כאן.
- מקור: https://nanonets.com/blog/langchain/
- :יש ל
- :הוא
- :לֹא
- :איפה
- $ למעלה
- 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
- ממשקי API
- האפליקציה
- ישים
- בקשה
- פיתוח אפליקציות
- יישומים
- יישומית
- חל
- גישה
- גישות
- מתאים
- כראוי
- אפליקציות
- ארכיטקטורה
- ARE
- טענה
- טיעונים
- ארמסטרונג
- סביב
- מערך
- אמנים
- AS
- לשאול
- אספקט
- היבטים
- לעזור
- עוזר
- המשויך
- At
- לצרף
- תשומת לב
- אודיו
- מוגבר
- אימות
- אוטומטי
- אוטומטי
- אוטומטית
- באופן אוטומטי
- אוטומציה
- זמין
- מְמוּצָע
- לחכות
- מודע
- AWS
- בחזרה
- עמוד שדרה
- קצה אחורי
- רקע
- רע
- איזון
- בָּר
- בסיס
- מבוסס
- Baseline
- לחבוט
- בסיסי
- יסודות
- BCG
- BE
- חוף
- דובים
- כי
- היה
- לפני
- להתחיל
- התנהגות
- מאחור
- מאחורי הקלעים
- להיות
- להלן
- בנצ 'מרק
- מועיל
- הטוב ביותר
- מוטב
- בֵּין
- מעבר
- הגדול ביותר
- הצעת חוק
- ביל גייטס
- לאגד
- בינג
- קצת
- שחור
- חור שחור
- לחסום
- חסימה
- אבני
- בלוג
- שילינג
- אוזן נעל
- נולד
- בוט
- שניהם
- תַחתִית
- סניף
- לשבור
- רוח
- בקצרה
- רחב
- חום
- דפדפן
- חיץ
- לִבנוֹת
- בונה
- בִּניָן
- נבנה
- ניטל
- עסקים
- אבל
- by
- לחשב
- מחשב
- חישוב
- חישוב
- שיחה
- התקשרות חוזרת
- נקרא
- קוראים
- שיחות
- CAN
- יכול לקבל
- קנדה
- יכולות
- מסוגל
- קיבולת
- ללכוד
- לכידה
- מקרה
- מקרים
- חָתוּל
- לספק
- קייטרינג
- מספקת
- חתולים
- זהירות
- זהיר
- מרוכז
- מסוים
- שרשרת
- שרשראות
- האתגרים
- שינויים
- אופי
- chatbot
- chatbots
- לבדוק
- בדיקות
- בחרו
- נבחר
- בנסיבות
- עִיר
- בכיתה
- כיתות
- לקוחות
- ענן
- קוד
- סִמוּל
- קָפֶה
- קוהרנטי
- מגובש
- לשתף פעולה
- הִתמוֹטְטוּת
- אוסף
- צבעוני
- טור
- עמודות
- COM
- לשלב
- משולב
- משלב
- שילוב
- איך
- מגיע
- נוח
- Common
- תקשורת
- חברה
- לְהַשְׁווֹת
- השוואה
- תאימות
- תואם
- להשלים
- לחלוטין
- השלמה
- מורכב
- מורכבות
- רְכִיב
- רכיבים
- מורכב
- הרכב
- מַקִיף
- מכיל
- מושג
- תמציתית
- במקביל
- מצב
- תְצוּרָה
- מפגש
- לְחַבֵּר
- מקשר
- קישוריות
- חסרונות
- לשקול
- באופן עקבי
- מורכב
- קונסול
- תמיד
- בונה
- להכיל
- מכיל
- תוכן
- הקשר
- הקשרים
- קשר
- להמשיך
- ברציפות
- לעומת זאת
- לִשְׁלוֹט
- בקרות
- נוֹחַ
- שיחה
- שיחה
- AI שיחה
- שיחות
- המרה
- הומר
- המרת
- ליבה
- בפינה
- לתקן
- תוֹאֵם
- יכול
- ספירה
- מדינה
- זוג
- לכסות
- מכוסה
- לִיצוֹר
- נוצר
- יוצר
- יוצרים
- יצירה
- אישורים
- הקריטריונים
- מבקר
- CRM
- מכריע
- נוֹכְחִי
- כיום
- מנהג
- לקוחות
- התאמה אישית
- אישית
- אישית
- שיא הטכנולוגיה
- נתונים
- מבנה נתונים
- מסד נתונים
- מאגרי מידע
- תַאֲרִיך
- datetime
- עסקה
- התמודדות
- דֵצֶמבֶּר
- להחליט
- מחליטים
- קבלת החלטות
- פענוח
- מוקדש
- עמוק יותר
- בְּרִירַת מֶחדָל
- לְהַגדִיר
- מוגדר
- הגדרה
- הגדרות
- אספקה
- מספק
- להתעמק
- הדגמה
- להפגין
- מופגן
- הפגנה
- לסמוך
- תלוי
- תלוי
- לפרוס
- פרס
- פריסה
- פריסה
- פורס
- לתאר
- תיאור
- עיצוב
- יעוד
- מעוצב
- רצוי
- פרט
- מְפוֹרָט
- פרטים
- לקבוע
- קובע
- לפתח
- מפתח
- מפתחים
- מתפתח
- צעצועי התפתחות
- דיאגרמות
- DICT
- DID
- נבדלים
- אחר
- באופן שונה
- קשה
- מֵמַד
- ממדים
- הנחיות
- ישירות
- לדון
- נָדוֹן
- מציג
- מובהק
- צלילה
- שונה
- DM
- do
- מסמך
- תיעוד
- מסמכים
- עושה
- לא איכפת
- עושה
- דון
- עשה
- לְהַכפִּיל
- מטה
- להורדה
- הורדות
- טיוטה
- נהיגה
- ראוי
- בְּמַהֲלָך
- דינמי
- באופן דינמי
- e
- כל אחד
- מוקדם יותר
- מוקדם
- להקל
- קלות שימוש
- קל יותר
- בקלות
- קל
- קל לשימוש
- הד
- המערכת האקולוגית
- אפקטיבי
- יעילות
- יְעִילוּת
- יעיל
- יעילות
- ללא מאמץ
- או
- אלמנט
- אלמנטים
- אלון
- אלון מאסק
- אחר
- אמייל
- שבץ
- מוטבע
- הטבעה
- מוּעֳסָק
- עובדים
- מעסיקה
- להסמיך
- לאפשר
- מאפשר
- מה שמאפשר
- עוטף
- פוגש
- מקצה לקצה
- נקודת קצה
- מרתק
- מנוע
- מנועים
- אַנְגלִיָה
- אנגלית
- ליגה האנגלית
- להגביר את
- משופר
- שיפור
- לְהַבטִיחַ
- מבטיח
- הבטחתי
- מִפְעָל
- ישויות
- ישות
- סביבה
- סביבות
- שווה
- תקופה
- שגיאה
- שגיאות
- במיוחד
- חיוני
- חָנוּק
- וכו '
- להעריך
- הערכה
- אֲפִילוּ
- אירועים
- כל
- דוגמה
- דוגמאות
- עולה על
- אלא
- לבצע
- יצא לפועל
- מוציאים להורג
- מבצע
- הוצאת להורג
- מדגים
- תרגיל
- להתקיים
- לצפות
- הציפיות
- צפוי
- מצפה
- ניסיון
- ניסיוני
- מומחים
- מוסבר
- מסביר
- בִּמְפוּרָשׁ
- חקירה
- לחקור
- חקר
- יצוא
- ביטוי
- להאריך
- מאריך
- נרחב
- חיצוני
- נוסף
- תמצית
- הוֹצָאָה
- תמציות
- פָּנִים
- לְהַקֵל
- מקל
- מפעל
- עובדות
- רחוק
- מהר
- חביב
- מאפיין
- תכונות
- מָשׁוֹב
- מעטים
- שדה
- שדות
- פיגמה
- תרשים
- שלח
- קבצים
- למלא
- ממולא
- מְלִית
- לסנן
- סינון
- סופי
- בסופו של דבר
- מציאת
- ראשון
- חמש
- גמישות
- גמיש
- תזרים
- להתמקד
- מרוכז
- מתמקד
- התמקדות
- לעקוב
- הבא
- כדלקמן
- מזון
- בעד
- טופס
- פוּרמָט
- נוצר
- למרבה המזל
- מצא
- מסגרת
- מסגרות
- בתדירות גבוהה
- חבר
- חברים
- החל מ-
- מלא
- מן המניין
- פונקציה
- פונקציות
- פונקציונלי
- פונקציות
- יסודי
- מצחיק
- נוסף
- עתיד
- לְהַשִׂיג
- משחקים
- גייטס
- כללי
- בדרך כלל
- ליצור
- נוצר
- מייצר
- יצירת
- דור
- ז'ָאנר
- גרמניה
- לקבל
- מקבל
- gif
- GitHub
- נתן
- GMT
- Go
- Goes
- הולך
- טוב
- פרטני
- גרף
- גדול
- יותר
- הדרכה
- מדריך
- הנחיות
- האקטון
- לטפל
- מטפל
- טיפול
- שימושי
- קשה
- לפגוע
- רתמות
- יש
- יש
- בִּכְבֵדוּת
- הוחזק
- לעזור
- מועיל
- עוזר
- לה
- כאן
- hi
- גָבוֹהַ
- ברמה גבוהה
- באיכות גבוהה
- הגבוה ביותר
- מאוד
- היסטורי
- היסטוריה
- חור
- ברדס
- המארח
- איך
- איך
- אולם
- HTML
- http
- HTTPS
- טבור
- בן אנוש
- מאות
- i
- ID
- רעיון
- אידאל
- מזהה
- if
- ii
- ג
- להמחיש
- מדגים
- תמונות
- מיידי
- ליישם
- הפעלה
- יישומים
- יושם
- לייבא
- שיפורים
- שיפור
- in
- מעמיק
- לכלול
- כלול
- כולל
- כולל
- בע"מ
- שילוב
- בצורה מדהימה
- מדד
- אינדקסים
- להצביע
- מצביע על
- בנפרד
- אנשים
- מידע
- בתחילה
- ליזום
- חדשני
- קלט
- תשומות
- תובנות
- להתקין
- מותקן
- התקנה
- למשל
- מיידי
- במקום
- הוראות
- אינטגרלי
- לשלב
- משולב
- משלב
- שילוב
- השתלבות
- ואינטגרציות
- אינטליגנטי
- התכוון
- אינטראקציה
- אינטראקציה
- יחסי גומלין
- אינטראקטיבי
- אינטראקטיבי
- מִמְשָׁק
- ממשקים
- כלפי פנים
- אינטרנט
- אל תוך
- הציג
- מציג
- אינטואיטיבי
- מעורב
- J States
- סוגיה
- בעיות
- IT
- פריטים
- איטרציות
- שֶׁלָה
- עצמו
- ג'קסון
- JavaScript
- עבודה
- ירדן
- מסע
- ג'סון
- יולי
- רק
- שופט
- שמור
- שומר
- מפתח
- מפתחות
- סוג
- לדעת
- ידע
- גרף ידע
- ידוע
- תווית
- תוויות
- מדינה
- שפה
- שפות
- גָדוֹל
- גדול יותר
- אחרון
- חֶבִיוֹן
- מאוחר יותר
- האחרון
- ליגה
- לִלמוֹד
- למידה
- עזבו
- מוֹרֶשֶׁת
- אורך
- פחות
- לתת
- מאפשר לי
- מכתב
- רמה
- רמות
- תנופה
- מנופים
- מינוף
- ספריות
- סִפְרִיָה
- כמו
- סביר
- להגביל
- מגבלות
- מוגבל
- מגביל
- גבולות
- קישורים
- רשימה
- להקשיב
- רשימות
- לחיות
- ll
- LLM
- לִטעוֹן
- מטעין
- ממוקם
- מיקום
- היכנס
- מחובר
- רישום
- הגיון
- ארוך
- עוד
- נראה
- הסתכלות
- נראה
- בדיקה
- ה
- לוס אנג'לס
- נמוך
- מכונה
- למידת מכונה
- עשוי
- לתחזק
- ניתנת לשמירה
- שמירה
- שומר
- לעשות
- עושה
- עשייה
- לנהל
- ניהול
- מנהל
- ניהול
- מנצ'סטר
- מנצ'סטר יונייטד
- מניפולציה
- דרך
- מדריך ל
- יַצרָן
- רב
- הרבה אנשים
- מַפָּה
- מיפוי
- מפות
- להתאים
- תואם
- מתמטיקה
- מתימטי
- עניינים
- מקסימום
- מאי..
- me
- אומר
- משמעות
- אומר
- למדוד
- מדיה
- מפגש
- פוגשת
- זכרונות
- זכרון
- מוּזְכָּר
- למזג
- מיזוג
- הודעה
- הודעות
- הודעות
- מידע נוסף
- שיטה
- שיטות
- מדדים
- יכול
- מיליונים
- מינימלי
- קטין
- חסר
- טעויות
- ערבוב
- MLB
- סלולרי
- מודל
- מודלים
- מתינות
- מודול
- מודולים
- רֶגַע
- MongoDB
- צג
- ניטור
- ירח
- יותר
- רוב
- הכי פופולארי
- המהלך
- סרט
- הרבה
- מספר
- שרשראות מרובות
- מושק
- צריך
- my
- שם
- שם
- שמות
- לאומי
- טבעי
- עיבוד שפה טבעית
- נווט
- מנווט
- ליד
- הכרחי
- צורך
- נחוץ
- צרכי
- שלילי
- חדש
- ניו יורק
- ניו יורק טיימס
- הבא
- לא
- ללא חתימה
- שום דבר
- רעיון
- עַכשָׁיו
- מספר
- אובמה
- אובייקט
- מטרה
- אובייקטים
- תצפית
- להשיג
- להשיג
- OCR
- of
- הַצָעָה
- הצעה
- המיוחדות שלנו
- לעתים קרובות
- oh
- בסדר
- האולימפיאדה
- on
- פעם
- ONE
- רק
- קוד פתוח
- OpenAI
- תפעול
- מפעיל
- אופטימיזציה
- מייעל
- אפשרות
- or
- להזמין
- אורגני
- ארגונים
- מְקוֹרִי
- OS
- אחר
- אחרים
- אַחֶרֶת
- שלנו
- הַחוּצָה
- תפוקה
- פלטים
- יותר
- לעקוף
- סקירה
- שֶׁלוֹ
- חבילה
- חבילות
- עמוד
- דפים
- זוגות
- דובי פנדה
- מאמר
- מקביל
- פרמטר
- פרמטרים
- פארק
- חלק
- במיוחד
- חלקים
- לעבור
- עבר
- מעברי
- חולף
- עבר
- נתיב
- שבילים
- דפוסי
- גליון שכר
- אֲנָשִׁים
- עבור
- בצורה מושלמת
- לְבַצֵעַ
- ביצועים
- ביצוע
- מבצע
- הרשאות
- התמדה
- אדם
- אישית
- פרספקטיבה
- פיסיקה
- לְחַבֵּר
- צינור
- פיצה
- מציין מיקום
- פלטפורמה
- אפלטון
- מודיעין אפלטון
- אפלטון נתונים
- לְשַׂחֵק
- גן שעשועים
- משחק
- אנא
- ועוד
- נקודה
- מדיניות
- מדיניות
- פוליטי
- בריכה
- פופולרי
- מְאוּכלָס
- חיובי
- אפשרי
- הודעה
- הודעות
- פוטנציאל
- כּוֹחַ
- מופעל
- חזק
- מעשי
- תרגול
- לְהַעֲדִיף
- ראש הממשלה
- להציג
- נשיא
- למנוע
- מניעה
- קודם
- בראש ובראשונה
- יְסוֹדִי
- ראשוני
- פְּרָטִי
- בעיה
- בעיות
- להמשיך
- תהליך
- מעובד
- תהליכים
- תהליך
- לייצר
- המוצר
- הפקה
- פרופסור
- תכנות
- שפות תכנות
- פּרוֹיֶקט
- פרויקטים
- נכסים
- רכוש
- PROS
- אב טיפוס
- prototyping
- לספק
- ובלבד
- ספק
- ספקים
- מספק
- מתן
- ציבורי
- מטרה
- למטרות
- גם
- פיתון
- שאלות ותשובות
- איכות
- שאילתות
- שאלה
- שאלות
- מָהִיר
- מהירות
- ציטוטים
- R
- להעלות
- רכס
- טִוּוּחַ
- במקום
- דירוג
- חי
- RE
- לְהַגִיעַ
- להגיב
- חומר עיוני
- קריאה
- מוכן
- ממשי
- זמן אמת
- נתונים בזמן אמת
- תחום
- טעם
- סיבות
- לאחרונה
- מוּמלָץ
- מוקלט
- רשום
- להחלים
- להפחית
- מפחית
- הפחתה
- הפחתה
- הפניה
- התייחסות
- לחדד
- זיקוק
- אזורים
- מערכות יחסים
- שוחרר
- הרלוונטיות
- רלוונטי
- אמינות
- אָמִין
- לסמוך
- הסתמכות
- שְׂרִידִים
- לזכור
- תזכורת
- מרחוק
- לדקלם
- לחזור על
- שוב ושוב
- לנסח מחדש
- להחליף
- לדווח
- מאגר
- נציגות
- המייצג
- מייצג
- לבקש
- בקשות
- לדרוש
- נדרש
- דרישות
- דורש
- להציל
- מחקר
- לפתור
- משאב
- להגיב
- להגיב
- תגובה
- תגובות
- אחראי
- תגובה
- REST
- תוצאה
- וכתוצאה מכך
- תוצאות
- שמירה
- שייר
- לַחֲזוֹר
- חוזר
- החזרות
- לשימוש חוזר
- סקירה
- סובב
- אורז
- עשיר
- רובוטים
- תפקיד
- תפקידים
- שורש
- ניתוב
- שׁוּרָה
- הפעלה
- ריצה
- פועל
- זמן ריצה
- s
- אמצעי הגנה
- מכירות
- כוח מכירות
- סם
- אותו
- שמור
- לומר
- אומר
- להרחבה
- סולם
- תרחיש
- תרחישים
- סצנות
- לוח זמנים
- ציון
- לגרד
- בצורה חלקה
- בצורה חלקה
- חיפוש
- מנוע חיפוש
- חיפושים
- חיפוש
- סעיף
- סעיפים
- לבטח
- אבטחה
- לִרְאוֹת
- נבחר
- מבחר
- מכירת
- לשלוח
- רגיש
- רגש
- רגשות
- נפרד
- סֶפּטֶמבֶּר
- רצף
- סדרה
- לשרת
- שרת
- משמש
- שירותים
- סט
- סטים
- הצבה
- הגדרות
- התקנה
- שבע
- כמה
- שיתוף
- משותף
- פָּגָז
- זורחת
- shipped
- צריך
- לְהַצִיג
- ראווה
- הראה
- הופעות
- סיגמא
- משמעותי
- דומה
- פָּשׁוּט
- פשוט
- לפשט
- מפשט
- בפשטות
- since
- יחיד
- מידה
- רָפוּי
- קטן
- קטן יותר
- חכם
- קטע
- So
- עד כה
- כדורגל
- חֶברָתִי
- מדיה חברתית
- פוסטים ברשתות החברתיות
- אך ורק
- מוצק
- פִּתָרוֹן
- לפתור
- כמה
- משהו
- לפעמים
- מתוחכם
- צלילים
- מָקוֹר
- מקורות
- מֶרחָב
- ספרדי
- מיוחד
- ספציפי
- במיוחד
- פירוט
- מפורט
- מְהִירוּת
- בילה
- לפצל
- פיצולים
- ספורט
- מרובע
- לעמוד
- עצמאי
- תֶקֶן
- התחלה
- החל
- החל
- מדינה
- הצהרות
- סטטי
- שלב
- צעדים
- עוד
- עצור
- סְתִימָה
- עוצר
- אחסון
- חנות
- מאוחסן
- חנויות
- אחסון
- סיפור
- פשוט
- זרם
- נהירה
- לייעל
- זִרמִי
- חוזק
- שביתות
- מחרוזת
- מִבְנֶה
- מובנה
- מבנים
- הַבנָיָה
- סגנון
- נושא
- לאחר מכן
- בהצלחה
- כזה
- כדלקמן
- מַתְאִים
- מערכת
- לסכם
- סיכום
- שקיעת השמש
- תמיכה
- נתמך
- תומך
- בטוח
- קיימות
- סִנכְּרוּן
- תַקצִיר
- תחביר
- מערכת
- מערכות
- שולחן
- חייט
- מותאם
- לקחת
- לוקח
- מטרות
- המשימות
- משימות
- נבחרת
- צוותי
- לספר
- תבנית
- תבניות
- מסוף
- טרמינולוגיה
- מונחים
- מבחן
- בדיקות
- טֶקסט
- מֵאֲשֶׁר
- תודה
- זֶה
- השמיים
- היסודות
- הרכזת
- המידע
- ניו יורק טיימס
- המיזמים
- המקור
- העולם
- שֶׁלָהֶם
- אותם
- אז
- שם.
- אלה
- הֵם
- דברים
- זֶה
- אלה
- אם כי?
- דרך
- בכל
- זמן
- דורש זמן רב
- פִּי
- כותרת
- ל
- יַחַד
- אסימון
- טוקניזציה
- מטבעות
- גַם
- כלי
- ארגז כלים
- כלים
- חלק עליון
- נושא
- נושאים
- סה"כ
- עיר
- מעקב
- לעקוב
- מסורתי
- הדרכה
- לשנות
- טרנספורמציות
- שנאי
- רוֹבּוֹטרִיקִים
- מַעֲבָר
- מִשׁפָּט
- נָכוֹן
- באמת
- לנסות
- כונון
- תור
- פנייה
- הדרכה
- פעמים
- שתיים
- סוג
- סוגים
- כתב כתיבה
- בדרך כלל
- ui
- בסופו של דבר
- לא מושפע
- תחת
- בְּסִיסִי
- להבין
- הבנה
- מבין
- מאוחד
- ייחודי
- מאוחד
- אוניברסלי
- בניגוד
- עד
- עדכון
- עדכונים
- נטען
- כתובת האתר
- us
- שמישות
- נוֹהָג
- להשתמש
- במקרה להשתמש
- מְשׁוּמָשׁ
- משתמש
- ממשק משתמש
- משתמשים
- שימושים
- באמצעות
- כלי עזר
- לנצל
- מנוצל
- מנצל
- ניצול
- v1
- אימות
- Validator
- בעל ערך
- ערך
- ערכים
- משתנה
- מגוון
- שונים
- Ve
- רב צדדי
- גרסה
- מאוד
- באמצעות
- וִידֵאוֹ
- לצפיה
- הפרות
- נראה
- לחזות
- חיוני
- vs
- ללכת
- בהדרכה
- רוצה
- היה
- שעון
- דֶרֶך..
- דרכים
- we
- מזג אוויר
- אינטרנט
- דפדפן אינטרנט
- שירותי אינטרנט
- אתרים
- טוֹב
- מוכר
- היו
- מה
- מה
- Whats
- מתי
- אם
- אשר
- בזמן
- מי
- כל
- למה
- רָחָב
- באופן נרחב
- יישומון
- ויקיפדיה
- יצטרך
- חלון
- ניצחונות
- עם
- בתוך
- לְלֹא
- Word
- תיק עבודות
- עבד
- זרימת עבודה
- זרימות עבודה
- עובד
- עובד
- עוֹלָם
- היה
- לכתוב
- כתיבה
- X
- עוד
- york
- אתה
- עצמך
- YouTube
- Zendesk
- זפירנט
- רוכסן