În centrul său, LangChain este un cadru inovator conceput pentru crearea de aplicații care valorifică capacitățile modelelor de limbaj. Este un set de instrumente conceput pentru ca dezvoltatorii să creeze aplicații care sunt conștiente de context și capabile de raționament sofisticat.
Aceasta înseamnă că aplicațiile LangChain pot înțelege contextul, cum ar fi instrucțiuni prompte sau răspunsuri de fundamentare a conținutului și pot folosi modele de limbaj pentru sarcini complexe de raționament, cum ar fi să decidă cum să răspundă sau ce acțiuni să întreprindă. LangChain reprezintă o abordare unificată a dezvoltării de aplicații inteligente, simplificând călătoria de la concept la execuție cu diversele sale componente.
Înțelegerea LangChain
LangChain este mult mai mult decât un cadru; este un ecosistem cu drepturi depline care cuprinde mai multe părți integrante.
- În primul rând, există bibliotecile LangChain, disponibile atât în Python, cât și în JavaScript. Aceste biblioteci sunt coloana vertebrală a LangChain, oferind interfețe și integrări pentru diferite componente. Ele oferă un timp de rulare de bază pentru combinarea acestor componente în lanțuri și agenți coezivi, împreună cu implementări gata făcute pentru utilizare imediată.
- În continuare, avem șabloane LangChain. Acestea sunt o colecție de arhitecturi de referință implementabile, adaptate pentru o gamă largă de sarcini. Indiferent dacă construiți un chatbot sau un instrument analitic complex, aceste șabloane oferă un punct de plecare solid.
- LangServe intervine ca o bibliotecă versatilă pentru implementarea lanțurilor LangChain ca API-uri REST. Acest instrument este esențial pentru a vă transforma proiectele LangChain în servicii web accesibile și scalabile.
- În cele din urmă, LangSmith servește ca platformă pentru dezvoltatori. Este conceput pentru a depana, testa, evalua și monitoriza lanțurile construite pe orice cadru LLM. Integrarea perfectă cu LangChain îl face un instrument indispensabil pentru dezvoltatorii care doresc să-și perfecționeze aplicațiile.
Împreună, aceste componente vă permit să dezvoltați, să producați și să implementați aplicații cu ușurință. Cu LangChain, începeți prin a vă scrie aplicațiile folosind bibliotecile, folosind șabloane pentru îndrumare. LangSmith vă ajută apoi să vă inspectați, să testați și să vă monitorizați lanțurile, asigurându-vă că aplicațiile dumneavoastră se îmbunătățesc în mod constant și sunt gata pentru implementare. În cele din urmă, cu LangServe, puteți transforma cu ușurință orice lanț într-un API, făcând implementarea o ușoară.
În secțiunile următoare, vom aprofunda cum să configurați LangChain și să vă începem călătoria în crearea de aplicații inteligente, bazate pe modele de limbaj.
Automatizați sarcinile și fluxurile de lucru manuale cu generatorul nostru de flux de lucru bazat pe inteligență artificială, conceput de Nanonets pentru dvs. și echipele dvs.
Instalare și configurare
Ești gata să te scufunzi în lumea LangChain? Configurarea este simplă, iar acest ghid vă va ghida pas cu pas prin procesul.
Primul pas în călătoria dvs. LangChain este să îl instalați. Puteți face acest lucru cu ușurință folosind pip sau conda. Rulați următoarea comandă în terminalul dvs.:
pip install langchain
Pentru cei care preferă cele mai recente funcții și se simt confortabil cu puțin mai multă aventură, puteți instala LangChain direct de la sursă. Clonați depozitul și navigați la langchain/libs/langchain
director. Apoi, rulați:
pip install -e .
Pentru caracteristici experimentale, luați în considerare instalarea langchain-experimental
. Este un pachet care conține cod de ultimă generație și este destinat scopurilor de cercetare și experimentale. Instalați-l folosind:
pip install langchain-experimental
LangChain CLI este un instrument util pentru lucrul cu șabloane LangChain și proiecte LangServe. Pentru a instala CLI LangChain, utilizați:
pip install langchain-cli
LangServe este esențial pentru implementarea lanțurilor dvs. LangChain ca API REST. Se instalează împreună cu LangChain CLI.
LangChain necesită adesea integrări cu furnizori de modele, magazine de date, API-uri etc. Pentru acest exemplu, vom folosi API-urile model OpenAI. Instalați pachetul OpenAI Python folosind:
pip install openai
Pentru a accesa API-ul, setați cheia API OpenAI ca variabilă de mediu:
export OPENAI_API_KEY="your_api_key"
Alternativ, transmiteți cheia direct în mediul dvs. Python:
import os
os.environ['OPENAI_API_KEY'] = 'your_api_key'
LangChain permite crearea de aplicații de model de limbaj prin module. Aceste module pot fi fie independente, fie compuse pentru cazuri de utilizare complexe. Aceste module sunt -
- Model I / O: facilitează interacțiunea cu diverse modele de limbaj, gestionând intrările și ieșirile acestora în mod eficient.
- Recuperare: Permite accesul și interacțiunea cu datele specifice aplicației, cruciale pentru utilizarea dinamică a datelor.
- Agenți: Permite aplicațiilor să selecteze instrumentele adecvate pe baza directivelor de nivel înalt, îmbunătățind capacitățile de luare a deciziilor.
- Lanţuri: Oferă compoziții predefinite, reutilizabile, care servesc drept blocuri pentru dezvoltarea aplicațiilor.
- Memorie: Menține starea aplicației în mai multe execuții în lanț, esențial pentru interacțiunile conștiente de context.
Fiecare modul vizează nevoi specifice de dezvoltare, făcând din LangChain un set de instrumente cuprinzător pentru crearea de aplicații avansate de model de limbaj.
Alături de componentele de mai sus, avem și LangChain Expression Language (LCEL), care este o modalitate declarativă de a compune cu ușurință module împreună, iar acest lucru permite înlănțuirea componentelor folosind o interfață universală Runnable.
LCEL arată cam așa -
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import BaseOutputParser # Example chain
chain = ChatPromptTemplate() | ChatOpenAI() | CustomOutputParser()
Acum că am acoperit elementele de bază, vom continua să:
- Sapă mai adânc în fiecare modul Langchain în detaliu.
- Aflați cum să utilizați LangChain Expression Language.
- Explorați cazuri de utilizare obișnuite și implementați-le.
- Implementați o aplicație end-to-end cu LangServe.
- Consultați LangSmith pentru depanare, testare și monitorizare.
Să începem!
Modulul I: Model I/O
În LangChain, elementul de bază al oricărei aplicații se învârte în jurul modelului de limbaj. Acest modul oferă elementele de bază esențiale pentru a interfața eficient cu orice model de limbă, asigurând o integrare și o comunicare perfectă.
Componentele cheie ale modelului I/O
- LLM-uri și modele de chat (utilizate interschimbabil):
- LLM-uri:
- Definiție: Modele de completare a textului pur.
- Intrare ieșire: Luați un șir de text ca intrare și returnați un șir de text ca ieșire.
- Modele de chat
- LLM-uri:
- Definiție: Modele care folosesc un model de limbă ca bază, dar diferă în formatele de intrare și de ieșire.
- Intrare ieșire: Acceptați o listă de mesaje de chat ca intrare și returnați un mesaj de chat.
- Prompts: Modelați, selectați dinamic și gestionați intrările modelului. Permite crearea de solicitări flexibile și specifice contextului care ghidează răspunsurile modelului lingvistic.
- Analizoare de ieșire: Extrageți și formatați informații din ieșirile modelului. Util pentru convertirea rezultatelor brute a modelelor de limbaj în date structurate sau în formate specifice necesare aplicației.
LLM-uri
Integrarea LangChain cu modele de limbaj mari (LLM) precum OpenAI, Cohere și Hugging Face este un aspect fundamental al funcționalității sale. LangChain în sine nu găzduiește LLM-uri, dar oferă o interfață uniformă pentru a interacționa cu diferite LLM-uri.
Această secțiune oferă o prezentare generală a utilizării pachetului OpenAI LLM în LangChain, aplicabil și altor tipuri de LLM. Am instalat deja acest lucru în secțiunea „Noțiuni introductive”. Să inițializam LLM.
from langchain.llms import OpenAI
llm = OpenAI()
- LLM-urile implementează Interfață rulabilă, blocul de bază al LangChain Expression Language (LCEL). Asta înseamnă că ei susțin
invoke
,ainvoke
,stream
,astream
,batch
,abatch
,astream_log
apeluri. - LLM-urile acceptă siruri ca intrări, sau obiecte care pot fi forțate la solicitări șir, inclusiv
List[BaseMessage]
șiPromptValue
. (mai multe despre acestea mai târziu)
Să ne uităm la câteva exemple.
response = llm.invoke("List the seven wonders of the world.")
print(response)
Puteți apela alternativ metoda stream pentru a transmite răspunsul text.
for chunk in llm.stream("Where were the 2012 Olympics held?"): print(chunk, end="", flush=True)
Modele de chat
Integrarea LangChain cu modelele de chat, o variație specializată a modelelor de limbaj, este esențială pentru crearea de aplicații interactive de chat. În timp ce folosesc modele de limbaj intern, modelele de chat prezintă o interfață distinctă centrată pe mesajele de chat ca intrări și ieșiri. Această secțiune oferă o prezentare detaliată a utilizării modelului de chat OpenAI în LangChain.
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI()
Modelele de chat din LangChain funcționează cu diferite tipuri de mesaje, cum ar fi AIMessage
, HumanMessage
, SystemMessage
, FunctionMessage
, și ChatMessage
(cu un parametru de rol arbitrar). În general, HumanMessage
, AIMessage
, și SystemMessage
sunt cele mai des folosite.
Modelele de chat acceptă în primul rând List[BaseMessage]
ca intrări. Șirurile pot fi convertite în HumanMessage
, și PromptValue
este, de asemenea, acceptat.
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)
Prompts
Solicitările sunt esențiale în ghidarea modelelor lingvistice pentru a genera rezultate relevante și coerente. Acestea pot varia de la instrucțiuni simple până la exemple complexe cu câteva fotografii. În LangChain, gestionarea solicitărilor poate fi un proces foarte simplificat, datorită mai multor clase și funcții dedicate.
LangChain's PromptTemplate
class este un instrument versatil pentru crearea de prompturi șir. Folosește Python str.format
sintaxă, permițând generarea dinamică a promptului. Puteți defini un șablon cu substituenți și le puteți completa cu valori specifice după cum este necesar.
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)
Pentru modelele de chat, solicitările sunt mai structurate, implicând mesaje cu roluri specifice. Oferte LangChain ChatPromptTemplate
în acest scop.
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)
Această abordare permite crearea de chatbot-uri interactive, captivante, cu răspunsuri dinamice.
Ambele PromptTemplate
și ChatPromptTemplate
se integrează perfect cu LangChain Expression Language (LCEL), permițându-le să facă parte din fluxuri de lucru mai mari și complexe. Vom discuta mai multe despre asta mai târziu.
Șabloanele de prompt personalizate sunt uneori esențiale pentru sarcini care necesită formatare unică sau instrucțiuni specifice. Crearea unui șablon de prompt personalizat implică definirea variabilelor de intrare și o metodă de formatare personalizată. Această flexibilitate permite LangChain să răspundă unei game largi de cerințe specifice aplicației. Citește mai multe aici.
LangChain acceptă, de asemenea, solicitări cu câteva lovituri, permițând modelului să învețe din exemple. Această caracteristică este vitală pentru sarcinile care necesită înțelegere contextuală sau modele specifice. Șabloanele de prompturi cu câteva fotografii pot fi construite dintr-un set de exemple sau prin utilizarea unui obiect Selector de exemple. Citește mai multe aici.
Analizoare de ieșire
Analizatorii de ieșire joacă un rol crucial în Langchain, permițând utilizatorilor să structureze răspunsurile generate de modelele de limbaj. În această secțiune, vom explora conceptul de analizoare de ieșire și vom oferi exemple de cod folosind PydanticOutputParser, SimpleJsonOutputParser, CommaSeparatedListOutputParser, DatetimeOutputParser și XMLOutputParser Langchain.
PydanticOutputParser
Langchain oferă PydanticOutputParser pentru analizarea răspunsurilor în structurile de date Pydantic. Mai jos este un exemplu pas cu pas al modului de utilizare:
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)
Ieșirea va fi:
SimpleJsonOutputParser
SimpleJsonOutputParser de la Langchain este utilizat atunci când doriți să analizați ieșiri asemănătoare JSON. Iată un exemplu:
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 este util atunci când doriți să extrageți liste separate prin virgulă din răspunsurile modelului. Iată un exemplu:
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 de la Langchain este conceput pentru a analiza informațiile datetime. Iată cum să-l folosești:
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)
Aceste exemple arată cum analizoarele de ieșire ale Langchain pot fi utilizate pentru a structura diferite tipuri de răspunsuri model, făcându-le potrivite pentru diferite aplicații și formate. Analizatoarele de ieșire sunt un instrument valoros pentru îmbunătățirea gradului de utilizare și interpretabilității rezultatelor modelului de limbaj în Langchain.
Automatizați sarcinile și fluxurile de lucru manuale cu generatorul nostru de flux de lucru bazat pe inteligență artificială, conceput de Nanonets pentru dvs. și echipele dvs.
Modulul II: Recuperare
Recuperarea în LangChain joacă un rol crucial în aplicațiile care necesită date specifice utilizatorului, care nu sunt incluse în setul de antrenament al modelului. Acest proces, cunoscut sub numele de Retrieval Augmented Generation (RAG), implică preluarea datelor externe și integrarea acestora în procesul de generare a modelului de limbaj. LangChain oferă o suită cuprinzătoare de instrumente și funcționalități pentru a facilita acest proces, găzduind atât aplicațiile simple, cât și cele complexe.
LangChain realizează recuperarea printr-o serie de componente pe care le vom discuta una câte una.
Încărcătoare de documente
Încărcătoarele de documente din LangChain permit extragerea datelor din diverse surse. Cu peste 100 de încărcătoare disponibile, aceștia acceptă o gamă largă de tipuri de documente, aplicații și surse (buckets s3 private, site-uri web publice, baze de date).
Puteți alege un încărcător de documente în funcție de cerințele dvs aici.
Toate aceste încărcătoare ingerează date în Document clase. Vom învăța mai târziu cum să folosim datele ingerate în clasele Document.
Încărcător de fișiere text: Încărcați un simplu .txt
dosar într-un document.
from langchain.document_loaders import TextLoader loader = TextLoader("./sample.txt")
document = loader.load()
Încărcător CSV: Încărcați un fișier CSV într-un document.
from langchain.document_loaders.csv_loader import CSVLoader loader = CSVLoader(file_path='./example_data/sample.csv')
documents = loader.load()
Putem alege să personalizăm parsarea specificând numele câmpurilor -
loader = CSVLoader(file_path='./example_data/mlb_teams_2012.csv', csv_args={ 'delimiter': ',', 'quotechar': '"', 'fieldnames': ['MLB Team', 'Payroll in millions', 'Wins']
})
documents = loader.load()
Încărcătoare PDF: Încărcătoarele PDF din LangChain oferă diferite metode pentru analizarea și extragerea conținutului din fișierele PDF. Fiecare încărcător răspunde cerințelor diferite și utilizează biblioteci subiacente diferite. Mai jos sunt exemple detaliate pentru fiecare încărcător.
PyPDFLoader este utilizat pentru analizarea de bază a PDF-urilor.
from langchain.document_loaders import PyPDFLoader loader = PyPDFLoader("example_data/layout-parser-paper.pdf")
pages = loader.load_and_split()
MathPixLoader este ideal pentru extragerea de conținut matematic și diagrame.
from langchain.document_loaders import MathpixPDFLoader loader = MathpixPDFLoader("example_data/math-content.pdf")
data = loader.load()
PyMuPDFLoader este rapid și include extragerea detaliată a metadatelor.
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 este folosit pentru un control mai granular asupra extragerii textului.
from langchain.document_loaders import PDFMinerLoader loader = PDFMinerLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
AmazonTextractPDFParser utilizează AWS Textract pentru OCR și alte funcții avansate de analiză PDF.
from langchain.document_loaders import AmazonTextractPDFLoader # Requires AWS account and configuration
loader = AmazonTextractPDFLoader("example_data/complex-layout.pdf")
documents = loader.load()
PDFMinerPDFasHTMLLoader generează HTML din PDF pentru analiza semantică.
from langchain.document_loaders import PDFMinerPDFasHTMLLoader loader = PDFMinerPDFasHTMLLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
PDFPlumberLoader oferă metadate detaliate și acceptă un document pe pagină.
from langchain.document_loaders import PDFPlumberLoader loader = PDFPlumberLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
Încărcătoare integrate: LangChain oferă o mare varietate de încărcătoare personalizate pentru a încărca direct date din aplicațiile dvs. (cum ar fi Slack, Sigma, Notion, Confluence, Google Drive și multe altele) și baze de date și pentru a le utiliza în aplicațiile LLM.
Lista completă este aici.
Mai jos sunt câteva exemple pentru a ilustra acest lucru -
Exemplul I – Slack
Slack, o platformă de mesagerie instantanee utilizată pe scară largă, poate fi integrată în fluxurile de lucru și aplicațiile LLM.
- Accesați pagina dvs. Slack Workspace Management.
- Navigheaza catre
{your_slack_domain}.slack.com/services/export
. - Selectați intervalul de date dorit și inițiați exportul.
- Slack notifică prin e-mail și DM odată ce exportul este gata.
- Exportul are ca rezultat a
.zip
fișier aflat în folderul Descărcări sau în calea de descărcare desemnată. - Atribuiți calea fișierului descărcat
.zip
fișier deLOCAL_ZIPFILE
. - Folosește
SlackDirectoryLoader
de lalangchain.document_loaders
pachet.
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)
Exemplul II – Figma
Figma, un instrument popular pentru proiectarea interfeței, oferă un API REST pentru integrarea datelor.
- Obțineți cheia fișierului Figma din formatul URL:
https://www.figma.com/file/{filekey}/sampleFilename
. - ID-urile nodurilor se găsesc în parametrul URL
?node-id={node_id}
. - Generați un token de acces urmând instrucțiunile de la Centrul de ajutor Figma.
-
FigmaFileLoader
clasa de lalangchain.document_loaders.figma
este folosit pentru a încărca datele Figma. - Diverse module LangChain, cum ar fi
CharacterTextSplitter
,ChatOpenAI
, etc., sunt angajați pentru prelucrare.
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
funcția utilizează datele Figma pentru a crea cod HTML/CSS. - Utilizează o conversație șablon cu un model bazat pe 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
funcția, când este executată, returnează codul HTML/CSS bazat pe intrarea de proiectare Figma.
Să ne folosim acum cunoștințele pentru a crea câteva seturi de documente.
Încărcăm mai întâi un PDF, raportul anual de sustenabilitate BCG.
Pentru aceasta folosim PyPDFLoader.
from langchain.document_loaders import PyPDFLoader loader = PyPDFLoader("bcg-2022-annual-sustainability-report-apr-2023.pdf")
pdfpages = loader.load_and_split()
Vom ingera date de la Airtable acum. Avem un Airtable care conține informații despre diverse OCR și modele de extracție a datelor -
Să folosim AirtableLoader pentru aceasta, care se găsește în lista încărcătoarelor integrate.
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()
Să continuăm acum și să învățăm cum să folosim aceste clase de documente.
Transformatori de documente
Transformatoarele de documente din LangChain sunt instrumente esențiale concepute pentru a manipula documente, pe care le-am creat în subsecțiunea anterioară.
Acestea sunt utilizate pentru sarcini precum împărțirea documentelor lungi în bucăți mai mici, combinarea și filtrarea, care sunt cruciale pentru adaptarea documentelor la fereastra de context a unui model sau pentru satisfacerea nevoilor specifice ale aplicației.
Un astfel de instrument este RecursiveCharacterTextSplitter, un divizor de text versatil care utilizează o listă de caractere pentru împărțire. Permite parametri precum dimensiunea bucăților, suprapunerea și indexul de pornire. Iată un exemplu despre cum este folosit în 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])
Un alt instrument este CharacterTextSplitter, care împarte textul pe baza unui caracter specificat și include controale pentru dimensiunea și suprapunerea bucăților:
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 este conceput pentru a împărți conținutul HTML pe baza etichetelor de antet, păstrând structura semantică:
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])
O manipulare mai complexă poate fi realizată prin combinarea HTMLHeaderTextSplitter cu un alt splitter, cum ar fi 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 oferă, de asemenea, splittere specifice pentru diferite limbaje de programare, cum ar fi Python Code Splitter și JavaScript Code Splitter:
from langchain.text_splitter import RecursiveCharacterTextSplitter, Language python_code = """
def hello_world(): print("Hello, World!")
hello_world() """ python_splitter = RecursiveCharacterTextSplitter.from_language( language=Language.PYTHON, chunk_size=50
)
python_docs = python_splitter.create_documents([python_code])
print(python_docs[0]) js_code = """
function helloWorld() { console.log("Hello, World!");
}
helloWorld(); """ js_splitter = RecursiveCharacterTextSplitter.from_language( language=Language.JS, chunk_size=60
)
js_docs = js_splitter.create_documents([js_code])
print(js_docs[0])
Pentru împărțirea textului pe baza numărului de simboluri, care este utilă pentru modelele de limbă cu limite de simboluri, este utilizat 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])
În cele din urmă, LongContextReorder reordonează documentele pentru a preveni degradarea performanței în modele din cauza contextelor lungi:
from langchain.document_transformers import LongContextReorder reordering = LongContextReorder()
reordered_docs = reordering.transform_documents(docs)
print(reordered_docs[0])
Aceste instrumente demonstrează diferite modalități de transformare a documentelor în LangChain, de la simpla împărțire a textului la reordonarea complexă și împărțirea specifică limbii. Pentru cazuri de utilizare mai aprofundate și specifice, ar trebui consultată secțiunea de documentație și integrări LangChain.
În exemplele noastre, încărcătoarele au creat deja documente fragmentate pentru noi, iar această parte este deja gestionată.
Modele de încorporare a textului
Modelele de încorporare a textului în LangChain oferă o interfață standardizată pentru diverși furnizori de modele de încorporare precum OpenAI, Cohere și Hugging Face. Aceste modele transformă textul în reprezentări vectoriale, permițând operații precum căutarea semantică prin similaritatea textului în spațiul vectorial.
Pentru a începe cu modelele de încorporare a textului, de obicei trebuie să instalați anumite pachete și să configurați chei API. Am făcut deja acest lucru pentru OpenAI
În LangChain, embed_documents
metoda este utilizată pentru a încorpora mai multe texte, oferind o listă de reprezentări vectoriale. De exemplu:
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]))
Pentru încorporarea unui singur text, cum ar fi o interogare de căutare, embed_query
se foloseste metoda. Acest lucru este util pentru a compara o interogare cu un set de încorporare a documentelor. De exemplu:
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])
Înțelegerea acestor înglobări este crucială. Fiecare bucată de text este convertită într-un vector, a cărui dimensiune depinde de modelul utilizat. De exemplu, modelele OpenAI produc de obicei vectori cu 1536 de dimensiuni. Aceste înglobări sunt apoi utilizate pentru preluarea informațiilor relevante.
Funcționalitatea de încorporare a LangChain nu se limitează la OpenAI, ci este concepută pentru a funcționa cu diverși furnizori. Configurarea și utilizarea pot diferi ușor în funcție de furnizor, dar conceptul de bază de încorporare a textelor în spațiul vectorial rămâne același. Pentru utilizare detaliată, inclusiv configurații avansate și integrări cu diferiți furnizori de modele de încorporare, documentația LangChain din secțiunea Integrari este o resursă valoroasă.
Magazine Vector
Magazinele Vector din LangChain acceptă stocarea și căutarea eficientă a înglobărilor de text. LangChain se integrează cu peste 50 de magazine de vectori, oferind o interfață standardizată pentru ușurință în utilizare.
Exemplu: stocarea și căutarea înglobărilor
După încorporarea textelor, le putem stoca într-un magazin de vectori precum Chroma
și efectuați căutări de similaritate:
from langchain.vectorstores import Chroma db = Chroma.from_texts(embedded_texts)
similar_texts = db.similarity_search("search query")
Să folosim alternativ magazinul de vectori FAISS pentru a crea indecși pentru documentele noastre.
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS pdfstore = FAISS.from_documents(pdfpages, embedding=OpenAIEmbeddings()) airtablestore = FAISS.from_documents(airtabledocs, embedding=OpenAIEmbeddings())
copoi
Retriever-urile din LangChain sunt interfețe care returnează documente ca răspuns la o interogare nestructurată. Ele sunt mai generale decât magazinele vectoriale, concentrându-se mai degrabă pe recuperare decât pe stocare. Deși magazinele de vectori pot fi folosite ca coloană vertebrală a unui retriever, există și alte tipuri de retriever.
Pentru a configura un retriever Chroma, mai întâi îl instalați folosind pip install chromadb
. Apoi, încărcați, împărțiți, încorporați și preluați documente folosind o serie de comenzi Python. Iată un exemplu de cod pentru configurarea unui retriever Chroma:
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma full_text = open("state_of_the_union.txt", "r").read()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
texts = text_splitter.split_text(full_text) embeddings = OpenAIEmbeddings()
db = Chroma.from_texts(texts, embeddings)
retriever = db.as_retriever() retrieved_docs = retriever.invoke("What did the president say about Ketanji Brown Jackson?")
print(retrieved_docs[0].page_content)
MultiQueryRetriever automatizează reglarea promptă prin generarea de interogări multiple pentru o interogare de intrare de utilizator și combină rezultatele. Iată un exemplu de utilizare simplă a acestuia:
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))
Comprimarea contextuală în LangChain comprimă documentele preluate folosind contextul interogării, asigurându-se că sunt returnate numai informații relevante. Aceasta implică reducerea conținutului și filtrarea documentelor mai puțin relevante. Următorul exemplu de cod arată cum să utilizați 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 combină diferiți algoritmi de recuperare pentru a obține performanțe mai bune. Un exemplu de combinare a BM25 și FAISS Retrievers este prezentat în următorul cod:
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 din LangChain permite interogarea documentelor cu mai mulți vectori per document, ceea ce este util pentru capturarea diferitelor aspecte semantice într-un document. Metodele pentru crearea mai multor vectori includ împărțirea în bucăți mai mici, rezumarea sau generarea de întrebări ipotetice. Pentru împărțirea documentelor în bucăți mai mici, se poate folosi următorul cod 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)))
Generarea de rezumate pentru o recuperare mai bună datorită reprezentării mai concentrate a conținutului este o altă metodă. Iată un exemplu de generare a rezumatelor:
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)))
Generarea de întrebări ipotetice relevante pentru fiecare document folosind LLM este o altă abordare. Acest lucru se poate face cu următorul cod:
functions = [{"name": "hypothetical_questions", "parameters": {"questions": {"type": "array", "items": {"type": "string"}}}}]
from langchain.output_parsers.openai_functions import JsonKeyOutputFunctionsParser chain = (lambda x: x.page_content) | ChatPromptTemplate.from_template("Generate 3 hypothetical questions:nn{doc}") | ChatOpenAI(max_retries=0).bind(functions=functions, function_call={"name": "hypothetical_questions"}) | JsonKeyOutputFunctionsParser(key_name="questions")
hypothetical_questions = chain.batch(docs, {"max_concurrency": 5}) question_docs = [Document(page_content=q, metadata={id_key: doc_ids[i]}) for i, questions in enumerate(hypothetical_questions) for q in questions]
retriever.vectorstore.add_documents(question_docs)
retriever.docstore.mset(list(zip(doc_ids, docs)))
Parent Document Retriever este un alt retriever care atinge un echilibru între acuratețea încorporarii și păstrarea contextului prin stocarea unor bucăți mici și preluarea documentelor părinte mai mari. Implementarea sa este după cum urmează:
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")
Un retriever cu autointerogare construiește interogări structurate din intrări în limbaj natural și le aplică VectorStore-ului său de bază. Implementarea sa este prezentată în următorul cod:
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 efectuează cercetări web pe baza unei anumite interogări -
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")
Pentru exemplele noastre, putem folosi, de asemenea, retrieverul standard deja implementat ca parte a obiectului nostru de stocare vectorială, după cum urmează -
Acum îi putem interoga pe retrievers. Rezultatul interogării noastre va fi obiecte document relevante pentru interogare. Acestea vor fi utilizate în cele din urmă pentru a crea răspunsuri relevante în secțiunile ulterioare.
Automatizați sarcinile și fluxurile de lucru manuale cu generatorul nostru de flux de lucru bazat pe inteligență artificială, conceput de Nanonets pentru dvs. și echipele dvs.
Modulul III: Agenți
LangChain introduce un concept puternic numit „Agenți” care duce ideea de lanțuri la un nivel cu totul nou. Agenții folosesc modele de limbaj pentru a determina în mod dinamic secvențele de acțiuni de efectuat, făcându-le incredibil de versatile și adaptabile. Spre deosebire de lanțurile tradiționale, în care acțiunile sunt codificate în cod, agenții folosesc modele de limbaj ca motoare de raționament pentru a decide ce acțiuni să întreprindă și în ce ordine.
Agentul este componenta de bază responsabilă de luarea deciziilor. Acesta valorifică puterea unui model de limbaj și un prompt pentru a determina următorii pași pentru atingerea unui obiectiv specific. Intrările către un agent includ de obicei:
- Unelte: Descrieri ale instrumentelor disponibile (mai multe despre aceasta mai târziu).
- Intrare utilizator: Obiectivul de nivel înalt sau interogarea de la utilizator.
- Etape intermediare: Un istoric al perechilor (acțiuni, instrumente) executate pentru a ajunge la intrarea curentă a utilizatorului.
Ieșirea unui agent poate fi următoarea acțiune a lua măsuri (AgentAcțiuni) sau finala răspuns pentru a trimite utilizatorului (Agent Finish). Un acțiune specifică a instrument si intrare pentru acel instrument.
Instrumente
Instrumentele sunt interfețe pe care un agent le poate folosi pentru a interacționa cu lumea. Acestea permit agenților să efectueze diverse sarcini, cum ar fi căutarea pe web, rularea comenzilor shell sau accesarea API-urilor externe. În LangChain, instrumentele sunt esențiale pentru extinderea capacităților agenților și pentru a le permite să îndeplinească diverse sarcini.
Pentru a utiliza instrumente în LangChain, le puteți încărca folosind următorul fragment:
from langchain.agents import load_tools tool_names = [...]
tools = load_tools(tool_names)
Unele instrumente pot necesita un model de limbă de bază (LLM) pentru inițializare. În astfel de cazuri, puteți promova și un LLM:
from langchain.agents import load_tools tool_names = [...]
llm = ...
tools = load_tools(tool_names, llm=llm)
Această configurare vă permite să accesați o varietate de instrumente și să le integrați în fluxurile de lucru ale agentului dvs. Lista completă a instrumentelor cu documentație de utilizare este aici.
Să ne uităm la câteva exemple de instrumente.
DuckDuckGo
Instrumentul DuckDuckGo vă permite să efectuați căutări web folosind motorul său de căutare. Iată cum să-l folosești:
from langchain.tools import DuckDuckGoSearchRun
search = DuckDuckGoSearchRun()
search.run("manchester united vs luton town match summary")
DataForSeo
Setul de instrumente DataForSeo vă permite să obțineți rezultate ale motorului de căutare folosind API-ul DataForSeo. Pentru a utiliza acest set de instrumente, va trebui să vă configurați acreditările API. Iată cum să configurați acreditările:
import os os.environ["DATAFORSEO_LOGIN"] = "<your_api_access_username>"
os.environ["DATAFORSEO_PASSWORD"] = "<your_api_access_password>"
Odată ce acreditările sunt setate, puteți crea un DataForSeoAPIWrapper
instrument pentru a accesa API:
from langchain.utilities.dataforseo_api_search import DataForSeoAPIWrapper wrapper = DataForSeoAPIWrapper() result = wrapper.run("Weather in Los Angeles")
DataForSeoAPIWrapper
Instrumentul preia rezultatele motorului de căutare din diverse surse.
Puteți personaliza tipul de rezultate și câmpuri returnate în răspunsul JSON. De exemplu, puteți specifica tipurile de rezultate, câmpurile și puteți seta un număr maxim pentru numărul de rezultate de top de returnat:
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")
Acest exemplu personalizează răspunsul JSON specificând tipurile de rezultate, câmpurile și limitând numărul de rezultate.
De asemenea, puteți specifica locația și limba pentru rezultatele căutării prin transmiterea unor parametri suplimentari în wrapper-ului 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")
Prin furnizarea de parametri de locație și de limbă, vă puteți adapta rezultatele căutării la anumite regiuni și limbi.
Aveți flexibilitatea de a alege motorul de căutare pe care doriți să îl utilizați. Pur și simplu specificați motorul de căutare dorit:
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")
În acest exemplu, căutarea este personalizată pentru a utiliza Bing ca motor de căutare.
Wrapper-ul API vă permite, de asemenea, să specificați tipul de căutare pe care doriți să o efectuați. De exemplu, puteți efectua o căutare pe hărți:
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")
Aceasta personalizează căutarea pentru a prelua informații legate de hărți.
Shell (bash)
Setul de instrumente Shell oferă agenților acces la mediul shell, permițându-le să execute comenzi shell. Această caracteristică este puternică, dar trebuie utilizată cu prudență, în special în mediile cu nisip. Iată cum puteți utiliza instrumentul Shell:
from langchain.tools import ShellTool shell_tool = ShellTool() result = shell_tool.run({"commands": ["echo 'Hello World!'", "time"]})
În acest exemplu, instrumentul Shell rulează două comenzi shell: ecou „Hello World!” și afișarea orei curente.
Puteți furniza instrumentul Shell unui agent pentru a efectua sarcini mai complexe. Iată un exemplu de agent care preia link-uri de pe o pagină web folosind instrumentul 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."
)
În acest scenariu, agentul folosește instrumentul Shell pentru a executa o secvență de comenzi pentru a prelua, filtra și sorta adresele URL dintr-o pagină web.
Exemplele oferite demonstrează unele dintre instrumentele disponibile în LangChain. Aceste instrumente extind în cele din urmă capacitățile agenților (explorate în subsecțiunea următoare) și le împuternicesc să îndeplinească diferite sarcini în mod eficient. În funcție de cerințele dvs., puteți alege instrumentele și seturile de instrumente care se potrivesc cel mai bine nevoilor proiectului dvs. și le puteți integra în fluxurile de lucru ale agentului dvs.
Înapoi la agenți
Să trecem la agenți acum.
AgentExecutor este mediul de rulare pentru un agent. Este responsabil pentru apelarea agentului, executarea acțiunilor pe care le selectează, transmiterea rezultatelor acțiunii înapoi agentului și repetarea procesului până când agentul termină. În pseudocod, AgentExecutor ar putea arăta cam așa:
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 se ocupă de diverse complexități, cum ar fi tratarea cazurilor în care agentul selectează un instrument inexistent, gestionarea erorilor instrumentului, gestionarea rezultatelor produse de agent și furnizarea de jurnalizare și observabilitate la toate nivelurile.
În timp ce clasa AgentExecutor este timpul de execuție principal al agentului în LangChain, sunt acceptate și alte runtime mai experimentale, inclusiv:
- Agent de planificare și execuție
- Baby AGI
- GPT automat
Pentru a înțelege mai bine cadrul agentului, să construim un agent de bază de la zero și apoi să trecem la explorarea agenților pre-construiți.
Înainte de a ne aprofunda în construirea agentului, este esențial să revizuim câteva terminologii și schema cheie:
- Acțiune agent: Aceasta este o clasă de date care reprezintă acțiunea pe care ar trebui să o întreprindă un agent. Este format dintr-un
tool
proprietate (numele instrumentului de invocat) și atool_input
proprietate (intrarea pentru acel instrument). - Agent Finish: Această clasă de date indică faptul că agentul și-a încheiat sarcina și ar trebui să returneze un răspuns utilizatorului. Acesta include de obicei un dicționar de valori returnate, adesea cu o „ieșire” cheie care conține textul răspunsului.
- Etape intermediare: Acestea sunt înregistrările acțiunilor anterioare ale agentului și ale rezultatelor corespunzătoare. Ele sunt cruciale pentru transmiterea contextului la iterațiile viitoare ale agentului.
În exemplul nostru, vom folosi OpenAI Function Calling pentru a ne crea agentul. Această abordare este de încredere pentru crearea de agenți. Vom începe prin a crea un instrument simplu care calculează lungimea unui cuvânt. Acest instrument este util deoarece modelele de limbaj pot face uneori greșeli din cauza tokenizării atunci când numără lungimile cuvintelor.
Mai întâi, să încărcăm modelul de limbaj pe care îl vom folosi pentru a controla agentul:
from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
Să testăm modelul cu un calcul al lungimii cuvântului:
llm.invoke("how many letters in the word educa?")
Răspunsul trebuie să indice numărul de litere din cuvântul „educa”.
În continuare, vom defini o funcție simplă Python pentru a calcula lungimea unui cuvânt:
from langchain.agents import tool @tool
def get_word_length(word: str) -> int: """Returns the length of a word.""" return len(word)
Am creat un instrument numit get_word_length
care ia un cuvânt ca intrare și returnează lungimea acestuia.
Acum, să creăm promptul pentru agent. Promptul informează agentul despre cum să raționeze și să formateze rezultatul. În cazul nostru, folosim OpenAI Function Calling, care necesită instrucțiuni minime. Vom defini promptul cu substituenți pentru introducerea utilizatorului și blocul de date al agentului:
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"), ]
)
Acum, de unde știe agentul ce instrumente poate folosi? Ne bazăm pe modele de limbaj de apelare a funcției OpenAI, care necesită ca funcțiile să fie transmise separat. Pentru a furniza instrumentele noastre agentului, le vom formata ca apeluri de funcție 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])
Acum, putem crea agentul prin definirea mapărilor de intrare și conectarea componentelor:
Acesta este limbajul LCEL. Vom discuta acest lucru mai târziu în detaliu.
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()
)
Am creat agentul nostru, care înțelege introducerea utilizatorului, folosește instrumentele disponibile și formatează ieșirea. Acum, să interacționăm cu el:
agent.invoke({"input": "how many letters in the word educa?", "intermediate_steps": []})
Agentul ar trebui să răspundă cu o acțiune AgentAction, indicând următoarea acțiune de întreprins.
Am creat agentul, dar acum trebuie să scriem un timp de execuție pentru el. Cel mai simplu timp de rulare este cel care apelează continuu agentul, execută acțiuni și se repetă până când agentul termină. Iată un exemplu:
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)
În această buclă, apelăm în mod repetat agentul, executăm acțiuni și actualizăm pașii intermediari până când agentul termină. De asemenea, ne ocupăm de interacțiunile instrumentelor în buclă.
Pentru a simplifica acest proces, LangChain oferă clasa AgentExecutor, care încapsulează execuția agentului și oferă gestionarea erorilor, oprirea timpurie, urmărirea și alte îmbunătățiri. Să folosim AgentExecutor pentru a interacționa cu agentul:
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 simplifică procesul de execuție și oferă o modalitate convenabilă de a interacționa cu agentul.
Memoria este, de asemenea, discutată în detaliu mai târziu.
Agentul pe care l-am creat până acum este apatrid, ceea ce înseamnă că nu își amintește interacțiunile anterioare. Pentru a permite întrebări și conversații ulterioare, trebuie să adăugăm memorie agentului. Aceasta implică doi pași:
- Adăugați o variabilă de memorie în prompt pentru a stoca istoricul chatului.
- Urmăriți istoricul chatului în timpul interacțiunilor.
Să începem prin a adăuga un substituent de memorie în prompt:
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"), ]
)
Acum, creați o listă pentru a urmări istoricul chat-ului:
from langchain.schema.messages import HumanMessage, AIMessage chat_history = []
În pasul de creare a agentului, vom include și memoria:
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()
)
Acum, când rulați agentul, asigurați-vă că actualizați istoricul chat-ului:
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})
Acest lucru îi permite agentului să mențină un istoric de conversație și să răspundă la întrebările ulterioare pe baza interacțiunilor anterioare.
Felicitări! Ați creat și executat cu succes primul dvs. agent end-to-end în LangChain. Pentru a aprofunda capacitățile LangChain, puteți explora:
- Sunt acceptate diferite tipuri de agenți.
- Agenți preconstruiți
- Cum să lucrați cu instrumente și integrări de instrumente.
Tipuri de agenți
LangChain oferă diferite tipuri de agenți, fiecare potrivit pentru cazuri de utilizare specifice. Iată câțiva dintre agenții disponibili:
- Zero-shot ReAct: Acest agent folosește cadrul ReAct pentru a alege instrumentele bazate exclusiv pe descrierile lor. Necesită descrieri pentru fiecare instrument și este foarte versatil.
- Intrare structurată ReAct: Acest agent se ocupă de instrumente cu mai multe intrări și este potrivit pentru sarcini complexe, cum ar fi navigarea într-un browser web. Utilizează o schemă de argumente a instrumentelor pentru intrarea structurată.
- Funcții OpenAI: Proiectat special pentru modele reglate fin pentru apeluri de funcții, acest agent este compatibil cu modele precum gpt-3.5-turbo-0613 și gpt-4-0613. Am folosit acest lucru pentru a crea primul nostru agent de mai sus.
- De conversaţie: Conceput pentru setările conversaționale, acest agent folosește ReAct pentru selectarea instrumentului și folosește memoria pentru a reține interacțiunile anterioare.
- Întrebare automată cu căutare: Acest agent se bazează pe un singur instrument, „Răspuns intermediar”, care caută răspunsuri concrete la întrebări. Este echivalent cu auto-cererea originală cu hârtie de căutare.
- Magazin de documente ReAct: Acest agent interacționează cu un depozit de documente folosind cadrul ReAct. Necesită instrumente „Căutare” și „Căutare” și este similar cu exemplul Wikipedia din lucrarea originală ReAct.
Explorați aceste tipuri de agenți pentru a-l găsi pe cel care se potrivește cel mai bine nevoilor dvs. în LangChain. Acești agenți vă permit să legați un set de instrumente în cadrul lor pentru a gestiona acțiuni și a genera răspunsuri. Aflați mai multe pe cum să-ți construiești propriul agent cu instrumente aici.
Agenți preconstruiți
Să continuăm explorarea agenților, concentrându-ne pe agenți preconstruiți disponibili în LangChain.
Gmail
LangChain oferă un set de instrumente Gmail care vă permite să vă conectați e-mailul LangChain la API-ul Gmail. Pentru a începe, va trebui să vă configurați acreditările, care sunt explicate în documentația Gmail API. Odată ce ați descărcat credentials.json
fișier, puteți continua cu utilizarea API-ului Gmail. În plus, va trebui să instalați câteva biblioteci necesare folosind următoarele comenzi:
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
Puteți crea setul de instrumente Gmail după cum urmează:
from langchain.agents.agent_toolkits import GmailToolkit toolkit = GmailToolkit()
De asemenea, puteți personaliza autentificarea în funcție de nevoile dvs. În culise, o resursă googleapi este creată folosind următoarele metode:
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)
Setul de instrumente oferă diverse instrumente care pot fi utilizate în cadrul unui agent, inclusiv:
GmailCreateDraft
: Creați o schiță de e-mail cu câmpurile specificate pentru mesaje.GmailSendMessage
: Trimite mesaje de e-mail.GmailSearch
: Căutați mesaje de e-mail sau fire.GmailGetMessage
: Preluați un e-mail prin ID-ul mesajului.GmailGetThread
: Căutați mesaje de e-mail.
Pentru a utiliza aceste instrumente într-un agent, puteți inițializa agentul după cum urmează:
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,
)
Iată câteva exemple despre cum pot fi utilizate aceste instrumente:
- Creați o schiță Gmail pentru editare:
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."
)
- Căutați cel mai recent e-mail în schițele dvs.:
agent.run("Could you search in my drafts for the latest email?")
Aceste exemple demonstrează capacitățile setului de instrumente Gmail LangChain în cadrul unui agent, permițându-vă să interacționați cu Gmail în mod programatic.
Agent de bază de date SQL
Această secțiune oferă o prezentare generală a unui agent proiectat să interacționeze cu bazele de date SQL, în special baza de date Chinook. Acest agent poate răspunde la întrebări generale despre o bază de date și poate recupera din erori. Vă rugăm să rețineți că este încă în dezvoltare activă și că nu toate răspunsurile pot fi corecte. Fiți atenți când îl rulați pe date sensibile, deoarece poate efectua instrucțiuni DML în baza de date.
Pentru a utiliza acest agent, îl puteți inițializa după cum urmează:
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,
)
Acest agent poate fi inițializat folosind ZERO_SHOT_REACT_DESCRIPTION
tipul de agent. Este conceput pentru a răspunde la întrebări și pentru a oferi descrieri. Alternativ, puteți inițializa agentul folosind OPENAI_FUNCTIONS
tip de agent cu modelul OpenAI GPT-3.5-turbo, pe care l-am folosit la clientul nostru anterior.
Declinare a responsabilităţii
- Lanțul de interogări poate genera interogări de inserare/actualizare/ștergere. Fiți precaut și utilizați un prompt personalizat sau creați un utilizator SQL fără permisiuni de scriere, dacă este necesar.
- Rețineți că executarea anumitor interogări, cum ar fi „rulați cea mai mare interogare posibilă”, ar putea supraîncărca baza de date SQL, mai ales dacă conține milioane de rânduri.
- Bazele de date orientate spre depozit de date acceptă adesea cote la nivel de utilizator pentru a limita utilizarea resurselor.
Puteți cere agentului să descrie un tabel, cum ar fi tabelul „playlisttrack”. Iată un exemplu despre cum să o faci:
agent_executor.run("Describe the playlisttrack table")
Agentul va furniza informații despre schema tabelului și rândurile eșantion.
Dacă întrebați din greșeală despre un tabel care nu există, agentul poate recupera și furniza informații despre cel mai apropiat tabel care se potrivește. De exemplu:
agent_executor.run("Describe the playlistsong table")
Agentul va găsi cel mai apropiat tabel de potrivire și va oferi informații despre acesta.
De asemenea, puteți cere agentului să execute interogări în baza de date. De exemplu:
agent_executor.run("List the total sales per country. Which country's customers spent the most?")
Agentul va executa interogarea și va furniza rezultatul, cum ar fi țara cu cele mai mari vânzări totale.
Pentru a obține numărul total de melodii din fiecare listă de redare, puteți utiliza următoarea interogare:
agent_executor.run("Show the total number of tracks in each playlist. The Playlist name should be included in the result.")
Agentul va returna numele listelor de redare împreună cu numărul total de melodii corespunzător.
În cazurile în care agentul întâmpină erori, acesta poate recupera și poate oferi răspunsuri precise. De exemplu:
agent_executor.run("Who are the top 3 best selling artists?")
Chiar și după ce a întâlnit o eroare inițială, agentul se va ajusta și va oferi răspunsul corect, care, în acest caz, este primii 3 artiști cei mai vânduți.
Agent Pandas DataFrame
Această secțiune prezintă un agent conceput pentru a interacționa cu Pandas DataFrames în scopuri de răspunsuri la întrebări. Vă rugăm să rețineți că acest agent utilizează agentul Python sub capotă pentru a executa codul Python generat de un model de limbaj (LLM). Fiți atenți când utilizați acest agent pentru a preveni potențialele daune cauzate de codul Python rău intenționat generat de LLM.
Puteți inițializa agentul Pandas DataFrame după cum urmează:
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,
# )
Puteți cere agentului să numere numărul de rânduri din DataFrame:
agent.run("how many rows are there?")
Agentul va executa codul df.shape[0]
și furnizați răspunsul, cum ar fi „Există 891 de rânduri în cadrul de date”.
De asemenea, puteți cere agentului să filtreze rândurile pe baza unor criterii specifice, cum ar fi găsirea numărului de persoane cu mai mult de 3 frați:
agent.run("how many people have more than 3 siblings")
Agentul va executa codul df[df['SibSp'] > 3].shape[0]
și oferiți răspunsul, cum ar fi „30 de persoane au mai mult de 3 frați”.
Dacă doriți să calculați rădăcina pătrată a vârstei medii, puteți întreba agentul:
agent.run("whats the square root of the average age?")
Agentul va calcula vârsta medie folosind df['Age'].mean()
și apoi calculați rădăcina pătrată folosind math.sqrt()
. Acesta va oferi răspunsul, cum ar fi „Rădăcina pătrată a vârstei medii este 5.449689683556195”.
Să creăm o copie a DataFrame, iar valorile de vârstă lipsă sunt completate cu vârsta medie:
df1 = df.copy()
df1["Age"] = df1["Age"].fillna(df1["Age"].mean())
Apoi, puteți inițializa agentul cu ambele DataFrames și îi puteți adresa o întrebare:
agent = create_pandas_dataframe_agent(OpenAI(temperature=0), [df, df1], verbose=True)
agent.run("how many rows in the age column are different?")
Agentul va compara coloanele de vârstă din ambele DataFrames și va oferi răspunsul, cum ar fi „177 de rânduri în coloana de vârstă sunt diferite”.
Setul de instrumente Jira
Această secțiune explică cum să utilizați setul de instrumente Jira, care permite agenților să interacționeze cu o instanță Jira. Puteți efectua diverse acțiuni, cum ar fi căutarea problemelor și crearea de probleme folosind acest set de instrumente. Utilizează biblioteca atlassian-python-api. Pentru a utiliza acest set de instrumente, trebuie să setați variabile de mediu pentru instanța dvs. Jira, inclusiv JIRA_API_TOKEN, JIRA_USERNAME și JIRA_INSTANCE_URL. În plus, poate fi necesar să setați cheia API OpenAI ca variabilă de mediu.
Pentru a începe, instalați biblioteca atlassian-python-api și setați variabilele de mediu necesare:
%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
)
Puteți solicita agentului să creeze o nouă problemă într-un anumit proiect cu un rezumat și o descriere:
agent.run("make a new issue in project PW to remind me to make more fried rice")
Agentul va executa acțiunile necesare pentru a crea problema și va oferi un răspuns, cum ar fi „O problemă nouă a fost creată în proiectul PW cu rezumatul „Fă mai mult orez prăjit” și descrierea „Memento pentru a face mai mult orez prăjit”.
Acest lucru vă permite să interacționați cu instanța dvs. Jira folosind instrucțiuni în limbaj natural și setul de instrumente Jira.
Automatizați sarcinile și fluxurile de lucru manuale cu generatorul nostru de flux de lucru bazat pe inteligență artificială, conceput de Nanonets pentru dvs. și echipele dvs.
Modulul IV: Lanțuri
LangChain este un instrument conceput pentru utilizarea modelelor de limbaj mari (LLM) în aplicații complexe. Acesta oferă cadre pentru crearea lanțurilor de componente, inclusiv LLM-uri și alte tipuri de componente. Două cadre primare
- Limbajul de expresie LangChain (LCEL)
- Interfață Legacy Chain
LangChain Expression Language (LCEL) este o sintaxă care permite compunerea intuitivă a lanțurilor. Acceptă funcții avansate precum streaming, apeluri asincrone, loturi, paralelizare, reîncercări, alternative și urmărire. De exemplu, puteți compune un prompt, un model și un parser de ieșire în LCEL, așa cum se arată în următorul cod:
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)
Alternativ, LLMChain este o opțiune similară cu LCEL pentru compunerea componentelor. Exemplul LLMChain este următorul:
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")
Lanțurile din LangChain pot fi, de asemenea, cu stare prin încorporarea unui obiect Memory. Acest lucru permite persistența datelor între apeluri, așa cum se arată în acest exemplu:
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 acceptă, de asemenea, integrarea cu API-urile de apelare a funcțiilor OpenAI, care este utilă pentru obținerea de ieșiri structurate și pentru executarea funcțiilor în cadrul unui lanț. Pentru a obține rezultate structurate, le puteți specifica folosind clase Pydantic sau JsonSchema, după cum este ilustrat mai jos:
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"})
Pentru ieșirile structurate, este disponibilă și o abordare moștenită folosind 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 folosește funcțiile OpenAI pentru a crea diverse lanțuri specifice pentru diferite scopuri. Acestea includ lanțuri pentru extracție, etichetare, OpenAPI și QA cu citări.
În contextul extracției, procesul este similar cu lanțul de ieșire structurat, dar se concentrează pe extragerea informațiilor sau a entităților. Pentru etichetare, ideea este să etichetați un document cu clase precum sentiment, limbă, stil, subiecte acoperite sau tendință politică.
Un exemplu despre cum funcționează etichetarea în LangChain poate fi demonstrat cu un cod Python. Procesul începe cu instalarea pachetelor necesare și configurarea mediului:
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
Este definită schema de etichetare, specificând proprietățile și tipurile așteptate ale acestora:
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)
Exemple de rulare a lanțului de etichetare cu diferite intrări arată capacitatea modelului de a interpreta sentimentele, limbajele și agresivitatea:
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'}
Pentru un control mai fin, schema poate fi definită mai specific, incluzând posibile valori, descrieri și proprietăți necesare. Un exemplu de acest control îmbunătățit este prezentat mai jos:
schema = { "properties": { # Schema definitions here }, "required": ["language", "sentiment", "aggressiveness"],
} chain = create_tagging_chain(schema, llm)
Schemele Pydantice pot fi utilizate și pentru definirea criteriilor de etichetare, oferind o modalitate Pythonic de a specifica proprietățile și tipurile necesare:
from enum import Enum
from pydantic import BaseModel, Field class Tags(BaseModel): # Class fields here chain = create_tagging_chain_pydantic(Tags, llm)
În plus, transformatorul de documente de etichetare a metadatelor LangChain poate fi folosit pentru a extrage metadate din documentele LangChain, oferind o funcționalitate similară cu lanțul de etichetare, dar aplicată unui document LangChain.
Citarea surselor de regăsire este o altă caracteristică a LangChain, folosind funcțiile OpenAI pentru a extrage citările din text. Acest lucru este demonstrat în următorul cod:
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
În LangChain, înlănțuirea în aplicații Large Language Model (LLM) implică de obicei combinarea unui șablon prompt cu un LLM și, opțional, un parser de ieșire. Modul recomandat de a face acest lucru este prin LangChain Expression Language (LCEL), deși abordarea LLMChain moștenită este, de asemenea, acceptată.
Folosind LCEL, BasePromptTemplate, BaseLanguageModel și BaseOutputParser implementează toate interfața Runnable și pot fi conectate cu ușurință unul în celălalt. Iată un exemplu care demonstrează acest lucru:
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'
Rutarea în LangChain permite crearea de lanțuri nedeterministe în care rezultatul unui pas anterior determină pasul următor. Acest lucru ajută la structurarea și menținerea coerenței în interacțiunile cu LLM-urile. De exemplu, dacă aveți două șabloane optimizate pentru diferite tipuri de întrebări, puteți alege șablonul în funcție de intrarea utilizatorului.
Iată cum puteți realiza acest lucru folosind LCEL cu un RunnableBranch, care este inițializat cu o listă de perechi (condiții, rulabile) și un rulabil implicit:
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
Lanțul final este apoi construit folosind diferite componente, cum ar fi un clasificator de subiecte, o ramură promptă și un parser de ieșire, pentru a determina fluxul pe baza subiectului de intrare:
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
Această abordare exemplifică flexibilitatea și puterea LangChain în gestionarea interogărilor complexe și direcționarea lor adecvată pe baza intrării.
În domeniul modelelor de limbaj, o practică obișnuită este de a continua un apel inițial cu o serie de apeluri ulterioare, folosind rezultatul unui apel ca intrare pentru următorul. Această abordare secvențială este deosebit de benefică atunci când doriți să construiți pe informațiile generate în interacțiunile anterioare. În timp ce limbajul de expresie LangChain (LCEL) este metoda recomandată pentru crearea acestor secvențe, metoda SequentialChain este încă documentată pentru compatibilitatea sa inversă.
Pentru a ilustra acest lucru, să luăm în considerare un scenariu în care mai întâi generăm un sinopsis al piesei și apoi o recenzie bazată pe acel sinopsis. Folosind Python langchain.prompts
, creăm două PromptTemplate
cazuri: unul pentru rezumat și altul pentru recenzie. Iată codul pentru a configura aceste șabloane:
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:"
)
În abordarea LCEL, înlănțuim aceste solicitări cu ChatOpenAI
și StrOutputParser
pentru a crea o secvență care generează mai întâi un rezumat și apoi o recenzie. Fragmentul de cod este următorul:
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"})
Dacă avem nevoie atât de sinopsis, cât și de recenzie, putem folosi RunnablePassthrough
pentru a crea un lanț separat pentru fiecare și apoi a le combina:
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"})
Pentru scenariile care implică secvențe mai complexe, SequentialChain
metoda intră în joc. Acest lucru permite mai multe intrări și ieșiri. Luați în considerare un caz în care avem nevoie de un rezumat bazat pe titlul și epoca unei piese. Iată cum l-am putea configura:
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"})
În scenariile în care doriți să mențineți contextul de-a lungul unui lanț sau pentru o parte ulterioară a lanțului, SimpleMemory
poate fi folosit. Acest lucru este util în special pentru gestionarea relațiilor complexe de intrare/ieșire. De exemplu, într-un scenariu în care dorim să generăm postări pe rețelele sociale pe baza titlului, epocii, rezumatului și recenziei unei piese de teatru, SimpleMemory
poate ajuta la gestionarea acestor variabile:
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"})
Pe lângă lanțurile secvențiale, există și lanțuri specializate pentru lucrul cu documente. Fiecare dintre aceste lanțuri servește un scop diferit, de la combinarea documentelor până la rafinarea răspunsurilor pe baza analizei iterative a documentelor, până la cartografierea și reducerea conținutului documentului pentru rezumare sau re-clasificare pe baza răspunsurilor punctate. Aceste lanțuri pot fi recreate cu LCEL pentru flexibilitate suplimentară și personalizare.
-
StuffDocumentsChain
combină o listă de documente într-un singur prompt transmis unui LLM. -
RefineDocumentsChain
își actualizează răspunsul în mod iterativ pentru fiecare document, potrivit pentru sarcinile în care documentele depășesc capacitatea de context a modelului. -
MapReduceDocumentsChain
aplică un lanț fiecărui document în mod individual și apoi combină rezultatele. -
MapRerankDocumentsChain
punctează fiecare răspuns bazat pe document și îl selectează pe cel cu cel mai mare punctaj.
Iată un exemplu despre cum ați putea configura un MapReduceDocumentsChain
folosind 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")
Această configurație permite o analiză detaliată și cuprinzătoare a conținutului documentului, valorificând punctele forte ale LCEL și modelul lingvistic de bază.
Automatizați sarcinile și fluxurile de lucru manuale cu generatorul nostru de flux de lucru bazat pe inteligență artificială, conceput de Nanonets pentru dvs. și echipele dvs.
Modulul V: Memorie
În LangChain, memoria este un aspect fundamental al interfețelor conversaționale, permițând sistemelor să facă referire la interacțiunile din trecut. Acest lucru se realizează prin stocarea și interogarea informațiilor, cu două acțiuni principale: citirea și scrierea. Sistemul de memorie interacționează cu un lanț de două ori în timpul unei rulări, sporind intrările utilizatorului și stochând intrările și ieșirile pentru referințe viitoare.
Construirea memoriei într-un sistem
- Stocarea mesajelor de chat: Modulul de memorie LangChain integrează diverse metode de stocare a mesajelor de chat, de la liste în memorie până la baze de date. Acest lucru asigură că toate interacțiunile prin chat sunt înregistrate pentru referințe viitoare.
- Interogarea mesajelor de chat: Dincolo de stocarea mesajelor de chat, LangChain folosește structuri de date și algoritmi pentru a crea o vizualizare utilă a acestor mesaje. Sistemele simple de memorie ar putea returna mesaje recente, în timp ce sistemele mai avansate ar putea rezuma interacțiunile trecute sau se pot concentra asupra entităților menționate în interacțiunea curentă.
Pentru a demonstra utilizarea memoriei în LangChain, luați în considerare ConversationBufferMemory
class, o formă simplă de memorie care stochează mesajele de chat într-un buffer. Iată un exemplu:
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?")
Când integrați memoria într-un lanț, este esențial să înțelegeți variabilele returnate din memorie și modul în care sunt utilizate în lanț. De exemplu, cel load_memory_variables
metoda ajută la alinierea variabilelor citite din memorie cu așteptările lanțului.
Exemplu de la capăt la capăt cu LangChain
Luați în considerare utilizarea ConversationBufferMemory
într-un LLMChain
. Lanțul, combinat cu un șablon de prompt adecvat și cu memoria, oferă o experiență conversațională fără întreruperi. Iată un exemplu simplificat:
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?"})
Acest exemplu ilustrează modul în care sistemul de memorie LangChain se integrează cu lanțurile sale pentru a oferi o experiență conversațională coerentă și conștientă de context.
Tipuri de memorie în Langchain
Langchain oferă diverse tipuri de memorie care pot fi utilizate pentru a îmbunătăți interacțiunile cu modelele AI. Fiecare tip de memorie are propriii parametri și tipuri de returnare, făcându-le potrivite pentru diferite scenarii. Să explorăm câteva dintre tipurile de memorie disponibile în Langchain împreună cu exemple de cod.
1. Memoria tampon de conversație
Acest tip de memorie vă permite să stocați și să extrageți mesaje din conversații. Puteți extrage istoricul ca un șir sau ca o listă de mesaje.
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={})]}
Puteți utiliza, de asemenea, memoria tampon de conversație într-un lanț pentru interacțiuni asemănătoare chatului.
2. Memorie fereastră tampon de conversație
Acest tip de memorie păstrează o listă a interacțiunilor recente și utilizează ultimele K interacțiuni, prevenind ca memoria tampon să devină prea mare.
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'}
Ca și memoria tampon de conversație, puteți utiliza și acest tip de memorie într-un lanț pentru interacțiuni asemănătoare chat-ului.
3. Memoria entității de conversație
Acest tip de memorie reține fapte despre anumite entități dintr-o conversație și extrage informații folosind un 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. Memorie grafică a cunoștințelor conversației
Acest tip de memorie folosește un grafic de cunoștințe pentru a recrea memoria. Puteți extrage entități curente și tripleți de cunoștințe din mesaje.
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.'}
De asemenea, puteți utiliza acest tip de memorie într-un lanț pentru recuperarea cunoștințelor bazate pe conversații.
5. Memoria rezumatului conversației
Acest tip de memorie creează un rezumat al conversației în timp, util pentru condensarea informațiilor din conversații mai lungi.
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. Memoria tampon pentru rezumatul conversației
Acest tip de memorie combină rezumatul conversației și bufferul, menținând un echilibru între interacțiunile recente și un rezumat. Utilizează lungimea jetonului pentru a determina când să șterge interacțiunile.
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'}
Puteți folosi aceste tipuri de memorie pentru a vă îmbunătăți interacțiunile cu modelele AI din Langchain. Fiecare tip de memorie are un scop specific și poate fi selectat în funcție de cerințele dumneavoastră.
7. Memorie tampon pentru token de conversație
ConversationTokenBufferMemory este un alt tip de memorie care păstrează un buffer al interacțiunilor recente în memorie. Spre deosebire de tipurile de memorie anterioare care se concentrează pe numărul de interacțiuni, aceasta folosește lungimea simbolului pentru a determina când să șterge interacțiunile.
Utilizarea memoriei cu 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'}
În acest exemplu, memoria este setată să limiteze interacțiunile în funcție de lungimea simbolului, mai degrabă decât de numărul de interacțiuni.
De asemenea, puteți obține istoricul ca o listă de mesaje când utilizați acest tip de memorie.
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"})
Folosind în lanț:
Puteți utiliza ConversationTokenBufferMemory într-un lanț pentru a îmbunătăți interacțiunile cu modelul AI.
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?")
În acest exemplu, ConversationTokenBufferMemory este utilizat într-un ConversationChain pentru a gestiona conversația și a limita interacțiunile pe baza lungimii simbolului.
8. VectorStoreRetrieverMemory
VectorStoreRetrieverMemory stochează amintiri într-un magazin de vectori și interogează documentele cele mai „seminente” din top-K de fiecare dată când este apelată. Acest tip de memorie nu urmărește în mod explicit ordinea interacțiunilor, dar folosește recuperarea vectorului pentru a prelua amintirile relevante.
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"])
În acest exemplu, VectorStoreRetrieverMemory este folosit pentru a stoca și a prelua informații relevante dintr-o conversație bazată pe regăsirea vectorului.
De asemenea, puteți utiliza VectorStoreRetrieverMemory într-un lanț pentru recuperarea cunoștințelor bazate pe conversații, așa cum se arată în exemplele anterioare.
Aceste tipuri diferite de memorie din Langchain oferă diferite moduri de a gestiona și de a prelua informații din conversații, îmbunătățind capacitățile modelelor AI în înțelegerea și răspunsul la interogările și contextul utilizatorilor. Fiecare tip de memorie poate fi selectat în funcție de cerințele specifice aplicației dumneavoastră.
Acum vom învăța cum să folosim memoria cu un LLMChain. Memoria într-un LLMChain permite modelului să-și amintească interacțiunile și contextul anterioare pentru a oferi răspunsuri mai coerente și mai conștiente de context.
Pentru a configura memoria într-un LLMChain, trebuie să creați o clasă de memorie, cum ar fi ConversationBufferMemory. Iată cum îl puteți configura:
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")
În acest exemplu, ConversationBufferMemory este folosită pentru a stoca istoricul conversațiilor. The memory_key
parametrul specifică cheia folosită pentru a stoca istoricul conversației.
Dacă utilizați un model de chat în loc de un model în stil de finalizare, vă puteți structura solicitările în mod diferit pentru a utiliza mai bine memoria. Iată un exemplu despre cum să configurați un LLMChain bazat pe model de chat cu memorie:
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")
În acest exemplu, ChatPromptTemplate este folosit pentru a structura promptul, iar ConversationBufferMemory este folosit pentru a stoca și a prelua istoricul conversațiilor. Această abordare este utilă în special pentru conversațiile în stil chat în care contextul și istoria joacă un rol crucial.
Memoria poate fi adăugată și la un lanț cu intrări multiple, cum ar fi un lanț de întrebări/răspunsuri. Iată un exemplu despre cum să configurați memoria într-un lanț de întrebări/răspunsuri:
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)
În acest exemplu, se răspunde la o întrebare folosind un document împărțit în bucăți mai mici. ConversationBufferMemory este folosit pentru a stoca și a prelua istoricul conversațiilor, permițând modelului să ofere răspunsuri conștient de context.
Adăugarea memoriei unui agent îi permite acestuia să-și amintească și să folosească interacțiunile anterioare pentru a răspunde la întrebări și pentru a oferi răspunsuri conștiente de context. Iată cum puteți configura memoria într-un agent:
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)
În acest exemplu, memoriei este adăugată unui agent, permițându-i să-și amintească istoricul conversației anterioare și să ofere răspunsuri în funcție de context. Acest lucru îi permite agentului să răspundă la întrebările ulterioare cu acuratețe pe baza informațiilor stocate în memorie.
Limbajul de expresie LangChain
În lumea procesării limbajului natural și a învățării automate, alcătuirea lanțurilor complexe de operațiuni poate fi o sarcină descurajantă. Din fericire, LangChain Expression Language (LCEL) vine în ajutor, oferind o modalitate declarativă și eficientă de a construi și a implementa conducte sofisticate de procesare a limbajului. LCEL este conceput pentru a simplifica procesul de compunere a lanțurilor, făcând posibilă trecerea cu ușurință de la prototipare la producție. În acest blog, vom explora ce este LCEL și de ce ați dori să-l utilizați, împreună cu exemple practice de cod pentru a-i ilustra capacitățile.
LCEL, sau LangChain Expression Language, este un instrument puternic pentru alcătuirea lanțurilor de procesare a limbajului. A fost creat special pentru a sprijini tranziția de la prototip la producție fără probleme, fără a necesita modificări ample de cod. Indiferent dacă construiți un lanț simplu „prompt + LLM” sau o conductă complexă cu sute de pași, LCEL vă acoperă.
Iată câteva motive pentru a utiliza LCEL în proiectele dvs. de procesare a limbii:
- Streaming rapid de jetoane: LCEL furnizează jetoane dintr-un model de limbă către un parser de ieșire în timp real, îmbunătățind capacitatea de răspuns și eficiența.
- API-uri versatile: LCEL acceptă atât API-uri sincrone, cât și asincrone pentru prototipare și utilizare în producție, gestionând mai multe solicitări în mod eficient.
- Paralelizare automată: LCEL optimizează execuția paralelă atunci când este posibil, reducând latența atât în interfețele sincronizate, cât și asincrone.
- Configurații fiabile: configurați reîncercări și alternative pentru o fiabilitate îmbunătățită a lanțului la scară, cu suport pentru streaming în dezvoltare.
- Flux de rezultate intermediare: Accesați rezultatele intermediare în timpul procesării pentru actualizările utilizatorilor sau în scopuri de depanare.
- Generarea schemei: LCEL generează scheme Pydantic și JSONSchema pentru validarea de intrare și de ieșire.
- Urmărire cuprinzătoare: LangSmith urmărește automat toți pașii din lanțuri complexe pentru observabilitate și depanare.
- Implementare ușoară: Implementați lanțuri create de LCEL fără efort folosind LangServe.
Acum, să ne aprofundăm în exemple practice de cod care demonstrează puterea LCEL. Vom explora sarcini și scenarii comune în care LCEL strălucește.
Prompt + LLM
Cea mai fundamentală compoziție implică combinarea unui prompt și a unui model de limbaj pentru a crea un lanț care preia intrarea utilizatorului, o adaugă la un prompt, o transmite unui model și returnează rezultatul brut al modelului. Iată un exemplu:
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)
În acest exemplu, lanțul generează o glumă despre urși.
Puteți atașa secvențe de oprire la lanț pentru a controla modul în care procesează textul. De exemplu:
chain = prompt | model.bind(stop=["n"])
result = chain.invoke({"foo": "bears"})
print(result)
Această configurație oprește generarea de text atunci când este întâlnit un caracter de linie nouă.
LCEL acceptă atașarea informațiilor privind apelurile de funcție la lanțul dvs. Iată un exemplu:
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)
Acest exemplu atașează informații despre apelul de funcție pentru a genera o glumă.
Prompt + LLM + OutputParser
Puteți adăuga un parser de ieșire pentru a transforma ieșirea modelului brut într-un format mai funcțional. Iată cum o poți face:
from langchain.schema.output_parser import StrOutputParser chain = prompt | model | StrOutputParser()
result = chain.invoke({"foo": "bears"})
print(result)
Ieșirea este acum într-un format șir, care este mai convenabil pentru sarcinile din aval.
Când specificați o funcție de returnat, o puteți analiza direct folosind LCEL. De exemplu:
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)
Acest exemplu analizează direct rezultatul funcției „glumă”.
Acestea sunt doar câteva exemple ale modului în care LCEL simplifică sarcinile complexe de procesare a limbajului. Indiferent dacă construiți chatbot, generați conținut sau efectuați transformări complexe de text, LCEL vă poate simplifica fluxul de lucru și face codul mai ușor de întreținut.
RAG (Generație sporită cu recuperare)
LCEL poate fi folosit pentru a crea lanțuri de generare îmbunătățite cu recuperare, care combină pașii de recuperare și generarea limbajului. Iată un exemplu:
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)
În acest exemplu, lanțul preia informații relevante din context și generează un răspuns la întrebare.
Lanțul de recuperare conversațional
Puteți adăuga cu ușurință istoricul conversațiilor în lanțurile dvs. Iată un exemplu de lanț de recuperare conversațional:
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)
În acest exemplu, lanțul gestionează o întrebare ulterioară într-un context conversațional.
Cu memorie și documente sursă returnate
LCEL acceptă, de asemenea, memorie și returnarea documentelor sursă. Iată cum puteți utiliza memoria într-un lanț:
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)
În acest exemplu, memoria este utilizată pentru a stoca și a prelua istoricul conversațiilor și documentele sursă.
Lanțuri multiple
Puteți lega mai multe lanțuri folosind Runnables. Iată un exemplu:
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)
În acest exemplu, două lanțuri sunt combinate pentru a genera informații despre un oraș și țara acestuia într-o limbă specificată.
Ramificare și Fuziune
LCEL vă permite să împărțiți și să îmbinați lanțuri folosind RunnableMaps. Iată un exemplu de ramificare și îmbinare:
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)
În acest exemplu, un lanț de ramificare și fuziune este folosit pentru a genera un argument și pentru a evalua avantajele și dezavantajele acestuia înainte de a genera un răspuns final.
Scrierea codului Python cu LCEL
Una dintre aplicațiile puternice ale LangChain Expression Language (LCEL) este scrierea codului Python pentru a rezolva problemele utilizatorilor. Mai jos este un exemplu de utilizare a LCEL pentru a scrie cod 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)
În acest exemplu, un utilizator oferă intrare, iar LCEL generează cod Python pentru a rezolva problema. Codul este apoi executat folosind un REPL Python, iar codul Python rezultat este returnat în format Markdown.
Vă rugăm să rețineți că utilizarea unui REPL Python poate executa cod arbitrar, așa că utilizați-l cu precauție.
Adăugarea memoriei la un lanț
Memoria este esențială în multe aplicații AI conversaționale. Iată cum să adăugați memorie la un lanț arbitrar:
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({})
În acest exemplu, memoria este folosită pentru a stoca și a prelua istoricul conversațiilor, permițând chatbot-ului să mențină contextul și să răspundă în mod corespunzător.
Utilizarea instrumentelor externe cu executabile
LCEL vă permite să integrați fără probleme instrumente externe cu Runnables. Iată un exemplu de utilizare a instrumentului de căutare 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)
În acest exemplu, LCEL integrează instrumentul de căutare DuckDuckGo în lanț, permițându-i să genereze o interogare de căutare din intrarea utilizatorului și să preia rezultatele căutării.
Flexibilitatea LCEL facilitează încorporarea diverselor instrumente și servicii externe în conductele dvs. de procesare a limbii, îmbunătățind capacitățile și funcționalitatea acestora.
Adăugarea moderării la o aplicație LLM
Pentru a vă asigura că aplicația dvs. LLM respectă politicile de conținut și include măsuri de siguranță pentru moderare, puteți integra verificări de moderare în lanțul dvs. Iată cum puteți adăuga moderare folosind 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)
În acest exemplu, OpenAIModerationChain
este folosit pentru a adăuga moderare răspunsului generat de LLM. Lanțul de moderare verifică răspunsul pentru conținut care încalcă politica de conținut a OpenAI. Dacă sunt găsite încălcări, va semnala răspunsul în consecință.
Rutarea prin similitudine semantică
LCEL vă permite să implementați o logică de rutare personalizată bazată pe asemănarea semantică a intrărilor utilizatorului. Iată un exemplu despre cum să determinați dinamic logica lanțului pe baza intrării utilizatorului:
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"}))
În acest exemplu, prompt_router
funcția calculează asemănarea cosinusului dintre introducerea utilizatorului și șabloanele de prompte predefinite pentru întrebări de fizică și matematică. Pe baza scorului de similaritate, lanțul selectează în mod dinamic cel mai relevant șablon de prompt, asigurându-se că chatbot-ul răspunde în mod corespunzător la întrebarea utilizatorului.
Utilizarea agenților și a elementelor de rulare
LangChain vă permite să creați agenți combinând Runnables, prompturi, modele și instrumente. Iată un exemplu de construire a unui agent și de utilizare:
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)
În acest exemplu, un agent este creat prin combinarea unui model, instrumente, un prompt și o logică personalizată pentru pașii intermediari și conversia instrumentului. Agentul este apoi executat, oferind un răspuns la interogarea utilizatorului.
Interogarea unei baze de date SQL
Puteți utiliza LangChain pentru a interoga o bază de date SQL și pentru a genera interogări SQL pe baza întrebărilor utilizatorului. Iată un exemplu:
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)
În acest exemplu, LangChain este folosit pentru a genera interogări SQL pe baza întrebărilor utilizatorului și pentru a prelua răspunsuri dintr-o bază de date SQL. Solicitările și răspunsurile sunt formatate pentru a oferi interacțiuni în limbaj natural cu baza de date.
Automatizați sarcinile și fluxurile de lucru manuale cu generatorul nostru de flux de lucru bazat pe inteligență artificială, conceput de Nanonets pentru dvs. și echipele dvs.
LangServe și LangSmith
LangServe ajută dezvoltatorii să implementeze runnable și lanțuri LangChain ca API REST. Această bibliotecă este integrată cu FastAPI și folosește pydantic pentru validarea datelor. În plus, oferă un client care poate fi folosit pentru a apela elementele de rulare implementate pe un server, iar un client JavaScript este disponibil în LangChainJS.
DESCRIERE
- Schemele de intrare și ieșire sunt deduse automat din obiectul dvs. LangChain și aplicate la fiecare apel API, cu mesaje de eroare bogate.
- Este disponibilă o pagină de documente API cu JSONSchema și Swagger.
- Puncte finale eficiente /invoke, /batch și /stream cu suport pentru multe solicitări simultane pe un singur server.
- /stream_log punct final pentru transmiterea în flux a tuturor (sau a unora) pași intermediari din lanțul/agentul dvs.
- Pagina Loc de joacă la /playground cu ieșire de streaming și pași intermediari.
- Urmărire încorporată (opțională) către LangSmith; trebuie doar să adăugați cheia dvs. API (consultați Instrucțiuni).
- Toate construite cu biblioteci open-source Python testate în luptă, cum ar fi FastAPI, Pydantic, uvloop și asyncio.
Limitări
- Reapelurile clientului nu sunt încă acceptate pentru evenimentele care provin de pe server.
- Documentele OpenAPI nu vor fi generate când utilizați Pydantic V2. FastAPI nu acceptă amestecarea spațiilor de nume pydantic v1 și v2. Consultați secțiunea de mai jos pentru mai multe detalii.
Utilizați CLI LangChain pentru a porni rapid un proiect LangServe. Pentru a utiliza CLI-ul langchain, asigurați-vă că aveți instalată o versiune recentă de langchain-cli. Îl puteți instala cu pip install -U langchain-cli.
langchain app new ../path/to/directory
Porniți rapid instanța LangServe cu Șabloanele LangChain. Pentru mai multe exemple, consultați indexul de șabloane sau directorul de exemple.
Iată un server care implementează un model de chat OpenAI, un model de chat antropic și un lanț care folosește modelul antropic pentru a spune o glumă despre un subiect.
#!/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)
După ce ați implementat serverul de mai sus, puteți vizualiza documentele OpenAPI generate folosind:
curl localhost:8000/docs
Asigurați-vă că adăugați sufixul /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" }])
În TypeScript (necesită LangChain.js versiunea 0.0.166 sau o versiune ulterioară):
import { RemoteRunnable } from "langchain/runnables/remote"; const chain = new RemoteRunnable({ url: `http://localhost:8000/chain/invoke/`,
});
const result = await chain.invoke({ topic: "cats",
});
Python folosind cereri:
import requests
response = requests.post( "http://localhost:8000/chain/invoke/", json={'input': {'topic': 'cats'}}
)
response.json()
Puteți folosi și curl:
curl --location --request POST 'http://localhost:8000/chain/invoke/' --header 'Content-Type: application/json' --data-raw '{ "input": { "topic": "cats" } }'
Următorul cod:
...
add_routes( app, runnable, path="/my_runnable",
)
adaugă aceste puncte finale la server:
- POST /my_runnable/invoke – invocați rulabilul pe o singură intrare
- POST /my_runnable/batch – invocați rulabilul pe un lot de intrări
- POST /my_runnable/stream – invocați pe o singură intrare și transmiteți în flux ieșirea
- POST /my_runnable/stream_log – invocați pe o singură intrare și transmiteți în flux rezultatul, inclusiv ieșirea pașilor intermediari pe măsură ce este generat
- GET /my_runnable/input_schema – schema json pentru intrarea în rulabil
- GET /my_runnable/output_schema – schema json pentru ieșirea rulabilului
- GET /my_runnable/config_schema – schema json pentru configurația rulabilului
Puteți găsi o pagină pentru terenul de joacă pentru runnable la /my_runnable/playground. Acest lucru expune o interfață de utilizare simplă pentru a configura și a invoca fișierul rulabil cu ieșire în flux și pași intermediari.
Atât pentru client, cât și pentru server:
pip install "langserve[all]"
sau pip install „langserve[client]” pentru codul client și pip install „langserve[server]” pentru codul serverului.
Dacă trebuie să adăugați autentificare la serverul dvs., vă rugăm să consultați documentația de securitate FastAPI și documentația middleware.
Puteți implementa în GCP Cloud Run utilizând următoarea comandă:
gcloud run deploy [your-service-name] --source . --port 8001 --allow-unauthenticated --region us-central1 --set-env-vars=OPENAI_API_KEY=your_key
LangServe oferă suport pentru Pydantic 2 cu unele limitări. Documentele OpenAPI nu vor fi generate pentru invoke/batch/stream/stream_log atunci când utilizați Pydantic V2. Fast API nu acceptă amestecarea spațiilor de nume pydantic v1 și v2. LangChain folosește spațiul de nume v1 în Pydantic v2. Vă rugăm să citiți următoarele instrucțiuni pentru a asigura compatibilitatea cu LangChain. Cu excepția acestor limitări, ne așteptăm ca punctele finale API, locul de joacă și orice alte caracteristici să funcționeze conform așteptărilor.
Aplicațiile LLM se ocupă adesea de fișiere. Există diferite arhitecturi care pot fi realizate pentru a implementa procesarea fișierelor; la un nivel inalt:
- Fișierul poate fi încărcat pe server printr-un punct final dedicat și procesat folosind un punct final separat.
- Fișierul poate fi încărcat fie după valoare (octeți ai fișierului), fie prin referință (de exemplu, url s3 la conținutul fișierului).
- Punctul final de procesare poate fi blocant sau neblocant.
- Dacă este necesară o procesare semnificativă, procesarea poate fi descărcată într-un grup de procese dedicat.
Ar trebui să determinați care este arhitectura potrivită pentru aplicația dvs. În prezent, pentru a încărca fișiere după valoare într-un rulabil, utilizați codificarea base64 pentru fișier (multipart/form-data nu este încă acceptată).
Iată un exemplu care arată cum să utilizați codificarea base64 pentru a trimite un fișier către un rulabil de la distanță. Amintiți-vă, puteți oricând să încărcați fișiere prin referință (de exemplu, s3 url) sau să le încărcați ca date multiparte/form-date la un punct final dedicat.
Tipurile de intrare și ieșire sunt definite pe toate elementele rulabile. Le puteți accesa prin proprietățile input_schema și output_schema. LangServe folosește aceste tipuri pentru validare și documentare. Dacă doriți să înlocuiți tipurile implicite deduse, puteți utiliza metoda with_types.
Iată un exemplu de jucărie pentru a ilustra ideea:
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)
Moșteniți de la CustomUserType dacă doriți ca datele să se deserializeze într-un model pidantic, mai degrabă decât într-o reprezentare dict echivalentă. În acest moment, acest tip funcționează doar pe partea serverului și este folosit pentru a specifica comportamentul de decodare dorit. Dacă moștenește de la acest tip, serverul va păstra tipul decodat ca model pidantic în loc să îl convertească într-un 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")
Locul de joacă vă permite să definiți widget-uri personalizate pentru rulabilul dvs. din backend. Un widget este specificat la nivel de câmp și livrat ca parte a schemei JSON a tipului de intrare. Un widget trebuie să conțină o cheie numită type, valoarea fiind una dintr-o listă binecunoscută de widget-uri. Alte chei widget vor fi asociate cu valori care descriu căile într-un obiect JSON.
Schema generala:
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;
};
Permite crearea unei intrări de încărcare a fișierelor în spațiul de joacă UI pentru fișierele care sunt încărcate ca șiruri codificate base64. Iată exemplul complet.
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
Automatizați sarcinile și fluxurile de lucru manuale cu generatorul nostru de flux de lucru bazat pe inteligență artificială, conceput de Nanonets pentru dvs. și echipele dvs.
Introducere în LangSmith
LangChain facilitează prototiparea aplicațiilor și agenților LLM. Cu toate acestea, livrarea aplicațiilor LLM în producție poate fi înșelător de dificilă. Probabil va trebui să personalizați puternic și să repetați prompturile, lanțurile și alte componente pentru a crea un produs de înaltă calitate.
Pentru a ajuta acest proces, a fost introdus LangSmith, o platformă unificată pentru depanare, testare și monitorizare a aplicațiilor dvs. LLM.
Când ar putea fi util acest lucru? Poate fi util atunci când doriți să depanați rapid un nou lanț, agent sau set de instrumente, vizualizați modul în care componentele (lanțuri, llms, retrievers etc.) se relaționează și sunt utilizate, evaluați diferite solicitări și LLM-uri pentru o singură componentă, rulați un anumit lanț de mai multe ori peste un set de date pentru a vă asigura că îndeplinește în mod constant o bară de calitate sau capturați urmele de utilizare și utilizați LLM-uri sau conducte de analiză pentru a genera informații.
Cerințe preliminare:
- Creați un cont LangSmith și creați o cheie API (vezi colțul din stânga jos).
- Familiarizați-vă cu platforma uitându-vă prin documente.
Acum, să începem!
Mai întâi, configurați variabilele de mediu pentru a-i spune lui LangChain să înregistreze urmele. Acest lucru se face prin setarea variabilei de mediu LANGCHAIN_TRACING_V2 la true. Puteți spune lui LangChain la ce proiect să se conecteze setând variabila de mediu LANGCHAIN_PROJECT (dacă aceasta nu este setată, rulările vor fi înregistrate în proiectul implicit). Acest lucru va crea automat proiectul pentru dvs., dacă acesta nu există. De asemenea, trebuie să setați variabilele de mediu LANGCHAIN_ENDPOINT și LANGCHAIN_API_KEY.
NOTĂ: Puteți utiliza, de asemenea, un manager de context în python pentru a înregistra urme folosind:
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?")
Cu toate acestea, în acest exemplu, vom folosi variabile de mediu.
%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>"
Creați clientul LangSmith pentru a interacționa cu API-ul:
from langsmith import Client client = Client()
Creați o componentă LangChain și jurnalul rulează pe platformă. În acest exemplu, vom crea un agent în stil ReAct cu acces la un instrument de căutare general (DuckDuckGo). Solicitarea agentului poate fi vizualizată în Hub aici:
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
)
Executăm agentul simultan pe mai multe intrări pentru a reduce latența. Execuțiile sunt conectate la LangSmith în fundal, astfel încât latența de execuție nu este afectată:
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]
Presupunând că v-ați configurat cu succes mediul, urmele agenților dvs. ar trebui să apară în secțiunea Proiecte din aplicație. Felicitări!
Totuși, se pare că agentul nu folosește eficient instrumentele. Să evaluăm acest lucru, astfel încât să avem o linie de bază.
Pe lângă rulările de înregistrare, LangSmith vă permite, de asemenea, să testați și să evaluați aplicațiile LLM.
În această secțiune, veți folosi LangSmith pentru a crea un set de date de referință și a rula evaluatori asistați de AI pe un agent. Veți face acest lucru în câțiva pași:
- Creați un set de date LangSmith:
Mai jos, folosim clientul LangSmith pentru a crea un set de date din întrebările introduse de mai sus și o listă de etichete. Le veți folosi mai târziu pentru a măsura performanța unui agent nou. Un set de date este o colecție de exemple, care nu sunt altceva decât perechi intrare-ieșire pe care le puteți utiliza ca cazuri de testare pentru aplicația dvs.:
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 )
- Inițializați un agent nou pentru a evalua comparativ:
LangSmith vă permite să evaluați orice LLM, lanț, agent sau chiar o funcție personalizată. Agenții conversaționali sunt cu stare (au memorie); pentru a ne asigura că această stare nu este partajată între rulările setului de date, vom trece într-un chain_factory (
alias un constructor) funcție de inițializat pentru fiecare apel:
# 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)
- Configurați evaluarea:
Compararea manuală a rezultatelor lanțurilor în UI este eficientă, dar poate consuma mult timp. Poate fi util să utilizați valori automate și feedback asistat de inteligență artificială pentru a evalua performanța componentei dvs.:
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=[],
)
- Rulați agentul și evaluatorii:
Utilizați funcția run_on_dataset (sau asincronă arun_on_dataset) pentru a vă evalua modelul. Asta va:
- Preluați exemple de rânduri din setul de date specificat.
- Rulați agentul (sau orice funcție personalizată) pentru fiecare exemplu.
- Aplicați evaluatori la urmele de rulare rezultate și la exemplele de referință corespunzătoare pentru a genera feedback automat.
Rezultatele vor fi vizibile în aplicația 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", ],
)
Acum că avem rezultatele testelor noastre, putem face modificări agentului nostru și le putem compara. Să încercăm acest lucru din nou cu un prompt diferit și să vedem rezultatele:
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 vă permite să exportați datele în formate comune, cum ar fi CSV sau JSONL, direct în aplicația web. De asemenea, puteți utiliza clientul pentru a prelua rulări pentru analize ulterioare, pentru a stoca în propria dvs. bază de date sau pentru a partaja cu alții. Să preluăm urmele rulării din rularea de evaluare:
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
Acesta a fost un ghid rapid pentru a începe, dar există multe alte moduri de a folosi LangSmith pentru a accelera fluxul de dezvoltatori și pentru a produce rezultate mai bune.
Pentru mai multe informații despre cum puteți profita la maximum de LangSmith, consultați documentația LangSmith.
Treceți la nivel cu Nanonets
În timp ce LangChain este un instrument valoros pentru integrarea modelelor de limbă (LLM) cu aplicațiile dvs., se poate confrunta cu limitări atunci când vine vorba de cazuri de utilizare în întreprinderi. Să explorăm modul în care Nanonets depășește LangChain pentru a aborda aceste provocări:
1. Conectivitate cuprinzătoare de date:
LangChain oferă conectori, dar este posibil să nu acopere toate aplicațiile pentru spațiul de lucru și formatele de date pe care se bazează companiile. Nanonets oferă conectori de date pentru peste 100 de aplicații pentru spațiul de lucru utilizate pe scară largă, inclusiv Slack, Notion, Google Suite, Salesforce, Zendesk și multe altele. De asemenea, acceptă toate tipurile de date nestructurate, cum ar fi PDF-uri, TXT-uri, imagini, fișiere audio și fișiere video, precum și tipuri de date structurate cum ar fi CSV-uri, foi de calcul, MongoDB și baze de date SQL.
2. Automatizarea sarcinilor pentru aplicațiile pentru spațiul de lucru:
În timp ce generarea de text/răspuns funcționează excelent, capacitățile LangChain sunt limitate atunci când vine vorba de utilizarea limbajului natural pentru a efectua sarcini în diverse aplicații. Nanonets oferă agenți de declanșare/acțiune pentru cele mai populare aplicații pentru spațiul de lucru, permițându-vă să configurați fluxuri de lucru care să asculte evenimentele și să efectueze acțiuni. De exemplu, puteți automatiza răspunsurile la e-mail, intrările CRM, interogările SQL și multe altele, toate prin comenzi în limbaj natural.
3. Sincronizare a datelor în timp real:
LangChain preia date statice cu conectori de date, care ar putea să nu țină pasul cu modificările datelor din baza de date sursă. În schimb, Nanonets asigură sincronizarea în timp real cu sursele de date, asigurându-vă că lucrați întotdeauna cu cele mai recente informații.
3. Configurație simplificată:
Configurarea elementelor conductei LangChain, cum ar fi retrieverele și sintetizatoarele, poate fi un proces complex și consumator de timp. Nanonets eficientizează acest lucru, oferind asimilare și indexare optimizată a datelor pentru fiecare tip de date, toate gestionate în fundal de către Asistentul AI. Acest lucru reduce sarcina de reglare fină și facilitează configurarea și utilizarea.
4. Soluție unificată:
Spre deosebire de LangChain, care poate necesita implementări unice pentru fiecare sarcină, Nanonets servește ca o soluție unică pentru conectarea datelor cu LLM-uri. Indiferent dacă aveți nevoie să creați aplicații LLM sau fluxuri de lucru AI, Nanonets oferă o platformă unificată pentru nevoile dvs. diverse.
Fluxuri de lucru Nanonets AI
Nanonets Workflows este un asistent AI securizat, multifuncțional, care simplifică integrarea cunoștințelor și datelor dumneavoastră cu LLM-uri și facilitează crearea de aplicații și fluxuri de lucru fără cod. Oferă o interfață de utilizator ușor de utilizat, făcând-o accesibilă atât pentru persoane fizice, cât și pentru organizații.
Pentru a începe, puteți programa un apel cu unul dintre experții noștri în inteligență artificială, care vă poate oferi o demonstrație personalizată și o încercare a fluxurilor de lucru Nanonets adaptate cazului dvs. de utilizare specific.
Odată configurat, puteți folosi limbajul natural pentru a proiecta și executa aplicații și fluxuri de lucru complexe alimentate de LLM-uri, integrându-se perfect cu aplicațiile și datele dvs.
Încărcați-vă echipele cu Nanonets AI pentru a crea aplicații și pentru a vă integra datele cu aplicații și fluxuri de lucru bazate pe inteligență artificială, permițând echipelor dvs. să se concentreze pe ceea ce contează cu adevărat.
Automatizați sarcinile și fluxurile de lucru manuale cu generatorul nostru de flux de lucru bazat pe inteligență artificială, conceput de Nanonets pentru dvs. și echipele dvs.
- Distribuție de conținut bazat pe SEO și PR. Amplifică-te astăzi.
- PlatoData.Network Vertical Generative Ai. Împuterniciți-vă. Accesați Aici.
- PlatoAiStream. Web3 Intelligence. Cunoștințe amplificate. Accesați Aici.
- PlatoESG. carbon, CleanTech, Energie, Mediu inconjurator, Solar, Managementul deșeurilor. Accesați Aici.
- PlatoHealth. Biotehnologie și Inteligență pentru studii clinice. Accesați Aici.
- Sursa: https://nanonets.com/blog/langchain/
- :are
- :este
- :nu
- :Unde
- $UP
- 1
- 10
- 100
- 114
- 13
- 15%
- 2000
- 2012
- 2023
- 25
- 30
- 32
- 36
- 40
- 400
- 408
- 50
- 500
- 7
- 8
- a
- ABC
- capacitate
- Capabil
- Despre Noi
- despre
- mai sus
- Accept
- acceptă
- acces
- accesibil
- accesarea
- realiza
- în consecință
- Cont
- precizie
- precis
- precis
- Obține
- realizat
- Realizeaza
- peste
- act
- Acțiune
- acțiuni
- activ
- de adaptare
- adaptivă
- adăuga
- adăugat
- adăugare
- plus
- Suplimentar
- În plus,
- adresa
- Adaugă
- admite
- avansat
- Aventură
- După
- din nou
- vârstă
- Agent
- agenţi
- AI
- Asistent AI
- Modele AI
- Ajutorul
- Urmarind
- algoritmi
- alinia
- Se aliniază
- TOATE
- permite
- Permiterea
- permite
- singur
- de-a lungul
- pe langa
- deja
- de asemenea
- Cu toate ca
- mereu
- an
- analiză
- Analitic
- Google Analytics
- și
- Angeles
- anunța
- anual
- O alta
- răspunde
- răspunsuri
- imn
- Antropică
- Orice
- nimic
- api
- CHEILE API
- API-uri
- aplicaţia
- aplicabil
- aplicație
- Dezvoltare de Aplicații
- aplicatii
- aplicat
- se aplică
- abordare
- abordari
- adecvat
- în mod corespunzător
- Apps
- arhitectură
- SUNT
- argument
- argumente
- Armstrong
- în jurul
- Mulțime
- Artiști
- AS
- cere
- aspect
- aspecte
- ajuta
- Asistent
- asociate
- At
- atașa
- atenţie
- audio
- augmented
- Autentificare
- automatizarea
- Automata
- automate
- în mod automat
- Automatizare
- disponibil
- in medie
- astept
- conştient
- AWS
- înapoi
- Șira spinării
- Backend
- fundal
- prost
- Sold
- bar
- de bază
- bazat
- De bază
- pocni
- de bază
- Noțiuni de bază
- BCG
- BE
- Plajă
- Urșii
- deoarece
- fost
- înainte
- începe
- comportament
- în spatele
- în spatele scenelor
- fiind
- de mai jos
- Benchmark
- benefică
- CEL MAI BUN
- Mai bine
- între
- Dincolo de
- Cea mai mare
- Proiect de lege
- Bill Gates
- lega
- Bing
- Pic
- Negru
- Black Hole
- Bloca
- blocarea
- Blocuri
- Blog
- Bob
- Bootstrap
- născut
- Bot
- atât
- De jos
- Branch firma
- Pauză
- briză
- scurt
- mai larg
- maro
- browser-ul
- tampon
- construi
- constructor
- Clădire
- construit
- povară
- întreprinderi
- dar
- by
- calcula
- calculează
- calcularea
- calcul
- apel
- apeluri de apel
- denumit
- apel
- apeluri
- CAN
- Poate obține
- Canada
- capacități
- capabil
- Capacitate
- captura
- capturarea
- caz
- cazuri
- CAT
- satisface
- catering
- satisface
- Pisici
- prudenţă
- precaut
- centrat
- sigur
- lanţ
- lanţuri
- provocări
- Modificări
- caracter
- chatbot
- chatbots
- verifica
- Verificări
- Alege
- ales
- împrejurări
- Oraș
- clasă
- clase
- client
- Cloud
- cod
- Codificare
- Cafea
- COERENT
- coeziv
- colabora
- Colaps
- colectare
- colorat
- Coloană
- Coloane
- COM
- combina
- combinate
- combină
- combinând
- cum
- vine
- confortabil
- Comun
- Comunicare
- companie
- comparaţie
- compararea
- compatibilitate
- compatibil
- Completă
- complet
- completare
- complex
- complexități
- component
- componente
- compuse
- compoziție
- cuprinzător
- care cuprinde
- concept
- concis
- concurent
- condiție
- Configuraţie
- confluenţă
- Conectați
- Conectarea
- Suport conectare
- Contra
- Lua în considerare
- consecvent
- constă
- Consoleze
- mereu
- construcții
- conţine
- conține
- conţinut
- context
- contexte
- contextual
- continua
- continuu
- contrast
- Control
- controale
- Convenabil
- Conversație
- de conversaţie
- AI de conversație
- conversații
- Convertire
- convertit
- de conversie a
- Nucleu
- Colț
- corecta
- Corespunzător
- ar putea
- socoteală
- ţară
- Cuplu
- acoperi
- acoperit
- crea
- a creat
- creează
- Crearea
- creaţie
- scrisori de acreditare
- Criteriile de
- critic
- CRM
- crucial
- Curent
- În prezent
- personalizat
- clienţii care
- personalizare
- personaliza
- personalizate
- ultima generație
- de date
- Structura datelor
- Baza de date
- baze de date
- Data
- datetime
- afacere
- abuzive
- decembrie
- decide
- Decidând
- Luarea deciziilor
- Decodare
- dedicat
- Mai adânc
- Mod implicit
- defini
- definit
- definire
- Definitii
- livrarea
- Oferă
- se îngropa
- Demo
- demonstra
- demonstrat
- demonstrând
- depinde
- În funcție
- depinde de
- implementa
- dislocate
- Implementarea
- desfășurarea
- implementează
- descrie
- descriere
- Amenajări
- desemnat
- proiectat
- dorit
- detaliu
- detaliat
- detalii
- Determina
- determină
- dezvolta
- Dezvoltator
- Dezvoltatorii
- în curs de dezvoltare
- Dezvoltare
- diagrame
- DICT
- FĂCUT
- diferi
- diferit
- diferit
- dificil
- Dimensiune
- Dimensiuni
- instrucțiuni
- direct
- discuta
- discutat
- afișarea
- distinct
- scufunda
- diferit
- DM
- do
- document
- documentaţie
- documente
- face
- nu
- face
- don
- făcut
- dubla
- jos
- Descarca
- download-uri
- proiect
- conduce
- două
- în timpul
- dinamic
- dinamic
- e
- fiecare
- Mai devreme
- Devreme
- uşura
- ușurință în utilizare
- mai ușor
- cu ușurință
- uşor
- ușor de folosit
- ecou
- ecosistem
- Eficace
- în mod eficient
- eficiență
- eficient
- eficient
- efort
- oricare
- element
- element
- Elon
- Elon Musk
- altfel
- încastra
- încorporat
- Încorporarea
- angajat
- de angajați
- angajează
- împuternici
- permite
- permite
- permițând
- încapsulează
- întâlnire
- un capăt la altul
- Punct final
- captivant
- Motor
- Motoare
- Anglia
- Engleză
- Engleză Premier League
- spori
- sporită
- consolidarea
- asigura
- asigură
- asigurare
- Afacere
- entități
- entitate
- Mediu inconjurator
- medii
- Echivalent
- Eră
- eroare
- Erori
- mai ales
- esenţial
- înstrăinat
- etc
- evalua
- evaluare
- Chiar
- evenimente
- Fiecare
- exemplu
- exemple
- depăși
- Cu excepția
- a executa
- executat
- Executa
- executând
- execuție
- exemplifică
- Exercita
- exista
- aștepta
- aşteptări
- de aşteptat
- se așteaptă
- experienţă
- experimental
- experți
- a explicat
- explică
- explicit
- explorare
- explora
- explorat
- exporturile
- expresie
- extinde
- extindere
- extensiv
- extern
- suplimentar
- extrage
- extracţie
- extracte
- Față
- facilita
- facilitează
- fabrică
- fapte
- departe
- FAST
- Favorite
- Caracteristică
- DESCRIERE
- feedback-ul
- puțini
- camp
- Domenii
- figma
- Figura
- Fișier
- Fişiere
- umple
- umplut
- umplere
- filtru
- filtrare
- final
- În cele din urmă
- Găsi
- descoperire
- First
- cinci
- Flexibilitate
- flexibil
- debit
- Concentra
- concentrat
- se concentrează
- concentrându-se
- urma
- următor
- urmează
- alimente
- Pentru
- formă
- format
- format
- din fericire
- găsit
- Cadru
- cadre
- frecvent
- prieten
- Prietenii lui
- din
- Complet
- cu drepturi depline
- funcţie
- funcționalități
- funcționalitate
- funcții
- fundamental
- amuzant
- mai mult
- viitor
- Câştig
- Jocuri
- porti
- General
- în general
- genera
- generată
- generează
- generator
- generaţie
- natură
- Germania
- obține
- obtinerea
- gif
- GitHub
- dat
- GMT
- Go
- Merge
- merge
- bine
- granular
- grafic
- mare
- mai mare
- îndrumare
- ghida
- orientări
- Hackathon
- manipula
- Mânere
- Manipularea
- la indemana
- Greu
- rău
- hamurile
- Avea
- având în
- puternic
- Held
- ajutor
- util
- ajută
- ei
- aici
- hi
- Înalt
- la nivel înalt
- de înaltă calitate
- cea mai mare
- extrem de
- istoric
- istorie
- Gaură
- capotă
- gazdă
- Cum
- Cum Pentru a
- Totuși
- HTML
- http
- HTTPS
- Butuc
- uman
- sute
- i
- ID
- idee
- ideal
- ID-uri
- if
- ii
- III
- ilustra
- ilustrează
- imagini
- imediat
- punerea în aplicare a
- implementarea
- implementările
- implementat
- import
- îmbunătățiri
- îmbunătățirea
- in
- în profunzime
- include
- inclus
- include
- Inclusiv
- incorpora
- care încorporează
- incredibil
- index
- indexurile
- indica
- indică
- Individual
- persoane fizice
- informații
- inițială
- iniția
- inovatoare
- intrare
- intrări
- perspective
- instala
- instalat
- Instalarea
- instanță
- clipă
- in schimb
- instrucțiuni
- integrală
- integra
- integrate
- integreaza
- integrarea
- integrare
- integrările
- Inteligent
- destinate
- interacţiona
- interacţiune
- interacţiuni
- interactiv
- interactiv
- interfaţă
- interfeţe
- intern
- Internet
- în
- introdus
- Prezintă
- intuitiv
- implicând
- ISN
- problema
- probleme de
- IT
- articole
- iterații
- ESTE
- în sine
- Jackson
- JavaScript
- Loc de munca
- Iordania
- călătorie
- JSON
- iulie
- doar
- Justiție
- A pastra
- păstrează
- Cheie
- chei
- Copil
- Cunoaște
- cunoştinţe
- Graficul de cunoștințe
- cunoscut
- Etichetă
- etichete
- Țară
- limbă
- Limbă
- mare
- mai mare
- Nume
- Latență
- mai tarziu
- Ultimele
- Ligă
- AFLAȚI
- învăţare
- stânga
- Moştenire
- Lungime
- mai puțin
- lăsa
- Permite
- scrisoare
- Nivel
- nivelurile de
- Pârghie
- pîrghii
- efectului de pârghie
- biblioteci
- Bibliotecă
- ca
- Probabil
- LIMITĂ
- limitări
- Limitat
- limitativ
- Limitele
- Link-uri
- Listă
- asculta
- liste
- trăi
- ll
- LLM
- încărca
- încărcător
- situat
- locaţie
- log
- autentificat
- logare
- logică
- Lung
- mai lung
- Uite
- cautati
- Se pare
- căutare
- lor
- Los Angeles
- Jos
- maşină
- masina de învățare
- făcut
- menține
- De întreținut
- Mentine
- susține
- face
- FACE
- Efectuarea
- administra
- administrare
- manager
- de conducere
- Manchester
- Manchester United
- Manipulare
- manieră
- manual
- Producător
- multe
- mulți oameni
- Hartă
- cartografiere
- Harta
- Meci
- potrivire
- matematica
- matematic
- materie
- maxim
- Mai..
- me
- însemna
- sens
- mijloace
- măsura
- Mass-media
- Reuniunea
- se intalneste
- Amintiri
- Memorie
- menționat
- Îmbina
- care fuzionează
- mesaj
- mesaje
- mesagerie
- Metadata
- metodă
- Metode
- Metrici
- ar putea
- milioane
- minim
- minor
- dispărut
- greşeli
- Amestecarea
- MLB
- Mobil
- model
- Modele
- moderare
- Module
- Module
- moment
- MongoDB
- monitor
- Monitorizarea
- Lună
- mai mult
- cele mai multe
- Cel mai popular
- muta
- film
- mult
- multiplu
- lanțuri multiple
- Mosc
- trebuie sa
- my
- nume
- Numit
- nume
- național
- Natural
- Procesarea limbajului natural
- Navigaţi
- navigând
- În apropiere
- necesar
- Nevoie
- necesar
- nevoilor
- negativ
- Nou
- New York
- New York Times
- următor
- Nu.
- Nici unul
- nimic
- noțiune
- acum
- număr
- Obama
- obiect
- obiectiv
- obiecte
- observaţie
- obține
- obținerea
- OCR
- of
- oferi
- oferind
- promoții
- de multe ori
- oh
- Bine
- olympics
- on
- dată
- ONE
- afară
- open-source
- OpenAI
- Operațiuni
- operator
- optimizate
- Optimizează
- Opțiune
- or
- comandă
- organic
- organizații
- original
- OS
- Altele
- Altele
- in caz contrar
- al nostru
- afară
- producție
- iesiri
- peste
- trece peste
- Prezentare generală
- propriu
- pachet
- ofertele
- pagină
- pagini
- perechi
- panda
- Hârtie
- Paralel
- parametru
- parametrii
- Parc
- parte
- în special
- piese
- trece
- Trecut
- trece
- Care trece
- trecut
- cale
- căi
- modele
- stat de plată
- oameni
- pentru
- Perfect
- perfect
- Efectua
- performanță
- efectuarea
- efectuează
- permisiuni
- persistență
- persoană
- Personalizat
- perspectivă
- Fizică
- bucată
- conducte
- Pizza
- înlocuitor
- platformă
- Plato
- Informații despre date Platon
- PlatoData
- Joaca
- loc de joaca
- joacă
- "vă rog"
- la care se adauga
- Punct
- Politicile
- Politica
- politic
- piscină
- Popular
- populat
- pozitiv
- posibil
- Post
- postări
- potenţial
- putere
- alimentat
- puternic
- Practic
- practică
- a prefera
- premier
- prezenta
- preşedinte
- împiedica
- prevenirea
- precedent
- în primul rând
- primar
- Prim
- privat
- Problemă
- probleme
- continua
- proces
- Procesat
- procese
- prelucrare
- produce
- Produs
- producere
- Profesor
- Programare
- limbaje de programare
- proiect
- Proiecte
- proprietăţi
- proprietate
- PROS
- prototip
- prototipuri
- furniza
- prevăzut
- furnizorul
- furnizori
- furnizează
- furnizarea
- public
- scop
- scopuri
- pune
- Piton
- Q & A
- calitate
- interogări
- întrebare
- Întrebări
- Rapid
- repede
- Citate
- R
- ridica
- gamă
- variind
- mai degraba
- evaluare
- Crud
- RE
- ajunge
- Reacţiona
- Citeste
- Citind
- gata
- real
- în timp real
- date în timp real
- tărâm
- motiv
- motive
- recent
- recomandat
- inregistrata
- înregistrări
- Recupera
- reduce
- reduce
- reducerea
- reducere
- referință
- corelarea
- rafina
- rafinare
- regiuni
- Relaţii
- eliberat
- relevanţa
- încredere
- de încredere
- se bazează
- bazându-se
- rămășițe
- minte
- aducere aminte
- la distanta
- randament
- repeta
- REPETAT
- reformularea
- înlocui
- raportează
- depozit
- reprezentare
- reprezentând
- reprezintă
- solicita
- cereri de
- necesita
- necesar
- Cerinţe
- Necesită
- salvare
- cercetare
- rezolvă
- resursă
- Răspunde
- răspunde
- răspuns
- răspunsuri
- responsabil
- sensibil
- REST
- rezultat
- rezultând
- REZULTATE
- reținere
- retenţie
- reveni
- revenind
- Returnează
- reutilizabile
- revizuiască
- se învârte
- Orez
- Bogat
- roboţi
- Rol
- rolurile
- rădăcină
- rutare
- RÂND
- Alerga
- funcţionare
- ruleaza
- Runtime
- s
- garanții
- de vânzări
- Salesforce
- Sam
- acelaşi
- Economisiți
- Spune
- spune
- scalabil
- Scară
- scenariu
- scenarii
- scene
- programa
- scor
- zgâria
- fără sudură
- perfect
- Caută
- motor de cautare
- Cautari
- căutare
- Secțiune
- secțiuni
- sigur
- securitate
- vedea
- selectate
- selecţie
- De vânzare
- trimite
- sensibil
- sentiment
- sentimente
- distinct
- Septembrie
- Secvenţă
- serie
- servi
- serverul
- servește
- Servicii
- set
- Seturi
- instalare
- setări
- configurarea
- Șapte
- câteva
- Distribuie
- comun
- Coajă
- strălucește
- expediate
- să
- Arăta
- prezenta
- indicat
- Emisiuni
- Sigma
- semnificativ
- asemănător
- simplu
- simplificată
- simplifica
- simplificarea
- pur şi simplu
- întrucât
- singur
- Mărimea
- moale
- mic
- mai mici
- inteligent
- fragment
- So
- până acum
- Fotbal
- Social
- social media
- Postări în rețelele sociale
- Numai
- solid
- soluţie
- REZOLVAREA
- unele
- ceva
- uneori
- sofisticat
- sunete
- Sursă
- Surse
- Spaţiu
- Spaniolă
- de specialitate
- specific
- specific
- specific
- specificată
- viteză
- uzat
- împărţi
- șpalturi
- sportiv
- pătrat
- stand
- standalone
- standard
- Începe
- început
- Pornire
- Stat
- Declarații
- static
- Pas
- paşi
- Încă
- Stop
- oprire
- opriri
- depozitare
- stoca
- stocate
- magazine
- stocarea
- Poveste
- simplu
- curent
- de streaming
- simplifica
- raționalizate
- puncte forte
- Grevele
- Şir
- structura
- structurat
- structurile
- structurarea
- stil
- subiect
- ulterior
- Reușit
- astfel de
- Costum
- potrivit
- suită
- rezuma
- REZUMAT
- Apus
- a sustine
- Suportat
- Sprijină
- sigur
- Durabilitate
- sincronizare
- rezumat
- sintaxă
- sistem
- sisteme
- tabel
- Croitor
- adaptate
- Lua
- ia
- obiective
- Sarcină
- sarcini
- echipă
- echipe
- spune
- șablon
- şabloane
- Terminal
- terminologie
- termeni
- test
- Testarea
- a) Sport and Nutrition Awareness Day in Manasia Around XNUMX people from the rural commune Manasia have participated in a sports and healthy nutrition oriented activity in one of the community’s sports ready yards. This activity was meant to gather, mainly, middle-aged people from a Romanian rural community and teach them about the benefits that sports have on both their mental and physical health and on how sporting activities can be used to bring people from a community closer together. Three trainers were made available for this event, so that the participants would get the best possible experience physically and so that they could have the best access possible to correct information and good sports/nutrition practices. b) Sports Awareness Day in Poiana Țapului A group of young participants have taken part in sporting activities meant to teach them about sporting conduct, fairplay, and safe physical activities. The day culminated with a football match.
- decât
- mulțumesc
- acea
- Noțiuni de bază
- hubul
- informațiile
- New York Times
- Proiectele
- Sursa
- lumea
- lor
- Lor
- apoi
- Acolo.
- Acestea
- ei
- lucruri
- acest
- aceste
- deşi?
- Prin
- de-a lungul
- timp
- consumă timp
- ori
- Titlu
- la
- împreună
- semn
- tokenizarea
- indicativele
- de asemenea
- instrument
- Toolkit
- Unelte
- top
- subiect
- subiecte
- Total
- oraş
- calc
- urmări
- tradiţional
- Pregătire
- Transforma
- transformări
- transformator
- transformatoare
- tranziţie
- proces
- adevărat
- cu adevărat
- încerca
- de reglaj
- ÎNTORCĂ
- Cotitură
- tutorial
- De două ori
- Două
- tip
- Tipuri
- manuscris dactilografiat
- tipic
- ui
- în cele din urmă
- neafectat
- în
- care stau la baza
- înţelege
- înţelegere
- înțelege
- unificat
- unic
- Unit
- Universal
- spre deosebire de
- până la
- Actualizează
- actualizări
- încărcat
- URL-ul
- us
- uzabilitate
- Folosire
- utilizare
- carcasa de utilizare
- utilizat
- Utilizator
- User Interface
- utilizatorii
- utilizări
- folosind
- utilitati
- folosi
- utilizate
- utilizează
- Utilizand
- v1
- validare
- validator
- Valoros
- valoare
- Valori
- variabil
- varietate
- diverse
- Ve
- multilateral
- versiune
- foarte
- de
- Video
- Vizualizare
- încălcări
- vizibil
- imagina
- vital
- vs
- umbla
- walkthrough
- vrea
- a fost
- Ceas
- Cale..
- modalități de
- we
- Vreme
- web
- browser web
- servicii web
- site-uri web
- BINE
- bine cunoscut
- au fost
- Ce
- Ce este
- Ceea ce este
- cand
- dacă
- care
- în timp ce
- OMS
- întreg
- de ce
- larg
- pe larg
- widget
- Wikipedia
- voi
- fereastră
- Victorii
- cu
- în
- fără
- Cuvânt
- Apartamente
- a lucrat
- flux de lucru
- fluxuri de lucru
- de lucru
- fabrică
- lume
- ar
- scrie
- scris
- X
- încă
- York
- Tu
- Ta
- te
- youtube
- Zendesk
- zephyrnet
- Zip