I sin kerne Langkæde er en innovativ ramme, der er skræddersyet til at lave applikationer, der udnytter mulighederne i sprogmodeller. Det er et værktøjssæt designet til udviklere til at skabe applikationer, der er kontekstbevidste og i stand til sofistikeret ræsonnement.
Dette betyder, at LangChain-applikationer kan forstå konteksten, såsom hurtige instruktioner eller indholdsbaserede svar og bruge sprogmodeller til komplekse ræsonnementopgaver, som at beslutte, hvordan de skal reagere, eller hvilke handlinger, der skal tages. LangChain repræsenterer en samlet tilgang til udvikling af intelligente applikationer, der forenkler rejsen fra koncept til udførelse med dens forskellige komponenter.
Forstå LangChain
LangChain er meget mere end blot en ramme; det er et fuldgyldigt økosystem, der består af flere integrerede dele.
- For det første er der LangChain-bibliotekerne, tilgængelige i både Python og JavaScript. Disse biblioteker er rygraden i LangChain, der tilbyder grænseflader og integrationer til forskellige komponenter. De giver en grundlæggende køretid til at kombinere disse komponenter i sammenhængende kæder og agenter sammen med færdige implementeringer til øjeblikkelig brug.
- Dernæst har vi LangChain skabeloner. Disse er en samling af deployerbare referencearkitekturer, der er skræddersyet til en bred vifte af opgaver. Uanset om du bygger en chatbot eller et komplekst analytisk værktøj, tilbyder disse skabeloner et solidt udgangspunkt.
- LangServe træder ind som et alsidigt bibliotek til implementering af LangChain-kæder som REST API'er. Dette værktøj er vigtigt for at gøre dine LangChain-projekter til tilgængelige og skalerbare webtjenester.
- Endelig fungerer LangSmith som en udviklerplatform. Det er designet til at fejlsøge, teste, evaluere og overvåge kæder bygget på ethvert LLM-framework. Den sømløse integration med LangChain gør det til et uundværligt værktøj for udviklere, der sigter mod at forfine og perfektionere deres applikationer.
Sammen giver disse komponenter dig mulighed for at udvikle, producere og implementere applikationer med lethed. Med LangChain starter du med at skrive dine ansøgninger ved hjælp af bibliotekerne, med henvisning til skabeloner til vejledning. LangSmith hjælper dig derefter med at inspicere, teste og overvåge dine kæder og sikre, at dine applikationer konstant forbedres og klar til implementering. Endelig kan du med LangServe nemt transformere enhver kæde til en API, hvilket gør implementeringen til en leg.
I de næste afsnit vil vi dykke dybere ned i, hvordan du opsætter LangChain og begynder din rejse med at skabe intelligente, sprogmodeldrevne applikationer.
Automatiser manuelle opgaver og arbejdsgange med vores AI-drevne workflow-bygger, designet af Nanonets til dig og dine teams.
Installation og opsætning
Er du klar til at dykke ned i LangChains verden? Opsætningen er ligetil, og denne guide vil guide dig gennem processen trin-for-trin.
Det første trin i din LangChain-rejse er at installere det. Du kan nemt gøre dette ved at bruge pip eller conda. Kør følgende kommando i din terminal:
pip install langchain
For dem, der foretrækker de nyeste funktioner og er fortrolige med lidt mere eventyr, kan du installere LangChain direkte fra kilden. Klon depotet og naviger til langchain/libs/langchain
vejviser. Kør derefter:
pip install -e .
For eksperimentelle funktioner, overvej at installere langchain-experimental
. Det er en pakke, der indeholder banebrydende kode og er beregnet til forsknings- og eksperimentelle formål. Installer det ved hjælp af:
pip install langchain-experimental
LangChain CLI er et praktisk værktøj til at arbejde med LangChain skabeloner og LangServe projekter. For at installere LangChain CLI skal du bruge:
pip install langchain-cli
LangServe er afgørende for at implementere dine LangChain-kæder som en REST API. Det bliver installeret sammen med LangChain CLI.
LangChain kræver ofte integrationer med modeludbydere, datalagre, API'er osv. Til dette eksempel vil vi bruge OpenAI's model-API'er. Installer OpenAI Python-pakken ved hjælp af:
pip install openai
For at få adgang til API'en skal du indstille din OpenAI API-nøgle som en miljøvariabel:
export OPENAI_API_KEY="your_api_key"
Alternativt kan du sende nøglen direkte i dit python-miljø:
import os
os.environ['OPENAI_API_KEY'] = 'your_api_key'
LangChain giver mulighed for at skabe sprogmodelapplikationer gennem moduler. Disse moduler kan enten stå alene eller være sammensat til komplekse brugssager. Disse moduler er -
- I/O model: Faciliterer interaktion med forskellige sprogmodeller, håndterer deres input og output effektivt.
- Hentning: Muliggør adgang til og interaktion med applikationsspecifikke data, afgørende for dynamisk dataudnyttelse.
- Agenter: Giv applikationer mulighed for at vælge passende værktøjer baseret på direktiver på højt niveau, hvilket forbedrer beslutningstagningskapaciteten.
- Halskæder: Tilbyder foruddefinerede, genanvendelige sammensætninger, der fungerer som byggesten til applikationsudvikling.
- Hukommelse: Vedligeholder applikationstilstand på tværs af flere kædeudførelser, afgørende for kontekstbevidste interaktioner.
Hvert modul er rettet mod specifikke udviklingsbehov, hvilket gør LangChain til et omfattende værktøjssæt til at skabe avancerede sprogmodelapplikationer.
Sammen med ovenstående komponenter har vi også LangChain Expression Language (LCEL), som er en deklarativ måde at nemt komponere moduler sammen, og dette muliggør sammenkædning af komponenter ved hjælp af en universel Runnable-grænseflade.
LCEL ser sådan ud –
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import BaseOutputParser # Example chain
chain = ChatPromptTemplate() | ChatOpenAI() | CustomOutputParser()
Nu hvor vi har dækket det grundlæggende, vil vi fortsætte til:
- Grav dybere ned i hvert Langchain-modul i detaljer.
- Lær hvordan du bruger LangChain Expression Language.
- Udforsk almindelige use cases og implementer dem.
- Implementer en ende-til-ende-applikation med LangServe.
- Tjek LangSmith for fejlfinding, testning og overvågning.
Lad os komme igang!
Modul I: Model I/O
I LangChain drejer kerneelementet i enhver applikation sig om sprogmodellen. Dette modul giver de væsentlige byggeklodser til effektivt at interface med enhver sprogmodel, hvilket sikrer problemfri integration og kommunikation.
Nøglekomponenter i Model I/O
- LLM'er og chatmodeller (bruges i flæng):
- LLM'er:
- Definition: Rene tekstudfyldningsmodeller.
- Input / Output: Tag en tekststreng som input og returner en tekststreng som output.
- Chat modeller
- LLM'er:
- Definition: Modeller, der bruger en sprogmodel som basis, men som adskiller sig i input- og outputformater.
- Input / Output: Accepter en liste over chatbeskeder som input og returner en chatbesked.
- prompter: Skabeloner, vælg dynamisk og administrer modelinput. Giver mulighed for at skabe fleksible og kontekstspecifikke prompter, der styrer sprogmodellens svar.
- Output Parsere: Udtræk og formater oplysninger fra modeloutput. Nyttigt til at konvertere det rå output fra sprogmodeller til strukturerede data eller specifikke formater, som applikationen kræver.
LLM'er
LangChains integration med store sprogmodeller (LLM'er) som OpenAI, Cohere og Hugging Face er et grundlæggende aspekt af dets funktionalitet. LangChain selv er ikke vært for LLM'er, men tilbyder en ensartet grænseflade til at interagere med forskellige LLM'er.
Dette afsnit giver et overblik over brugen af OpenAI LLM-indpakningen i LangChain, der også kan anvendes til andre LLM-typer. Vi har allerede installeret dette i afsnittet "Kom godt i gang". Lad os initialisere LLM.
from langchain.llms import OpenAI
llm = OpenAI()
- LLM'er implementerer Kørbar grænseflade, den grundlæggende byggesten i LangChain Expression Language (LCEL). Det betyder, at de støtter
invoke
,ainvoke
,stream
,astream
,batch
,abatch
,astream_log
opkald. - LLM'er accepterer strygere som input eller objekter, der kan tvinges til strengprompter, herunder
List[BaseMessage]
,PromptValue
. (mere om disse senere)
Lad os se på nogle eksempler.
response = llm.invoke("List the seven wonders of the world.")
print(response)
Du kan alternativt kalde stream-metoden for at streame tekstsvaret.
for chunk in llm.stream("Where were the 2012 Olympics held?"): print(chunk, end="", flush=True)
Chat modeller
LangChains integration med chatmodeller, en specialiseret variation af sprogmodeller, er afgørende for at skabe interaktive chatapplikationer. Mens de bruger sprogmodeller internt, præsenterer chatmodeller en særskilt grænseflade centreret omkring chatbeskeder som input og output. Dette afsnit giver et detaljeret overblik over brugen af OpenAIs chatmodel i LangChain.
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI()
Chatmodeller i LangChain arbejder med forskellige beskedtyper som f.eks AIMessage
, HumanMessage
, SystemMessage
, FunctionMessage
og ChatMessage
(med en vilkårlig rolleparameter). Generelt, HumanMessage
, AIMessage
og SystemMessage
er de mest anvendte.
Chatmodeller accepterer primært List[BaseMessage]
som input. Strings kan konverteres til HumanMessage
og PromptValue
understøttes også.
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)
prompter
Spørgsmål er afgørende for at vejlede sprogmodeller for at generere relevante og sammenhængende output. De kan spænde fra simple instruktioner til komplekse få-shot-eksempler. I LangChain kan håndtering af prompter være en meget strømlinet proces, takket være flere dedikerede klasser og funktioner.
LangChain's PromptTemplate
class er et alsidigt værktøj til at oprette strengprompter. Den bruger Python's str.format
syntaks, hvilket giver mulighed for dynamisk promptgenerering. Du kan definere en skabelon med pladsholdere og udfylde dem med specifikke værdier efter behov.
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)
For chatmodeller er meddelelser mere strukturerede og involverer beskeder med specifikke roller. LangChain tilbyder ChatPromptTemplate
til dette formål.
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)
Denne tilgang giver mulighed for at skabe interaktive, engagerende chatbots med dynamiske svar.
Både PromptTemplate
, ChatPromptTemplate
integreres problemfrit med LangChain Expression Language (LCEL), hvilket gør dem i stand til at indgå i større, komplekse arbejdsgange. Vi vil diskutere mere om dette senere.
Tilpassede promptskabeloner er nogle gange essentielle for opgaver, der kræver unik formatering eller specifikke instruktioner. Oprettelse af en brugerdefineret promptskabelon involverer at definere inputvariabler og en brugerdefineret formateringsmetode. Denne fleksibilitet gør det muligt for LangChain at imødekomme en bred vifte af applikationsspecifikke krav. Læs mere her.
LangChain understøtter også få-shot prompt, hvilket gør det muligt for modellen at lære af eksempler. Denne funktion er afgørende for opgaver, der kræver kontekstuel forståelse eller specifikke mønstre. Få-shot-promptskabeloner kan bygges ud fra et sæt eksempler eller ved at bruge et eksempelvælgerobjekt. Læs mere her.
Output Parsere
Output-parsere spiller en afgørende rolle i Langchain, der gør det muligt for brugerne at strukturere de svar, der genereres af sprogmodeller. I dette afsnit vil vi udforske konceptet med outputparsere og give kodeeksempler ved hjælp af Langchains PydanticOutputParser, SimpleJsonOutputParser, CommaSeparatedListOutputParser, DatetimeOutputParser og XMLOutputParser.
PydanticOutputParser
Langchain leverer PydanticOutputParser til at parse svar ind i Pydantiske datastrukturer. Nedenfor er et trin-for-trin eksempel på, hvordan du bruger det:
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)
Outputtet vil være:
SimpleJsonOutputParser
Langchains SimpleJsonOutputParser bruges, når du vil parse JSON-lignende output. Her er et eksempel:
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 er praktisk, når du vil udtrække kommaseparerede lister fra modelsvar. Her er et eksempel:
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
Langchains DatetimeOutputParser er designet til at parse datetime information. Sådan bruger du det:
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)
Disse eksempler viser, hvordan Langchains outputparsere kan bruges til at strukturere forskellige typer modelsvar, hvilket gør dem velegnede til forskellige applikationer og formater. Output-parsere er et værdifuldt værktøj til at forbedre anvendeligheden og fortolkningen af sprogmodeloutput i Langchain.
Automatiser manuelle opgaver og arbejdsgange med vores AI-drevne workflow-bygger, designet af Nanonets til dig og dine teams.
Modul II: Hentning
Hentning i LangChain spiller en afgørende rolle i applikationer, der kræver brugerspecifikke data, som ikke indgår i modellens træningssæt. Denne proces, kendt som Retrieval Augmented Generation (RAG), involverer at hente eksterne data og integrere dem i sprogmodellens genereringsproces. LangChain leverer en omfattende suite af værktøjer og funktionaliteter til at lette denne proces, der henvender sig til både enkle og komplekse applikationer.
LangChain opnår hentning gennem en række komponenter, som vi vil diskutere én efter én.
Dokumentindlæsere
Dokumentindlæsere i LangChain muliggør udtræk af data fra forskellige kilder. Med over 100 tilgængelige indlæsere understøtter de en række dokumenttyper, apps og kilder (private s3 buckets, offentlige websteder, databaser).
Du kan vælge en dokumentindlæser baseret på dine krav link..
Alle disse indlæsere indtager data Dokument klasser. Vi lærer senere, hvordan du bruger data, der er optaget i dokumentklasser.
Tekstfilindlæser: Indlæs en simpel .txt
fil i et dokument.
from langchain.document_loaders import TextLoader loader = TextLoader("./sample.txt")
document = loader.load()
CSV-indlæser: Indlæs en CSV-fil i et dokument.
from langchain.document_loaders.csv_loader import CSVLoader loader = CSVLoader(file_path='./example_data/sample.csv')
documents = loader.load()
Vi kan vælge at tilpasse parsingen ved at angive feltnavne –
loader = CSVLoader(file_path='./example_data/mlb_teams_2012.csv', csv_args={ 'delimiter': ',', 'quotechar': '"', 'fieldnames': ['MLB Team', 'Payroll in millions', 'Wins']
})
documents = loader.load()
PDF-indlæsere: PDF Loaders i LangChain tilbyder forskellige metoder til at parse og udtrække indhold fra PDF-filer. Hver loader imødekommer forskellige krav og bruger forskellige underliggende biblioteker. Nedenfor er detaljerede eksempler for hver læsser.
PyPDFLoader bruges til grundlæggende PDF-parsing.
from langchain.document_loaders import PyPDFLoader loader = PyPDFLoader("example_data/layout-parser-paper.pdf")
pages = loader.load_and_split()
MathPixLoader er ideel til at udtrække matematisk indhold og diagrammer.
from langchain.document_loaders import MathpixPDFLoader loader = MathpixPDFLoader("example_data/math-content.pdf")
data = loader.load()
PyMuPDFLoader er hurtig og inkluderer detaljeret metadataudtræk.
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 bruges til mere detaljeret kontrol over tekstudtræk.
from langchain.document_loaders import PDFMinerLoader loader = PDFMinerLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
AmazonTextractPDFParser bruger AWS Textract til OCR og andre avancerede PDF-parsingfunktioner.
from langchain.document_loaders import AmazonTextractPDFLoader # Requires AWS account and configuration
loader = AmazonTextractPDFLoader("example_data/complex-layout.pdf")
documents = loader.load()
PDFMinerPDFasHTMLLoader genererer HTML fra PDF til semantisk parsing.
from langchain.document_loaders import PDFMinerPDFasHTMLLoader loader = PDFMinerPDFasHTMLLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
PDFPlumberLoader giver detaljerede metadata og understøtter ét dokument pr. side.
from langchain.document_loaders import PDFPlumberLoader loader = PDFPlumberLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
Integrerede læssere: LangChain tilbyder en bred vifte af brugerdefinerede indlæsere til direkte at indlæse data fra dine apps (såsom Slack, Sigma, Notion, Confluence, Google Drive og mange flere) og databaser og bruge dem i LLM-applikationer.
Den komplette liste er link..
Nedenfor er et par eksempler til at illustrere dette –
Eksempel I – Slack
Slack, en udbredt instant messaging platform, kan integreres i LLM workflows og applikationer.
- Gå til din Slack Workspace Management-side.
- Naviger til
{your_slack_domain}.slack.com/services/export
. - Vælg det ønskede datointerval, og start eksporten.
- Slack giver besked via e-mail og DM, når eksporten er klar.
- Eksporten resulterer i en
.zip
fil, der er placeret i mappen Downloads eller din angivne downloadsti. - Tildel stien til den downloadede
.zip
fil tilLOCAL_ZIPFILE
. - Brug
SlackDirectoryLoader
fralangchain.document_loaders
pakke.
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)
Eksempel II – Figma
Figma, et populært værktøj til interfacedesign, tilbyder en REST API til dataintegration.
- Få Figma-filnøglen fra URL-formatet:
https://www.figma.com/file/{filekey}/sampleFilename
. - Node-id'er findes i URL-parameteren
?node-id={node_id}
. - Generer et adgangstoken ved at følge instruktionerne på Figma Hjælpecenter.
-
FigmaFileLoader
klasse fralangchain.document_loaders.figma
bruges til at indlæse Figma-data. - Forskellige LangChain moduler som
CharacterTextSplitter
,ChatOpenAI
mv., er ansat til forarbejdning.
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
funktion bruger Figma-dataene til at oprette HTML/CSS-kode. - Den anvender en skabelonkonversation med en GPT-baseret model.
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
funktion, når den udføres, returnerer HTML/CSS kode baseret på Figma design input.
Lad os nu bruge vores viden til at skabe et par dokumentsæt.
Vi indlæser først en PDF, BCG's årlige bæredygtighedsrapport.
Vi bruger PyPDFLoader til dette.
from langchain.document_loaders import PyPDFLoader loader = PyPDFLoader("bcg-2022-annual-sustainability-report-apr-2023.pdf")
pdfpages = loader.load_and_split()
Vi indtager data fra Airtable nu. Vi har en Airtable, der indeholder information om forskellige OCR- og dataudtræksmodeller –
Lad os bruge AirtableLoader til dette, som findes på listen over integrerede læssere.
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()
Lad os nu fortsætte og lære at bruge disse dokumentklasser.
Dokument transformere
Dokumenttransformere i LangChain er essentielle værktøjer designet til at manipulere dokumenter, som vi oprettede i vores forrige underafsnit.
De bruges til opgaver som at opdele lange dokumenter i mindre bidder, kombinere og filtrere, hvilket er afgørende for at tilpasse dokumenter til en models kontekstvindue eller opfylde specifikke applikationsbehov.
Et sådant værktøj er RecursiveCharacterTextSplitter, en alsidig tekstsplitter, der bruger en tegnliste til opdeling. Det tillader parametre som chunk-størrelse, overlapning og startindeks. Her er et eksempel på, hvordan det bruges i 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])
Et andet værktøj er CharacterTextSplitter, som opdeler tekst baseret på et specificeret tegn og inkluderer kontroller til chunk-størrelse og overlapning:
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 er designet til at opdele HTML-indhold baseret på header-tags og bevare den semantiske struktur:
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])
En mere kompleks manipulation kan opnås ved at kombinere HTMLHeaderTextSplitter med en anden splitter, såsom 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 tilbyder også specifikke splittere til forskellige programmeringssprog, såsom Python Code Splitter og 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])
Til opdeling af tekst baseret på tokenantal, hvilket er nyttigt for sprogmodeller med token-grænser, bruges 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])
Endelig omarrangerer LongContextReorder dokumenter for at forhindre ydeevneforringelse i modeller på grund af lange sammenhænge:
from langchain.document_transformers import LongContextReorder reordering = LongContextReorder()
reordered_docs = reordering.transform_documents(docs)
print(reordered_docs[0])
Disse værktøjer demonstrerer forskellige måder at transformere dokumenter i LangChain på, fra simpel tekstopdeling til kompleks omarrangering og sprogspecifik opdeling. For mere dybdegående og specifikke brugssager bør LangChain-dokumentationen og integrationssektionen konsulteres.
I vores eksempler har læsserne allerede oprettet chunked dokumenter til os, og denne del er allerede håndteret.
Tekstindlejringsmodeller
Tekstindlejringsmodeller i LangChain giver en standardiseret grænseflade til forskellige udbydere af indlejringsmodeller som OpenAI, Cohere og Hugging Face. Disse modeller transformerer tekst til vektorrepræsentationer, hvilket muliggør operationer som semantisk søgning gennem tekstlighed i vektorrum.
For at komme i gang med tekstindlejringsmodeller skal du typisk installere specifikke pakker og opsætte API-nøgler. Vi har allerede gjort dette for OpenAI
I LangChain er embed_documents
metode bruges til at indlejre flere tekster, hvilket giver en liste over vektorrepræsentationer. For eksempel:
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]))
For indlejring af en enkelt tekst, såsom en søgeforespørgsel, embed_query
metode anvendes. Dette er nyttigt til at sammenligne en forespørgsel med et sæt dokumentindlejringer. For eksempel:
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])
Det er afgørende at forstå disse indlejringer. Hvert stykke tekst konverteres til en vektor, hvis dimension afhænger af den anvendte model. For eksempel producerer OpenAI-modeller typisk 1536-dimensionelle vektorer. Disse indlejringer bruges derefter til at hente relevant information.
LangChains indlejringsfunktionalitet er ikke begrænset til OpenAI, men er designet til at fungere med forskellige udbydere. Opsætningen og brugen kan variere lidt afhængigt af udbyderen, men kernekonceptet med at indlejre tekster i vektorrum forbliver det samme. Til detaljeret brug, herunder avancerede konfigurationer og integrationer med forskellige udbydere af indlejringsmodeller, er LangChain-dokumentationen i afsnittet Integrationer en værdifuld ressource.
Vektorbutikker
Vektorbutikker i LangChain understøtter effektiv lagring og søgning af tekstindlejringer. LangChain integreres med over 50 vektorbutikker, hvilket giver en standardiseret grænseflade til brugervenlighed.
Eksempel: Lagring og søgning af indlejringer
Efter indlejring af tekster kan vi gemme dem i en vektorbutik som Chroma
og udfør lighedssøgninger:
from langchain.vectorstores import Chroma db = Chroma.from_texts(embedded_texts)
similar_texts = db.similarity_search("search query")
Lad os alternativt bruge FAISS vektorlager til at oprette indekser til vores dokumenter.
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS pdfstore = FAISS.from_documents(pdfpages, embedding=OpenAIEmbeddings()) airtablestore = FAISS.from_documents(airtabledocs, embedding=OpenAIEmbeddings())
Retrievere
Retrievere i LangChain er grænseflader, der returnerer dokumenter som svar på en ustruktureret forespørgsel. De er mere generelle end vektorbutikker, der fokuserer på genfinding snarere end opbevaring. Selvom vektorlagre kan bruges som en retrievers rygrad, er der også andre typer retrievere.
For at konfigurere en Chroma retriever skal du først installere den vha pip install chromadb
. Derefter indlæser, opdeler, indlejrer og henter du dokumenter ved hjælp af en række Python-kommandoer. Her er et kodeeksempel til opsætning af en Chroma retriever:
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 automatiserer hurtig tuning ved at generere flere forespørgsler til en brugerinputforespørgsel og kombinerer resultaterne. Her er et eksempel på dens enkle brug:
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))
Kontekstuel komprimering i LangChain komprimerer hentede dokumenter ved hjælp af konteksten af forespørgslen, hvilket sikrer, at kun relevant information returneres. Dette involverer indholdsreduktion og frafiltrering af mindre relevante dokumenter. Følgende kodeeksempel viser, hvordan du bruger 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 kombinerer forskellige genfindingsalgoritmer for at opnå bedre ydeevne. Et eksempel på at kombinere BM25 og FAISS Retrievere er vist i følgende kode:
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 i LangChain giver mulighed for at forespørge dokumenter med flere vektorer pr. dokument, hvilket er nyttigt til at fange forskellige semantiske aspekter i et dokument. Metoder til at skabe flere vektorer omfatter opdeling i mindre bidder, opsummering eller generering af hypotetiske spørgsmål. Til opdeling af dokumenter i mindre bidder kan følgende Python-kode bruges:
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)))
Generering af resuméer for bedre genfinding på grund af mere fokuseret indholdsrepræsentation er en anden metode. Her er et eksempel på generering af oversigter:
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)))
Generering af hypotetiske spørgsmål, der er relevante for hvert dokument ved hjælp af LLM, er en anden tilgang. Dette kan gøres med følgende kode:
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 er en anden retriever, der skaber en balance mellem indlejring af nøjagtighed og kontekstbevarelse ved at gemme små bidder og hente deres større overordnede dokumenter. Dens implementering er som følger:
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")
En selvforespørgende retriever konstruerer strukturerede forespørgsler ud fra naturlige sproginput og anvender dem på dens underliggende VectorStore. Dens implementering er vist i følgende kode:
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 udfører webresearch baseret på en given forespørgsel –
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")
Til vores eksempler kan vi også bruge standardretrieveren, der allerede er implementeret som en del af vores vektorlagerobjekt som følger -
Vi kan nu forespørge retrieverne. Outputtet af vores forespørgsel vil være dokumentobjekter, der er relevante for forespørgslen. Disse vil i sidste ende blive brugt til at skabe relevante svar i yderligere afsnit.
Automatiser manuelle opgaver og arbejdsgange med vores AI-drevne workflow-bygger, designet af Nanonets til dig og dine teams.
Modul III: Agenter
LangChain introducerer et kraftfuldt koncept kaldet "Agenter", der tager ideen om kæder til et helt nyt niveau. Agenter udnytter sprogmodeller til dynamisk at bestemme sekvenser af handlinger, der skal udføres, hvilket gør dem utroligt alsidige og adaptive. I modsætning til traditionelle kæder, hvor handlinger er hårdkodet i kode, bruger agenter sprogmodeller som ræsonnement motorer til at beslutte, hvilke handlinger der skal tages og i hvilken rækkefølge.
Agenten er kernekomponenten ansvarlig for beslutningstagning. Det udnytter kraften i en sprogmodel og en opfordring til at bestemme de næste skridt for at nå et specifikt mål. Input til en agent inkluderer typisk:
- Værktøjer: Beskrivelser af tilgængelige værktøjer (mere om dette senere).
- Brugerinput: Målsætningen på højt niveau eller forespørgslen fra brugeren.
- Mellemtrin: En historik over (handling, værktøjsoutput) udførte par for at nå den aktuelle brugerinput.
Outputtet fra en agent kan være det næste Action at tage handlinger (Agenthandlinger) eller finalen svar at sende til brugeren (AgentFinish). en Action angiver en værktøj og indgang for det værktøj.
Værktøjer
Værktøjer er grænseflader, som en agent kan bruge til at interagere med verden. De gør det muligt for agenter at udføre forskellige opgaver, såsom at søge på nettet, køre shell-kommandoer eller få adgang til eksterne API'er. I LangChain er værktøjer essentielle for at udvide agenternes muligheder og gøre dem i stand til at udføre forskellige opgaver.
For at bruge værktøjer i LangChain kan du indlæse dem ved hjælp af følgende kodestykke:
from langchain.agents import load_tools tool_names = [...]
tools = load_tools(tool_names)
Nogle værktøjer kræver muligvis en basissprogmodel (LLM) for at initialisere. I sådanne tilfælde kan du også bestå en LLM:
from langchain.agents import load_tools tool_names = [...]
llm = ...
tools = load_tools(tool_names, llm=llm)
Denne opsætning giver dig adgang til en række værktøjer og integrerer dem i din agents arbejdsgange. Den komplette liste over værktøjer med brugsdokumentation er link..
Lad os se på nogle eksempler på værktøjer.
DuckDuckGo
DuckDuckGo-værktøjet giver dig mulighed for at udføre websøgninger ved hjælp af dets søgemaskine. Sådan bruger du det:
from langchain.tools import DuckDuckGoSearchRun
search = DuckDuckGoSearchRun()
search.run("manchester united vs luton town match summary")
DataForSeo
DataForSeo-værktøjssættet giver dig mulighed for at opnå søgemaskineresultater ved hjælp af DataForSeo API. For at bruge dette værktøjssæt skal du konfigurere dine API-legitimationsoplysninger. Sådan konfigurerer du legitimationsoplysningerne:
import os os.environ["DATAFORSEO_LOGIN"] = "<your_api_access_username>"
os.environ["DATAFORSEO_PASSWORD"] = "<your_api_access_password>"
Når dine legitimationsoplysninger er indstillet, kan du oprette en DataForSeoAPIWrapper
værktøj til at få adgang til API'en:
from langchain.utilities.dataforseo_api_search import DataForSeoAPIWrapper wrapper = DataForSeoAPIWrapper() result = wrapper.run("Weather in Los Angeles")
DataForSeoAPIWrapper
værktøj henter søgemaskineresultater fra forskellige kilder.
Du kan tilpasse typen af resultater og felter, der returneres i JSON-svaret. Du kan f.eks. angive resultattyper, felter og angive et maksimumantal for antallet af topresultater, der skal returneres:
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")
Dette eksempel tilpasser JSON-svaret ved at angive resultattyper, felter og begrænse antallet af resultater.
Du kan også angive placeringen og sproget for dine søgeresultater ved at overføre yderligere parametre til API-indpakningen:
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")
Ved at angive placerings- og sprogparametre kan du skræddersy dine søgeresultater til specifikke regioner og sprog.
Du har fleksibiliteten til at vælge den søgemaskine, du vil bruge. Du skal blot angive den ønskede søgemaskine:
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")
I dette eksempel er søgningen tilpasset til at bruge Bing som søgemaskine.
API-indpakningen giver dig også mulighed for at angive den type søgning, du vil udføre. For eksempel kan du udføre en kortsøgning:
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")
Dette tilpasser søgningen for at hente kortrelaterede oplysninger.
Skal (bash)
Shell-værktøjssættet giver agenter adgang til shell-miljøet, hvilket giver dem mulighed for at udføre shell-kommandoer. Denne funktion er kraftfuld, men bør bruges med forsigtighed, især i sandkassemiljøer. Sådan kan du bruge Shell-værktøjet:
from langchain.tools import ShellTool shell_tool = ShellTool() result = shell_tool.run({"commands": ["echo 'Hello World!'", "time"]})
I dette eksempel kører Shell-værktøjet to shell-kommandoer: ekko "Hello World!" og viser den aktuelle tid.
Du kan levere Shell-værktøjet til en agent til at udføre mere komplekse opgaver. Her er et eksempel på en agent, der henter links fra en webside ved hjælp af Shell-værktøjet:
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."
)
I dette scenarie bruger agenten Shell-værktøjet til at udføre en sekvens af kommandoer til at hente, filtrere og sortere URL'er fra en webside.
Eksemplerne viser nogle af de tilgængelige værktøjer i LangChain. Disse værktøjer udvider i sidste ende agenternes muligheder (udforsket i næste underafsnit) og giver dem mulighed for at udføre forskellige opgaver effektivt. Afhængigt af dine krav kan du vælge de værktøjer og værktøjssæt, der bedst passer til dit projekts behov, og integrere dem i din agents arbejdsgange.
Tilbage til Agenter
Lad os gå videre til agenter nu.
AgentExecutor er runtime-miljøet for en agent. Den er ansvarlig for at ringe til agenten, udføre de handlinger, den vælger, sende handlingsoutput tilbage til agenten og gentage processen, indtil agenten er færdig. I pseudokode kan AgentExecutor se nogenlunde sådan ud:
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 håndterer forskellige kompleksiteter, såsom håndtering af sager, hvor agenten vælger et ikke-eksisterende værktøj, håndtering af værktøjsfejl, styring af agentproducerede output og sørger for logning og observerbarhed på alle niveauer.
Mens AgentExecutor-klassen er den primære agent-runtime i LangChain, er der andre, mere eksperimentelle runtimes understøttet, herunder:
- Plan-og-udfør Agent
- Baby AGI
- Auto GPT
For at få en bedre forståelse af agentrammen, lad os bygge en grundlæggende agent fra bunden og derefter gå videre til at udforske præbyggede agenter.
Før vi dykker ned i opbygningen af agenten, er det vigtigt at gense nogle vigtige terminologier og skemaer:
- Agenthandling: Dette er en dataklasse, der repræsenterer den handling, en agent skal udføre. Den består af en
tool
egenskab (navnet på det værktøj, der skal påberåbes) og entool_input
egenskab (input til det pågældende værktøj). - AgentFinish: Denne dataklasse angiver, at agenten har afsluttet sin opgave og skal returnere et svar til brugeren. Den indeholder typisk en ordbog med returværdier, ofte med et nøgle "output", der indeholder svarteksten.
- Mellemtrin: Disse er registreringer af tidligere agenthandlinger og tilsvarende output. De er afgørende for at overføre kontekst til fremtidige iterationer af agenten.
I vores eksempel vil vi bruge OpenAI Function Calling til at oprette vores agent. Denne tilgang er pålidelig til oprettelse af agenter. Vi starter med at lave et simpelt værktøj, der beregner længden af et ord. Dette værktøj er nyttigt, fordi sprogmodeller nogle gange kan lave fejl på grund af tokenisering, når de tæller ordlængder.
Lad os først indlæse den sprogmodel, vi bruger til at styre agenten:
from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
Lad os teste modellen med en ordlængdeberegning:
llm.invoke("how many letters in the word educa?")
Svaret skal angive antallet af bogstaver i ordet "educa".
Dernæst vil vi definere en simpel Python-funktion til at beregne længden af et ord:
from langchain.agents import tool @tool
def get_word_length(word: str) -> int: """Returns the length of a word.""" return len(word)
Vi har lavet et værktøj ved navn get_word_length
der tager et ord som input og returnerer dets længde.
Lad os nu oprette prompten til agenten. Prompten instruerer agenten om, hvordan outputtet skal begrundes og formateres. I vores tilfælde bruger vi OpenAI Function Calling, som kræver minimale instruktioner. Vi definerer prompten med pladsholdere til brugerinput og agent-scratchpad:
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"), ]
)
Hvordan ved agenten nu, hvilke værktøjer den kan bruge? Vi er afhængige af OpenAI-funktionskaldende sprogmodeller, som kræver, at funktioner sendes separat. For at give vores værktøjer til agenten formaterer vi dem som OpenAI-funktionskald:
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])
Nu kan vi oprette agenten ved at definere inputtilknytninger og forbinde komponenterne:
Dette er LCEL-sprog. Vi vil diskutere dette senere i detaljer.
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()
)
Vi har oprettet vores agent, som forstår brugerinput, bruger tilgængelige værktøjer og formaterer output. Lad os nu interagere med det:
agent.invoke({"input": "how many letters in the word educa?", "intermediate_steps": []})
Agenten skal svare med en AgentAction, der angiver den næste handling, der skal udføres.
Vi har oprettet agenten, men nu skal vi skrive en runtime for den. Den enkleste runtime er en, der konstant kalder agenten, udfører handlinger og gentager, indtil agenten er færdig. Her er et eksempel:
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)
I denne løkke ringer vi gentagne gange til agenten, udfører handlinger og opdaterer de mellemliggende trin, indtil agenten er færdig. Vi håndterer også værktøjsinteraktioner inden for løkken.
For at forenkle denne proces leverer LangChain AgentExecutor-klassen, som indkapsler agentudførelse og tilbyder fejlhåndtering, tidlig stop, sporing og andre forbedringer. Lad os bruge AgentExecutor til at interagere med agenten:
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 forenkler eksekveringsprocessen og giver en bekvem måde at interagere med agenten på.
Hukommelse diskuteres også i detaljer senere.
Agenten, vi har oprettet indtil videre, er statsløs, hvilket betyder, at den ikke husker tidligere interaktioner. For at muliggøre opfølgende spørgsmål og samtaler skal vi tilføje hukommelse til agenten. Dette involverer to trin:
- Tilføj en hukommelsesvariabel i prompten for at gemme chathistorik.
- Hold styr på chathistorikken under interaktioner.
Lad os starte med at tilføje en hukommelsespladsholder i prompten:
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"), ]
)
Opret nu en liste for at spore chathistorikken:
from langchain.schema.messages import HumanMessage, AIMessage chat_history = []
I agentoprettelsestrinnet inkluderer vi også hukommelsen:
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()
)
Nu, når du kører agenten, skal du sørge for at opdatere chathistorikken:
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})
Dette gør det muligt for agenten at vedligeholde en samtalehistorik og besvare opfølgende spørgsmål baseret på tidligere interaktioner.
Tillykke! Du har med succes oprettet og udført din første end-to-end agent i LangChain. For at dykke dybere ned i LangChains muligheder kan du udforske:
- Forskellige agenttyper understøttes.
- Forudbyggede agenter
- Sådan arbejder du med værktøjer og værktøjsintegrationer.
Agenttyper
LangChain tilbyder forskellige agenttyper, der hver især er egnet til specifikke brugssager. Her er nogle af de tilgængelige agenter:
- Zero-shot ReAct: Denne agent bruger ReAct-rammen til at vælge værktøjer udelukkende baseret på deres beskrivelser. Det kræver beskrivelser for hvert værktøj og er meget alsidigt.
- Struktureret input ReAct: Denne agent håndterer multi-input værktøjer og er velegnet til komplekse opgaver som at navigere i en webbrowser. Den bruger et værktøjers argumentskema til struktureret input.
- OpenAI funktioner: Denne agent er specielt designet til modeller, der er finjusteret til funktionsopkald, og den er kompatibel med modeller som gpt-3.5-turbo-0613 og gpt-4-0613. Vi brugte dette til at oprette vores første agent ovenfor.
- Samtale: Denne agent er designet til samtaleindstillinger og bruger ReAct til værktøjsvalg og bruger hukommelse til at huske tidligere interaktioner.
- Selvspørg med søgning: Denne agent er afhængig af et enkelt værktøj, "Mellemsvar", som slår faktuelle svar på spørgsmål op. Det svarer til den originale selvspørgsmål med søgepapir.
- ReAct dokumentlager: Denne agent interagerer med et dokumentlager ved hjælp af ReAct-rammen. Det kræver "Søg" og "Opslag"-værktøjer og ligner det originale ReAct-blads Wikipedia-eksempel.
Udforsk disse agenttyper for at finde den, der passer bedst til dine behov i LangChain. Disse agenter giver dig mulighed for at binde et sæt værktøjer i dem til at håndtere handlinger og generere svar. Lær mere om hvordan du bygger din egen agent med værktøjer her.
Forudbyggede agenter
Lad os fortsætte vores udforskning af agenter med fokus på præbyggede agenter, der er tilgængelige i LangChain.
gmail
LangChain tilbyder et Gmail-værktøjssæt, der giver dig mulighed for at forbinde din LangChain-e-mail til Gmail API. For at komme i gang skal du konfigurere dine legitimationsoplysninger, som er forklaret i Gmail API-dokumentationen. Når du har downloadet credentials.json
fil, kan du fortsætte med at bruge Gmail API. Derudover skal du installere nogle nødvendige biblioteker ved hjælp af følgende kommandoer:
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
Du kan oprette Gmail-værktøjssættet som følger:
from langchain.agents.agent_toolkits import GmailToolkit toolkit = GmailToolkit()
Du kan også tilpasse godkendelse efter dine behov. Bag kulisserne oprettes en googleapi-ressource ved hjælp af følgende metoder:
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)
Værktøjssættet tilbyder forskellige værktøjer, der kan bruges i en agent, herunder:
GmailCreateDraft
: Opret en e-mailkladde med angivne meddelelsesfelter.GmailSendMessage
: Send e-mail-beskeder.GmailSearch
: Søg efter e-mail-beskeder eller tråde.GmailGetMessage
: Hent en e-mail med besked-id.GmailGetThread
: Søg efter e-mail-beskeder.
For at bruge disse værktøjer i en agent kan du initialisere agenten som følger:
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,
)
Her er et par eksempler på, hvordan disse værktøjer kan bruges:
- Opret en Gmail-kladde til redigering:
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."
)
- Søg efter den seneste e-mail i dine kladder:
agent.run("Could you search in my drafts for the latest email?")
Disse eksempler demonstrerer mulighederne i LangChains Gmail-værktøjssæt i en agent, hvilket gør det muligt for dig at interagere med Gmail programmatisk.
SQL Database Agent
Dette afsnit giver et overblik over en agent designet til at interagere med SQL-databaser, især Chinook-databasen. Denne agent kan besvare generelle spørgsmål om en database og gendanne efter fejl. Bemærk venligst, at den stadig er i aktiv udvikling, og ikke alle svar er muligvis korrekte. Vær forsigtig, når du kører det på følsomme data, da det kan udføre DML-sætninger på din database.
For at bruge denne agent kan du initialisere den som følger:
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,
)
Denne agent kan initialiseres ved hjælp af ZERO_SHOT_REACT_DESCRIPTION
agent type. Det er designet til at besvare spørgsmål og give beskrivelser. Alternativt kan du initialisere agenten ved hjælp af OPENAI_FUNCTIONS
agenttype med OpenAI's GPT-3.5-turbo-model, som vi brugte i vores tidligere klient.
Ansvarsfraskrivelse
- Forespørgselskæden kan generere indsæt/opdater/slet forespørgsler. Vær forsigtig, og brug en tilpasset prompt, eller opret en SQL-bruger uden skrivetilladelser, hvis det er nødvendigt.
- Vær opmærksom på, at kørsel af visse forespørgsler, såsom "kør den størst mulige forespørgsel", kan overbelaste din SQL-database, især hvis den indeholder millioner af rækker.
- Datavarehus-orienterede databaser understøtter ofte kvoter på brugerniveau for at begrænse ressourceforbruget.
Du kan bede agenten om at beskrive en tabel, såsom tabellen "playlisttrack". Her er et eksempel på, hvordan du gør det:
agent_executor.run("Describe the playlisttrack table")
Agenten vil give oplysninger om tabellens skema og eksempelrækker.
Hvis du ved en fejl spørger om en tabel, der ikke eksisterer, kan agenten gendanne og give oplysninger om den nærmeste matchende tabel. For eksempel:
agent_executor.run("Describe the playlistsong table")
Agenten finder den nærmeste matchende tabel og giver oplysninger om den.
Du kan også bede agenten om at køre forespørgsler på databasen. For eksempel:
agent_executor.run("List the total sales per country. Which country's customers spent the most?")
Agenten vil udføre forespørgslen og levere resultatet, såsom det land med det højeste samlede salg.
For at få det samlede antal numre i hver afspilningsliste kan du bruge følgende forespørgsel:
agent_executor.run("Show the total number of tracks in each playlist. The Playlist name should be included in the result.")
Agenten returnerer afspilningslistenavnene sammen med det tilsvarende samlede antal spor.
I tilfælde, hvor agenten støder på fejl, kan den genoprette og give nøjagtige svar. For eksempel:
agent_executor.run("Who are the top 3 best selling artists?")
Selv efter at have stødt på en indledende fejl, vil agenten justere og give det korrekte svar, som i dette tilfælde er de 3 bedst sælgende kunstnere.
Pandas DataFrame Agent
Dette afsnit introducerer en agent designet til at interagere med Pandas DataFrames med henblik på besvarelse af spørgsmål. Bemærk venligst, at denne agent bruger Python-agenten under hætten til at udføre Python-kode genereret af en sprogmodel (LLM). Vær forsigtig, når du bruger denne agent for at forhindre potentiel skade fra ondsindet Python-kode genereret af LLM.
Du kan initialisere Pandas DataFrame-agenten som følger:
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,
# )
Du kan bede agenten om at tælle antallet af rækker i DataFrame:
agent.run("how many rows are there?")
Agenten vil udføre koden df.shape[0]
og giv svaret, såsom "Der er 891 rækker i datarammen."
Du kan også bede agenten om at filtrere rækker baseret på specifikke kriterier, såsom at finde antallet af personer med mere end 3 søskende:
agent.run("how many people have more than 3 siblings")
Agenten vil udføre koden df[df['SibSp'] > 3].shape[0]
og giv svaret, såsom "30 personer har mere end 3 søskende."
Hvis du vil beregne kvadratroden af gennemsnitsalderen, kan du spørge agenten:
agent.run("whats the square root of the average age?")
Agenten vil beregne gennemsnitsalderen vha df['Age'].mean()
og udregn så kvadratroden vha math.sqrt()
. Det vil give svaret, såsom "Kvadratroden af gennemsnitsalderen er 5.449689683556195."
Lad os lave en kopi af DataFrame, og manglende aldersværdier udfyldes med middelalderen:
df1 = df.copy()
df1["Age"] = df1["Age"].fillna(df1["Age"].mean())
Derefter kan du initialisere agenten med begge DataFrames og stille den et spørgsmål:
agent = create_pandas_dataframe_agent(OpenAI(temperature=0), [df, df1], verbose=True)
agent.run("how many rows in the age column are different?")
Agenten vil sammenligne alderskolonnerne i begge DataFrames og give svaret, såsom "177 rækker i alderskolonnen er forskellige."
Jira Toolkit
Dette afsnit forklarer, hvordan man bruger Jira-værktøjssættet, som gør det muligt for agenter at interagere med en Jira-instans. Du kan udføre forskellige handlinger, såsom at søge efter problemer og oprette problemer ved hjælp af dette værktøjssæt. Det bruger atlassian-python-api-biblioteket. For at bruge dette værktøjssæt skal du indstille miljøvariabler for din Jira-instans, inklusive JIRA_API_TOKEN, JIRA_USERNAME og JIRA_INSTANCE_URL. Derudover skal du muligvis indstille din OpenAI API-nøgle som en miljøvariabel.
For at komme i gang skal du installere atlassian-python-api-biblioteket og indstille de nødvendige miljøvariabler:
%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
)
Du kan instruere agenten om at oprette et nyt problem i et specifikt projekt med en oversigt og beskrivelse:
agent.run("make a new issue in project PW to remind me to make more fried rice")
Agenten vil udføre de nødvendige handlinger for at skabe problemet og give et svar, såsom "Der er oprettet et nyt problem i projekt PW med resuméet 'Lav mere stegt ris' og beskrivelsen 'Påmindelse om at lave mere stegt ris'."
Dette giver dig mulighed for at interagere med din Jira-instans ved hjælp af instruktioner i naturligt sprog og Jira-værktøjssættet.
Automatiser manuelle opgaver og arbejdsgange med vores AI-drevne workflow-bygger, designet af Nanonets til dig og dine teams.
Modul IV: Kæder
LangChain er et værktøj designet til at bruge store sprogmodeller (LLM'er) i komplekse applikationer. Det giver rammer for at skabe kæder af komponenter, herunder LLM'er og andre typer komponenter. To primære rammer
- LangChain Expression Language (LCEL)
- Legacy Chain-grænseflade
LangChain Expression Language (LCEL) er en syntaks, der giver mulighed for intuitiv sammensætning af kæder. Den understøtter avancerede funktioner som streaming, asynkrone opkald, batching, parallelisering, genforsøg, fallbacks og sporing. For eksempel kan du komponere en prompt, model og outputparser i LCEL som vist i følgende kode:
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)
Alternativt er LLMChain en mulighed svarende til LCEL til at komponere komponenter. LLMChain-eksemplet er som følger:
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")
Kæder i LangChain kan også være stateful ved at inkorporere et Memory-objekt. Dette giver mulighed for datapersistens på tværs af opkald, som vist i dette eksempel:
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 understøtter også integration med OpenAIs funktionskaldende API'er, hvilket er nyttigt til at opnå strukturerede output og udføre funktioner i en kæde. For at få strukturerede output kan du specificere dem ved hjælp af Pydantic-klasser eller JsonSchema, som illustreret nedenfor:
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"})
For strukturerede output er en ældre tilgang ved hjælp af LLMChain også tilgængelig:
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 udnytter OpenAI-funktioner til at skabe forskellige specifikke kæder til forskellige formål. Disse inkluderer kæder til ekstraktion, tagging, OpenAPI og QA med citater.
I forbindelse med udvinding ligner processen den strukturerede outputkæde, men fokuserer på information eller enhedsudvinding. Til tagging er ideen at mærke et dokument med klasser såsom følelser, sprog, stil, dækkede emner eller politiske tendenser.
Et eksempel på hvordan tagging fungerer i LangChain kan demonstreres med en Python-kode. Processen begynder med installation af de nødvendige pakker og opsætning af miljøet:
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
Skemaet for tagging er defineret og specificerer egenskaberne og deres forventede typer:
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)
Eksempler på at køre tagging-kæden med forskellige input viser modellens evne til at fortolke følelser, sprog og aggressivitet:
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'}
For finere kontrol kan skemaet defineres mere specifikt, herunder mulige værdier, beskrivelser og påkrævede egenskaber. Et eksempel på denne forbedrede kontrol er vist nedenfor:
schema = { "properties": { # Schema definitions here }, "required": ["language", "sentiment", "aggressiveness"],
} chain = create_tagging_chain(schema, llm)
Pydantiske skemaer kan også bruges til at definere tagging-kriterier, hvilket giver en pytonisk måde at specificere nødvendige egenskaber og typer:
from enum import Enum
from pydantic import BaseModel, Field class Tags(BaseModel): # Class fields here chain = create_tagging_chain_pydantic(Tags, llm)
Derudover kan LangChains metadata-tagger-dokumenttransformator bruges til at udtrække metadata fra LangChain-dokumenter, der tilbyder lignende funktionalitet som tagging-kæden, men anvendt på et LangChain-dokument.
Citering af genfindingskilder er en anden funktion ved LangChain, der bruger OpenAI-funktioner til at udtrække citater fra tekst. Dette er demonstreret i følgende kode:
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
I LangChain involverer kæde i Large Language Model (LLM)-applikationer typisk at kombinere en promptskabelon med en LLM og eventuelt en outputparser. Den anbefalede måde at gøre dette på er gennem LangChain Expression Language (LCEL), selvom den gamle LLMChain-tilgang også understøttes.
Ved at bruge LCEL implementerer BasePromptTemplate, BaseLanguageModel og BaseOutputParser alle Runnable-grænsefladen og kan nemt overføres til hinanden. Her er et eksempel, der demonstrerer dette:
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'
Routing i LangChain giver mulighed for at skabe ikke-deterministiske kæder, hvor outputtet fra et tidligere trin bestemmer det næste trin. Dette hjælper med at strukturere og opretholde konsistens i interaktioner med LLM'er. For eksempel, hvis du har to skabeloner optimeret til forskellige typer spørgsmål, kan du vælge skabelonen baseret på brugerinput.
Sådan kan du opnå dette ved at bruge LCEL med en RunnableBranch, som initialiseres med en liste over (tilstand, kørebare) par og en standard runnable:
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
Den endelige kæde konstrueres derefter ved hjælp af forskellige komponenter, såsom en emneklassifikator, promptgren og en outputparser, for at bestemme flowet baseret på emnet for input:
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
Denne tilgang eksemplificerer LangChains fleksibilitet og kraft til at håndtere komplekse forespørgsler og dirigere dem korrekt baseret på input.
Inden for sprogmodellers område er det en almindelig praksis at følge op på et indledende opkald med en række efterfølgende opkald, ved at bruge outputtet fra et opkald som input til det næste. Denne sekventielle tilgang er især fordelagtig, når du vil bygge videre på den information, der er genereret i tidligere interaktioner. Mens LangChain Expression Language (LCEL) er den anbefalede metode til at skabe disse sekvenser, er SequentialChain-metoden stadig dokumenteret for dens bagudkompatibilitet.
For at illustrere dette, lad os overveje et scenarie, hvor vi først genererer en forestillingssynopsis og derefter en anmeldelse baseret på denne synopsis. Bruger Python's langchain.prompts
, skaber vi to PromptTemplate
instanser: en til synopsis og en anden til anmeldelsen. Her er koden til at konfigurere disse skabeloner:
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:"
)
I LCEL-tilgangen kæder vi disse prompter med ChatOpenAI
, StrOutputParser
at skabe en sekvens, der først genererer en synopsis og derefter en anmeldelse. Kodestykket er som følger:
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"})
Hvis vi har brug for både synopsis og anmeldelse, kan vi bruge RunnablePassthrough
for at oprette en separat kæde for hver og derefter kombinere dem:
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"})
For scenarier, der involverer mere komplekse sekvenser SequentialChain
metode kommer i spil. Dette giver mulighed for flere input og output. Overvej et tilfælde, hvor vi har brug for en synopsis baseret på et teaterstykkes titel og æra. Sådan kan vi konfigurere det:
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"})
I scenarier, hvor du ønsker at bevare konteksten gennem en kæde eller for en senere del af kæden, SimpleMemory
Kan bruges. Dette er især nyttigt til at håndtere komplekse input/output-relationer. For eksempel, i et scenarie, hvor vi ønsker at generere opslag på sociale medier baseret på et teaterstykkes titel, æra, synopsis og anmeldelse, SimpleMemory
kan hjælpe med at håndtere disse variabler:
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"})
Ud over sekventielle kæder er der specialiserede kæder til at arbejde med dokumenter. Hver af disse kæder tjener et andet formål, lige fra at kombinere dokumenter til at forfine svar baseret på iterativ dokumentanalyse, til at kortlægge og reducere dokumentindhold til opsummering eller omrangering baseret på scorede svar. Disse kæder kan genskabes med LCEL for yderligere fleksibilitet og tilpasning.
-
StuffDocumentsChain
kombinerer en liste over dokumenter til en enkelt prompt, der sendes til en LLM. -
RefineDocumentsChain
opdaterer sit svar iterativt for hvert dokument, velegnet til opgaver, hvor dokumenter overstiger modellens kontekstkapacitet. -
MapReduceDocumentsChain
anvender en kæde til hvert dokument individuelt og kombinerer derefter resultaterne. -
MapRerankDocumentsChain
scorer hvert dokumentbaseret svar og vælger det højest scorende svar.
Her er et eksempel på, hvordan du kan konfigurere en MapReduceDocumentsChain
bruger 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")
Denne konfiguration giver mulighed for en detaljeret og omfattende analyse af dokumentindhold, der udnytter styrkerne ved LCEL og den underliggende sprogmodel.
Automatiser manuelle opgaver og arbejdsgange med vores AI-drevne workflow-bygger, designet af Nanonets til dig og dine teams.
Modul V: Hukommelse
I LangChain er hukommelse et grundlæggende aspekt af samtalegrænseflader, hvilket gør det muligt for systemer at referere tidligere interaktioner. Dette opnås gennem lagring og forespørgsel efter information med to primære handlinger: læsning og skrivning. Hukommelsessystemet interagerer med en kæde to gange under en kørsel, øger brugerinput og gemmer input og output til fremtidig reference.
Indbygning af hukommelse i et system
- Lagring af chatbeskeder: LangChain-hukommelsesmodulet integrerer forskellige metoder til at gemme chatbeskeder, lige fra hukommelseslister til databaser. Dette sikrer, at alle chat-interaktioner registreres til fremtidig reference.
- Forespørgsel på chatbeskeder: Udover at gemme chatbeskeder, anvender LangChain datastrukturer og algoritmer til at skabe en nyttig visning af disse beskeder. Simple hukommelsessystemer kan returnere seneste beskeder, mens mere avancerede systemer kunne opsummere tidligere interaktioner eller fokusere på enheder nævnt i den aktuelle interaktion.
For at demonstrere brugen af hukommelse i LangChain, overveje ConversationBufferMemory
klasse, en simpel hukommelsesform, der gemmer chatbeskeder i en buffer. Her er et eksempel:
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?")
Når du integrerer hukommelse i en kæde, er det afgørende at forstå de variabler, der returneres fra hukommelsen, og hvordan de bruges i kæden. For eksempel load_memory_variables
metoden hjælper med at tilpasse de variabler, der læses fra hukommelsen, med kædens forventninger.
End-to-End-eksempel med LangChain
Overvej at bruge ConversationBufferMemory
i en LLMChain
. Kæden, kombineret med en passende promptskabelon og hukommelsen, giver en problemfri samtaleoplevelse. Her er et forenklet eksempel:
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?"})
Dette eksempel illustrerer, hvordan LangChains hukommelsessystem integreres med dets kæder for at give en sammenhængende og kontekstuelt bevidst samtaleoplevelse.
Hukommelsestyper i Langchain
Langchain tilbyder forskellige hukommelsestyper, der kan bruges til at forbedre interaktioner med AI-modellerne. Hver hukommelsestype har sine egne parametre og returtyper, hvilket gør dem velegnede til forskellige scenarier. Lad os udforske nogle af de tilgængelige hukommelsestyper i Langchain sammen med kodeeksempler.
1. Samtalebufferhukommelse
Denne hukommelsestype giver dig mulighed for at gemme og udtrække beskeder fra samtaler. Du kan udtrække historikken som en streng eller som en liste over beskeder.
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={})]}
Du kan også bruge samtalebufferhukommelse i en kæde til chatlignende interaktioner.
2. Hukommelse i samtalebuffervindue
Denne hukommelsestype gemmer en liste over seneste interaktioner og bruger de sidste K-interaktioner, hvilket forhindrer bufferen i at blive for stor.
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'}
Ligesom samtalebufferhukommelse kan du også bruge denne hukommelsestype i en kæde til chatlignende interaktioner.
3. Hukommelse for samtaleenhed
Denne hukommelsestype husker fakta om specifikke enheder i en samtale og udtrækker information ved hjælp af en 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. Hukommelse til samtalevidensgraf
Denne hukommelsestype bruger en vidensgraf til at genskabe hukommelse. Du kan udtrække aktuelle entiteter og videnstrillinger fra beskeder.
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.'}
Du kan også bruge denne hukommelsestype i en kæde til samtalebaseret videnshentning.
5. Samtaleoversigtshukommelse
Denne hukommelsestype opretter en oversigt over samtalen over tid, nyttig til at kondensere information fra længere samtaler.
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. Samtaleoversigt Bufferhukommelse
Denne hukommelsestype kombinerer samtaleoversigten og bufferen, og opretholder en balance mellem nylige interaktioner og et resumé. Den bruger tokenlængde til at bestemme, hvornår interaktioner skal skylles.
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'}
Du kan bruge disse hukommelsestyper til at forbedre dine interaktioner med AI-modeller i Langchain. Hver hukommelsestype tjener et specifikt formål og kan vælges baseret på dine krav.
7. Samtaletoken-bufferhukommelse
ConversationTokenBufferMemory er en anden hukommelsestype, der holder en buffer af nylige interaktioner i hukommelsen. I modsætning til de tidligere hukommelsestyper, der fokuserer på antallet af interaktioner, bruger denne tokenlængde til at bestemme, hvornår interaktioner skal tømmes.
Brug af hukommelse med 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'}
I dette eksempel er hukommelsen indstillet til at begrænse interaktioner baseret på tokenlængde snarere end antallet af interaktioner.
Du kan også få historikken som en liste over beskeder, når du bruger denne hukommelsestype.
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"})
Brug i en kæde:
Du kan bruge ConversationTokenBufferMemory i en kæde til at forbedre interaktioner med AI-modellen.
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?")
I dette eksempel bruges ConversationTokenBufferMemory i en ConversationChain til at styre samtalen og begrænse interaktioner baseret på tokenlængde.
8. VectorStoreRetrieverMemory
VectorStoreRetrieverMemory gemmer minder i et vektorlager og forespørger i de øverste K mest "fremtrædende" dokumenter, hver gang det kaldes. Denne hukommelsestype sporer ikke eksplicit rækkefølgen af interaktioner, men bruger vektorhentning til at hente relevante minder.
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"])
I dette eksempel bruges VectorStoreRetrieverMemory til at gemme og hente relevant information fra en samtale baseret på vektorhentning.
Du kan også bruge VectorStoreRetrieverMemory i en kæde til samtalebaseret videnshentning, som vist i de foregående eksempler.
Disse forskellige hukommelsestyper i Langchain giver forskellige måder at administrere og hente information fra samtaler på, hvilket forbedrer AI-modellernes muligheder for at forstå og svare på brugerforespørgsler og kontekst. Hver hukommelsestype kan vælges baseret på de specifikke krav til din applikation.
Nu lærer vi, hvordan man bruger hukommelse med en LLMChain. Hukommelse i en LLMChain giver modellen mulighed for at huske tidligere interaktioner og kontekst for at give mere sammenhængende og kontekstbevidste svar.
For at opsætte hukommelse i en LLMChain skal du oprette en hukommelsesklasse, såsom ConversationBufferMemory. Sådan kan du konfigurere det:
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")
I dette eksempel bruges ConversationBufferMemory til at gemme samtalehistorikken. Det memory_key
parameter angiver den nøgle, der bruges til at gemme samtalehistorikken.
Hvis du bruger en chatmodel i stedet for en færdiggørelsesmodel, kan du strukturere dine prompter anderledes for bedre at udnytte hukommelsen. Her er et eksempel på, hvordan man opsætter en chatmodelbaseret LLMChain med hukommelse:
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")
I dette eksempel bruges ChatPromptTemplate til at strukturere prompten, og ConversationBufferMemory bruges til at gemme og hente samtalehistorikken. Denne tilgang er især nyttig til samtaler i chat-stil, hvor kontekst og historie spiller en afgørende rolle.
Hukommelse kan også tilføjes til en kæde med flere input, såsom en spørgsmål/svar-kæde. Her er et eksempel på, hvordan du opsætter hukommelse i en spørgsmål/svar-kæde:
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)
I dette eksempel besvares et spørgsmål ved hjælp af et dokument opdelt i mindre bidder. ConversationBufferMemory bruges til at gemme og hente samtalehistorikken, hvilket gør det muligt for modellen at give kontekstbevidste svar.
Tilføjelse af hukommelse til en agent giver den mulighed for at huske og bruge tidligere interaktioner til at besvare spørgsmål og give kontekstbevidste svar. Sådan kan du konfigurere hukommelse i en 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)
I dette eksempel føjes hukommelse til en agent, så den kan huske den tidligere samtalehistorik og give kontekstbevidste svar. Dette gør det muligt for agenten at besvare opfølgende spørgsmål nøjagtigt baseret på de oplysninger, der er gemt i hukommelsen.
LangChain Expression Language
I en verden af naturlig sprogbehandling og maskinlæring kan det være en skræmmende opgave at sammensætte komplekse kæder af operationer. Heldigvis kommer LangChain Expression Language (LCEL) til undsætning og giver en deklarativ og effektiv måde at bygge og implementere sofistikerede sprogbehandlingspipelines. LCEL er designet til at forenkle processen med at sammensætte kæder, hvilket gør det muligt at gå fra prototyping til produktion med lethed. I denne blog vil vi undersøge, hvad LCEL er, og hvorfor du måske ønsker at bruge det, sammen med praktiske kodeeksempler for at illustrere dets muligheder.
LCEL, eller LangChain Expression Language, er et kraftfuldt værktøj til at sammensætte sprogbehandlingskæder. Det var specialbygget til at understøtte overgangen fra prototyping til produktion problemfrit uden at kræve omfattende kodeændringer. Uanset om du bygger en simpel "prompt + LLM"-kæde eller en kompleks pipeline med hundredvis af trin, har LCEL dig dækket.
Her er nogle grunde til at bruge LCEL i dine sprogbehandlingsprojekter:
- Hurtig tokenstreaming: LCEL leverer tokens fra en sprogmodel til en outputparser i realtid, hvilket forbedrer reaktionsevnen og effektiviteten.
- Alsidige API'er: LCEL understøtter både synkrone og asynkrone API'er til prototyping og produktionsbrug, og håndterer flere anmodninger effektivt.
- Automatisk parallellisering: LCEL optimerer parallel eksekvering, når det er muligt, og reducerer latens i både synkroniserings- og asynkrongrænseflader.
- Pålidelige konfigurationer: Konfigurer genforsøg og fallbacks for forbedret kædepålidelighed i stor skala med streamingunderstøttelse under udvikling.
- Stream mellemresultater: Få adgang til mellemliggende resultater under behandling til brugeropdateringer eller fejlretningsformål.
- Skemagenerering: LCEL genererer Pydantic- og JSONSchema-skemaer til input- og outputvalidering.
- Omfattende sporing: LangSmith sporer automatisk alle trin i komplekse kæder til observerbarhed og fejlretning.
- Nem implementering: Implementer LCEL-skabte kæder ubesværet ved hjælp af LangServe.
Lad os nu dykke ned i praktiske kodeeksempler, der demonstrerer LCELs kraft. Vi vil udforske almindelige opgaver og scenarier, hvor LCEL skinner.
Spørg + LLM
Den mest fundamentale sammensætning involverer at kombinere en prompt og en sprogmodel for at skabe en kæde, der tager brugerinput, føjer det til en prompt, sender det til en model og returnerer det rå modeloutput. Her er et eksempel:
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)
I dette eksempel genererer kæden en joke om bjørne.
Du kan vedhæfte stopsekvenser til din kæde for at kontrollere, hvordan den behandler tekst. For eksempel:
chain = prompt | model.bind(stop=["n"])
result = chain.invoke({"foo": "bears"})
print(result)
Denne konfiguration stopper tekstgenerering, når der stødes på et linjeskifttegn.
LCEL understøtter vedhæftning af funktionsopkaldsoplysninger til din kæde. Her er et eksempel:
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)
Dette eksempel vedhæfter funktionsopkaldsoplysninger for at generere en joke.
Prompt + LLM + OutputParser
Du kan tilføje en outputparser for at omdanne råmodeloutputtet til et mere brugbart format. Sådan kan du gøre det:
from langchain.schema.output_parser import StrOutputParser chain = prompt | model | StrOutputParser()
result = chain.invoke({"foo": "bears"})
print(result)
Outputtet er nu i et strengformat, hvilket er mere bekvemt til downstream-opgaver.
Når du angiver en funktion, der skal returneres, kan du parse den direkte ved hjælp af LCEL. For eksempel:
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)
Dette eksempel analyserer outputtet fra "joke"-funktionen direkte.
Dette er blot nogle få eksempler på, hvordan LCEL forenkler komplekse sprogbehandlingsopgaver. Uanset om du bygger chatbots, genererer indhold eller udfører komplekse teksttransformationer, kan LCEL strømline din arbejdsgang og gøre din kode mere vedligeholdelsesvenlig.
RAG (Retrieval-augmented Generation)
LCEL kan bruges til at skabe genfindingsforstærkede generationskæder, som kombinerer genfindings- og sproggenereringstrin. Her er et eksempel:
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)
I dette eksempel henter kæden relevant information fra konteksten og genererer et svar på spørgsmålet.
Samtalesøgningskæde
Du kan nemt tilføje samtalehistorik til dine kæder. Her er et eksempel på en samtale-hentningskæde:
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)
I dette eksempel håndterer kæden et opfølgende spørgsmål i en samtalekontekst.
Med hukommelse og returnerende kildedokumenter
LCEL understøtter også hukommelse og returnerende kildedokumenter. Sådan kan du bruge hukommelsen i en kæde:
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)
I dette eksempel bruges hukommelse til at gemme og hente samtalehistorik og kildedokumenter.
Flere kæder
Du kan sammenkæde flere kæder ved hjælp af Runnables. Her er et eksempel:
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)
I dette eksempel kombineres to kæder for at generere information om en by og dens land på et bestemt sprog.
Forgrening og fusion
LCEL giver dig mulighed for at opdele og flette kæder ved hjælp af RunnableMaps. Her er et eksempel på forgrening og fletning:
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)
I dette eksempel bruges en forgrenings- og sammensmeltningskæde til at generere et argument og evaluere dets fordele og ulemper, før der genereres et endeligt svar.
Skriver Python-kode med LCEL
En af de kraftfulde applikationer af LangChain Expression Language (LCEL) er at skrive Python-kode for at løse brugerproblemer. Nedenfor er et eksempel på, hvordan man bruger LCEL til at skrive Python-kode:
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)
I dette eksempel giver en bruger input, og LCEL genererer Python-kode for at løse problemet. Koden udføres derefter ved hjælp af en Python REPL, og den resulterende Python-kode returneres i Markdown-format.
Bemærk venligst, at brug af en Python REPL kan udføre vilkårlig kode, så brug den med forsigtighed.
Tilføjelse af hukommelse til en kæde
Hukommelse er essentiel i mange samtale-AI-applikationer. Sådan tilføjer du hukommelse til en vilkårlig kæde:
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({})
I dette eksempel bruges hukommelsen til at gemme og hente samtalehistorik, hvilket gør det muligt for chatbotten at bevare kontekst og reagere korrekt.
Brug af eksterne værktøjer med runnables
LCEL giver dig mulighed for problemfrit at integrere eksterne værktøjer med Runnables. Her er et eksempel ved hjælp af DuckDuckGo-søgeværktøjet:
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)
I dette eksempel integrerer LCEL DuckDuckGo Search-værktøjet i kæden, så det kan generere en søgeforespørgsel fra brugerinput og hente søgeresultater.
LCELs fleksibilitet gør det nemt at inkorporere forskellige eksterne værktøjer og tjenester i dine sprogbehandlingspipelines, hvilket forbedrer deres muligheder og funktionalitet.
Tilføjelse af moderation til en LLM-applikation
For at sikre, at din LLM-applikation overholder indholdspolitikker og inkluderer modereringssikkerhedsforanstaltninger, kan du integrere modereringstjek i din kæde. Sådan tilføjer du moderation ved hjælp af 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)
I dette eksempel er OpenAIModerationChain
bruges til at tilføje moderering til svaret genereret af LLM. Modereringskæden tjekker svaret for indhold, der overtræder OpenAIs indholdspolitik. Hvis der findes overtrædelser, vil den markere svaret i overensstemmelse hermed.
Routing ved semantisk lighed
LCEL giver dig mulighed for at implementere tilpasset routinglogik baseret på den semantiske lighed mellem brugerinput. Her er et eksempel på, hvordan man dynamisk bestemmer kædelogikken baseret på brugerinput:
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"}))
I dette eksempel er prompt_router
funktionen beregner cosinus-ligheden mellem brugerinput og foruddefinerede promptskabeloner til fysik- og matematikspørgsmål. Baseret på lighedsscoren udvælger kæden dynamisk den mest relevante promptskabelon, hvilket sikrer, at chatbotten svarer korrekt på brugerens spørgsmål.
Brug af agenter og runnables
LangChain giver dig mulighed for at oprette agenter ved at kombinere Runnables, prompter, modeller og værktøjer. Her er et eksempel på at bygge en agent og bruge den:
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)
I dette eksempel oprettes en agent ved at kombinere en model, værktøjer, en prompt og en tilpasset logik til mellemtrin og værktøjskonvertering. Agenten udføres derefter og giver et svar på brugerens forespørgsel.
Forespørgsel i en SQL-database
Du kan bruge LangChain til at forespørge en SQL-database og generere SQL-forespørgsler baseret på brugerspørgsmål. Her er et eksempel:
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)
I dette eksempel bruges LangChain til at generere SQL-forespørgsler baseret på brugerspørgsmål og hente svar fra en SQL-database. Spørgsmålene og svarene er formateret til at give naturlige sproginteraktioner med databasen.
Automatiser manuelle opgaver og arbejdsgange med vores AI-drevne workflow-bygger, designet af Nanonets til dig og dine teams.
LangServe & LangSmith
LangServe hjælper udviklere med at implementere LangChain runnables og kæder som en REST API. Dette bibliotek er integreret med FastAPI og bruger pydantic til datavalidering. Derudover giver det en klient, der kan bruges til at kalde ind i runnables, der er installeret på en server, og en JavaScript-klient er tilgængelig i LangChainJS.
Funktioner
- Input- og outputskemaer udledes automatisk fra dit LangChain-objekt og håndhæves på hvert API-kald med omfattende fejlmeddelelser.
- En API-dokumentside med JSONSchema og Swagger er tilgængelig.
- Effektive /invoke, /batch og /stream slutpunkter med understøttelse af mange samtidige anmodninger på en enkelt server.
- /stream_log slutpunkt til streaming af alle (eller nogle) mellemliggende trin fra din kæde/agent.
- Legepladsside på /legeplads med streaming output og mellemtrin.
- Indbygget (valgfrit) sporing til LangSmith; blot tilføje din API-nøgle (se instruktioner).
- Alt sammen bygget med kamptestede open source Python-biblioteker som FastAPI, Pydantic, uvloop og asyncio.
Begrænsninger
- Klienttilbagekald er endnu ikke understøttet for hændelser, der stammer fra serveren.
- OpenAPI-dokumenter vil ikke blive genereret, når du bruger Pydantic V2. FastAPI understøtter ikke blanding af pydantic v1 og v2 navnerum. Se afsnittet nedenfor for flere detaljer.
Brug LangChain CLI til hurtigt at starte et LangServe-projekt. For at bruge langchain CLI skal du sørge for, at du har en nyere version af langchain-cli installeret. Du kan installere det med pip install -U langchain-cli.
langchain app new ../path/to/directory
Kom hurtigt i gang med din LangServe-instans med LangChain-skabeloner. For flere eksempler, se skabelonindekset eller eksempelbiblioteket.
Her er en server, der implementerer en OpenAI-chatmodel, en antropisk chatmodel og en kæde, der bruger den antropiske model til at fortælle en vittighed om et emne.
#!/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)
Når du har installeret serveren ovenfor, kan du se de genererede OpenAPI-dokumenter ved hjælp af:
curl localhost:8000/docs
Sørg for at tilføje suffikset /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" }])
I TypeScript (kræver LangChain.js version 0.0.166 eller nyere):
import { RemoteRunnable } from "langchain/runnables/remote"; const chain = new RemoteRunnable({ url: `http://localhost:8000/chain/invoke/`,
});
const result = await chain.invoke({ topic: "cats",
});
Python ved hjælp af anmodninger:
import requests
response = requests.post( "http://localhost:8000/chain/invoke/", json={'input': {'topic': 'cats'}}
)
response.json()
Du kan også bruge krølle:
curl --location --request POST 'http://localhost:8000/chain/invoke/' --header 'Content-Type: application/json' --data-raw '{ "input": { "topic": "cats" } }'
Følgende kode:
...
add_routes( app, runnable, path="/my_runnable",
)
tilføjer af disse endepunkter til serveren:
- POST /my_runnable/invoke – start den runnable på et enkelt input
- POST /my_runnable/batch – start den runnable på en batch af input
- POST /my_runnable/stream – start på et enkelt input og stream output
- POST /my_runnable/stream_log – start på et enkelt input og stream output, inklusive output af mellemliggende trin, efterhånden som det genereres
- GET /my_runnable/input_schema – json-skema til input til det runnable
- GET /my_runnable/output_schema – json-skema til output af den runnable
- GET /my_runnable/config_schema – json-skema til konfiguration af den runnable
Du kan finde en legepladsside til din runnable på /my_runnable/playground. Dette afslører en simpel brugergrænseflade til at konfigurere og påkalde din runnable med streaming output og mellemliggende trin.
For både klient og server:
pip install "langserve[all]"
eller pip installer "langserve[client]" for klientkode, og pip installer "langserve[server]" for serverkode.
Hvis du har brug for at tilføje autentificering til din server, skal du henvise til FastAPI's sikkerhedsdokumentation og middleware-dokumentation.
Du kan implementere til GCP Cloud Run ved hjælp af følgende kommando:
gcloud run deploy [your-service-name] --source . --port 8001 --allow-unauthenticated --region us-central1 --set-env-vars=OPENAI_API_KEY=your_key
LangServe giver support til Pydantic 2 med nogle begrænsninger. OpenAPI-dokumenter vil ikke blive genereret til invoke/batch/stream/stream_log ved brug af Pydantic V2. Fast API understøtter ikke blanding af pydantic v1 og v2 navnerum. LangChain bruger v1-navnerummet i Pydantic v2. Læs venligst følgende retningslinjer for at sikre kompatibilitet med LangChain. Bortset fra disse begrænsninger forventer vi, at API-endepunkterne, legepladsen og alle andre funktioner fungerer som forventet.
LLM-applikationer beskæftiger sig ofte med filer. Der er forskellige arkitekturer, der kan laves til at implementere filbehandling; på højt niveau:
- Filen kan uploades til serveren via et dedikeret slutpunkt og behandles ved hjælp af et separat slutpunkt.
- Filen kan uploades med enten værdi (filbytes) eller reference (f.eks. s3 url til filindhold).
- Behandlingsslutpunktet kan være blokerende eller ikke-blokerende.
- Hvis der kræves væsentlig behandling, kan behandlingen blive overført til en dedikeret procespulje.
Du bør bestemme, hvad der er den passende arkitektur til din applikation. I øjeblikket, for at uploade filer efter værdi til en runable, skal du bruge base64-kodning til filen (multipart/form-data er ikke understøttet endnu).
Her er en eksempel der viser, hvordan man bruger base64-kodning til at sende en fil til en fjernkørbar. Husk, du kan altid uploade filer ved reference (f.eks. s3 url) eller uploade dem som multipart/form-data til et dedikeret slutpunkt.
Input- og outputtyper er defineret på alle runables. Du kan få adgang til dem via egenskaberne input_schema og output_schema. LangServe bruger disse typer til validering og dokumentation. Hvis du vil tilsidesætte de udledte standardtyper, kan du bruge metoden with_types.
Her er et legetøjseksempel for at illustrere ideen:
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)
Arv fra CustomUserType, hvis du ønsker, at dataene skal deserialiseres til en pydantisk model i stedet for den tilsvarende dict-repræsentation. I øjeblikket fungerer denne type kun på serversiden og bruges til at angive ønsket afkodningsadfærd. Hvis den arver fra denne type, vil serveren beholde den afkodede type som en pydantisk model i stedet for at konvertere den til en 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")
Legepladsen giver dig mulighed for at definere brugerdefinerede widgets til din runnable fra backend. En widget angives på feltniveau og sendes som en del af inputtypens JSON-skema. En widget skal indeholde en nøgle kaldet type, hvor værdien er en af en velkendt liste over widgets. Andre widgetnøgler vil blive knyttet til værdier, der beskriver stier i et JSON-objekt.
Generelt skema:
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;
};
Tillader oprettelse af et filupload-input i UI-legepladsen for filer, der uploades som base64-kodede strenge. Her er det fulde eksempel.
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
Automatiser manuelle opgaver og arbejdsgange med vores AI-drevne workflow-bygger, designet af Nanonets til dig og dine teams.
Introduktion til LangSmith
LangChain gør det nemt at prototype LLM applikationer og agenter. Det kan dog være vildledende vanskeligt at levere LLM-applikationer til produktionen. Du bliver sandsynligvis nødt til i høj grad at tilpasse og gentage dine prompter, kæder og andre komponenter for at skabe et produkt af høj kvalitet.
For at hjælpe i denne proces blev LangSmith introduceret, en samlet platform til fejlretning, test og overvågning af dine LLM-applikationer.
Hvornår kan dette være nyttigt? Du kan finde det nyttigt, når du hurtigt vil fejlsøge en ny kæde, agent eller sæt værktøjer, visualisere, hvordan komponenter (kæder, llms, retrievere osv.) relaterer og bruges, evaluere forskellige prompter og LLM'er for en enkelt komponent, køre en given kæde flere gange over et datasæt for at sikre, at det konsekvent opfylder en kvalitetsbar, eller opfang brugsspor og brug LLM'er eller analysepipelines til at generere indsigt.
Forudsætninger:
- Opret en LangSmith-konto og opret en API-nøgle (se nederste venstre hjørne).
- Gør dig bekendt med platformen ved at se dokumenterne igennem.
Lad os nu komme i gang!
Konfigurer først dine miljøvariabler til at fortælle LangChain at logge spor. Dette gøres ved at sætte miljøvariablen LANGCHAIN_TRACING_V2 til sand. Du kan fortælle LangChain, hvilket projekt der skal logges på, ved at indstille miljøvariablen LANGCHAIN_PROJECT (hvis dette ikke er indstillet, vil kørsler blive logget til standardprojektet). Dette vil automatisk oprette projektet for dig, hvis det ikke eksisterer. Du skal også indstille miljøvariablerne LANGCHAIN_ENDPOINT og LANGCHAIN_API_KEY.
BEMÆRK: Du kan også bruge en konteksthåndtering i python til at logge spor ved hjælp af:
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?")
Men i dette eksempel vil vi bruge miljøvariabler.
%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>"
Opret LangSmith-klienten for at interagere med API'en:
from langsmith import Client client = Client()
Opret en LangChain-komponent og log kørsler til platformen. I dette eksempel vil vi oprette en ReAct-lignende agent med adgang til et generelt søgeværktøj (DuckDuckGo). Agentens prompt kan ses i Hub her:
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
)
Vi kører agenten samtidigt på flere input for at reducere latens. Kørsler bliver logget til LangSmith i baggrunden, så udførelsesforsinkelsen er upåvirket:
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]
Forudsat at du har konfigureret dit miljø med succes, bør dine agentspor dukke op i afsnittet Projekter i appen. Tillykke!
Det ser dog ud til, at agenten ikke effektivt bruger værktøjerne. Lad os evaluere dette, så vi har en baseline.
Ud over at logge kørsler giver LangSmith dig også mulighed for at teste og evaluere dine LLM-applikationer.
I dette afsnit vil du udnytte LangSmith til at oprette et benchmark-datasæt og køre AI-assisterede evaluatorer på en agent. Du vil gøre det i et par trin:
- Opret et LangSmith-datasæt:
Nedenfor bruger vi LangSmith-klienten til at oprette et datasæt ud fra inputspørgsmålene fra oven og en listeetiketter. Du vil bruge disse senere til at måle ydeevne for en ny agent. Et datasæt er en samling af eksempler, som ikke er andet end input-output-par, du kan bruge som testcases til din applikation:
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 )
- Initialiser en ny agent for at benchmarke:
LangSmith lader dig evaluere enhver LLM, kæde, agent eller endda en brugerdefineret funktion. Samtaleagenter er statelige (de har hukommelse); for at sikre, at denne tilstand ikke deles mellem datasætkørsler, sender vi en chain_factory (
aka en konstruktør) funktion til at initialisere for hvert opkald:
# 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)
- Konfigurer evaluering:
Manuel sammenligning af resultaterne af kæder i brugergrænsefladen er effektiv, men det kan være tidskrævende. Det kan være nyttigt at bruge automatiserede målinger og AI-assisteret feedback til at evaluere din komponents ydeevne:
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=[],
)
- Kør agenten og evaluatorerne:
Brug funktionen run_on_dataset (eller asynkron arun_on_dataset) til at evaluere din model. Dette vil:
- Hent eksempelrækker fra det angivne datasæt.
- Kør din agent (eller enhver brugerdefineret funktion) på hvert eksempel.
- Anvend evaluatorer på de resulterende kørselsspor og tilsvarende referenceeksempler for at generere automatiseret feedback.
Resultaterne vil være synlige i LangSmith-appen:
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", ],
)
Nu hvor vi har vores testkørselsresultater, kan vi foretage ændringer i vores agent og benchmarke dem. Lad os prøve dette igen med en anden prompt og se resultaterne:
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 lader dig eksportere data til almindelige formater såsom CSV eller JSONL direkte i webappen. Du kan også bruge klienten til at hente kørsler til yderligere analyse, til at gemme i din egen database eller til at dele med andre. Lad os hente kørselssporene fra evalueringskørslen:
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
Dette var en hurtig guide til at komme i gang, men der er mange flere måder at bruge LangSmith til at fremskynde dit udviklerflow og producere bedre resultater.
For mere information om, hvordan du kan få mest muligt ud af LangSmith, se LangSmith-dokumentationen.
Op i niveau med nanonetter
Mens LangChain er et værdifuldt værktøj til at integrere sprogmodeller (LLM'er) med dine applikationer, kan det stå over for begrænsninger, når det kommer til virksomhedsbrug. Lad os undersøge, hvordan Nanonets går ud over LangChain for at løse disse udfordringer:
1. Omfattende dataforbindelse:
LangChain tilbyder stik, men det dækker muligvis ikke alle de workspace-apps og dataformater, som virksomheder er afhængige af. Nanonets leverer dataforbindelser til over 100 udbredte workspace-apps, herunder Slack, Notion, Google Suite, Salesforce, Zendesk og mange flere. Det understøtter også alle ustrukturerede datatyper som PDF'er, TXT'er, billeder, lydfiler og videofiler samt strukturerede datatyper som CSV'er, regneark, MongoDB og SQL-databaser.
2. Opgaveautomatisering til Workspace-apps:
Mens generering af tekst/svar fungerer godt, er LangChains muligheder begrænset, når det kommer til at bruge naturligt sprog til at udføre opgaver i forskellige applikationer. Nanonets tilbyder trigger-/handlingsagenter til de mest populære workspace-apps, så du kan opsætte arbejdsgange, der lytter efter begivenheder og udfører handlinger. For eksempel kan du automatisere e-mail-svar, CRM-poster, SQL-forespørgsler og mere, alt sammen gennem kommandoer i naturligt sprog.
3. Datasynkronisering i realtid:
LangChain henter statiske data med dataforbindelser, som muligvis ikke følger med dataændringer i kildedatabasen. I modsætning hertil sikrer Nanonets synkronisering i realtid med datakilder, hvilket sikrer, at du altid arbejder med den nyeste information.
3. Forenklet konfiguration:
Konfiguration af elementerne i LangChain-pipelinen, såsom retrievere og synthesizere, kan være en kompleks og tidskrævende proces. Nanonets strømliner dette ved at levere optimeret dataindtagelse og indeksering for hver datatype, alt sammen håndteret i baggrunden af AI Assistant. Dette reducerer byrden ved finjustering og gør det nemmere at sætte op og bruge.
4. Samlet løsning:
I modsætning til LangChain, som kan kræve unikke implementeringer for hver opgave, fungerer Nanonets som en one-stop-løsning til at forbinde dine data med LLM'er. Uanset om du skal oprette LLM-applikationer eller AI-arbejdsgange, tilbyder Nanonets en samlet platform til dine forskellige behov.
Nanonets AI arbejdsgange
Nanonets Workflows er en sikker, multi-purpose AI Assistant, der forenkler integrationen af din viden og data med LLM'er og letter oprettelsen af kodefri applikationer og arbejdsgange. Det tilbyder en brugervenlig brugergrænseflade, der gør den tilgængelig for både enkeltpersoner og organisationer.
For at komme i gang kan du planlægge et opkald med en af vores AI-eksperter, som kan give en personlig demo og prøveversion af Nanonets Workflows, der er skræddersyet til din specifikke brugssituation.
Når du først er konfigureret, kan du bruge naturligt sprog til at designe og udføre komplekse applikationer og arbejdsgange drevet af LLM'er, der kan integreres problemfrit med dine apps og data.
Overlad dine teams med Nanonets AI for at skabe apps og integrere dine data med AI-drevne applikationer og arbejdsgange, så dine teams kan fokusere på det, der virkelig betyder noget.
Automatiser manuelle opgaver og arbejdsgange med vores AI-drevne workflow-bygger, designet af Nanonets til dig og dine teams.
- SEO Powered Content & PR Distribution. Bliv forstærket i dag.
- PlatoData.Network Vertical Generative Ai. Styrk dig selv. Adgang her.
- PlatoAiStream. Web3 intelligens. Viden forstærket. Adgang her.
- PlatoESG. Kulstof, CleanTech, Energi, Miljø, Solenergi, Affaldshåndtering. Adgang her.
- PlatoHealth. Bioteknologiske og kliniske forsøgs intelligens. Adgang her.
- Kilde: https://nanonets.com/blog/langchain/
- :har
- :er
- :ikke
- :hvor
- $OP
- 1
- 10
- 100
- 114
- 13
- 15 %
- 2000
- 2012
- 2023
- 25
- 30
- 32
- 36
- 40
- 400
- 408
- 50
- 500
- 7
- 8
- a
- ABC
- evne
- I stand
- Om
- om det
- over
- Acceptere
- accepterer
- adgang
- tilgængelig
- Adgang
- udrette
- derfor
- Konto
- nøjagtighed
- præcis
- præcist
- opnå
- opnået
- opnår
- tværs
- Lov
- Handling
- aktioner
- aktiv
- tilpasse
- adaptive
- tilføje
- tilføjet
- tilføje
- Desuden
- Yderligere
- Derudover
- adresse
- Tilføjer
- indrømme
- fremskreden
- Eventyr
- Efter
- igen
- alder
- Agent
- midler
- AI
- AI assistent
- AI modeller
- Støtte
- sigter
- algoritmer
- tilpasse
- Justerer
- Alle
- tillade
- tillade
- tillader
- alene
- sammen
- langs med
- allerede
- også
- Skønt
- altid
- an
- analyse
- Analytisk
- analytics
- ,
- Angeles
- Annoncere
- årligt
- En anden
- besvare
- svar
- hymne
- Antropisk
- enhver
- noget
- api
- API NØGLER
- API'er
- app
- anvendelig
- Anvendelse
- Application Development
- applikationer
- anvendt
- gælder
- tilgang
- tilgange
- passende
- passende
- apps
- arkitektur
- ER
- argument
- argumenter
- Armstrong
- omkring
- Array
- Artister
- AS
- spørg
- udseende
- aspekter
- hjælpe
- Assistant
- forbundet
- At
- vedhæfte
- opmærksomhed
- lyd
- augmented
- Godkendelse
- automatisere
- Automatiseret
- automater
- automatisk
- Automation
- til rådighed
- gennemsnit
- vente
- opmærksom på
- AWS
- tilbage
- Backbone
- Bagende
- baggrund
- dårligt
- Balance
- Bar
- bund
- baseret
- Baseline
- bash
- grundlæggende
- Grundlæggende
- BCG
- BE
- Beach
- Bears
- fordi
- været
- før
- begynde
- adfærd
- bag
- bag scenen
- være
- jf. nedenstående
- benchmark
- gavnlig
- BEDSTE
- Bedre
- mellem
- Beyond
- Største
- Bill
- Bill Gates
- binde
- Bing
- Bit
- Sort
- Black Hole
- Bloker
- blokering
- Blocks
- Blog
- bob
- Bootstrap
- født
- Bot
- både
- Bund
- Branch
- Pause
- brise
- kortvarigt
- bredere
- brun
- browser
- buffer
- bygge
- Builder
- Bygning
- bygget
- byrde
- virksomheder
- men
- by
- beregne
- beregner
- beregning
- beregning
- ringe
- tilbagekald
- kaldet
- ringer
- Opkald
- CAN
- Kan få
- Canada
- kapaciteter
- stand
- Kapacitet
- fange
- Optagelse
- tilfælde
- tilfælde
- KAT
- imødekomme
- catering
- gearet
- Katte
- forsigtighed
- forsigtig
- centreret
- vis
- kæde
- kæder
- udfordringer
- Ændringer
- karakter
- chatbot
- chatbots
- kontrollere
- Kontrol
- Vælg
- valgt
- omstændigheder
- By
- klasse
- klasser
- kunde
- Cloud
- kode
- Kodning
- Kaffe
- SAMMENHÆNGENDE
- sammenhængende
- samarbejde
- Bryder sammen
- samling
- farverige
- Kolonne
- Kolonner
- KOM
- kombinerer
- kombineret
- kombinerer
- kombinerer
- Kom
- kommer
- behagelig
- Fælles
- Kommunikation
- selskab
- sammenligne
- sammenligne
- kompatibilitet
- kompatibel
- fuldføre
- fuldstændig
- færdiggørelse
- komplekse
- kompleksiteter
- komponent
- komponenter
- sammensat
- sammensætning
- omfattende
- omfattende
- Konceptet
- kortfattet
- konkurrent
- betingelse
- Konfiguration
- sammenløbet
- Tilslut
- Tilslutning
- Connectivity
- ULEMPER
- Overvej
- konsekvent
- består
- Konsol
- konstant
- konstruktioner
- indeholder
- indeholder
- indhold
- sammenhæng
- sammenhænge
- kontekstuelle
- fortsæt
- kontinuerligt
- kontrast
- kontrol
- kontrol
- Praktisk
- Samtale
- konversation
- samtale AI
- samtaler
- Konvertering
- konverteret
- konvertering af
- Core
- Corner
- korrigere
- Tilsvarende
- kunne
- tælle
- land
- Par
- dæksel
- dækket
- skabe
- oprettet
- skaber
- Oprettelse af
- skabelse
- Legitimationsoplysninger
- kriterier
- Critic
- CRM
- afgørende
- Nuværende
- For øjeblikket
- skik
- Kunder
- tilpasning
- tilpasse
- tilpassede
- banebrydende
- data
- Datastruktur
- Database
- databaser
- Dato
- dato tid
- deal
- beskæftiger
- december
- beslutte
- Beslutter
- Beslutningstagning
- Dekodning
- dedikeret
- dybere
- Standard
- definere
- definerede
- definere
- definitioner
- leverer
- leverer
- dykke
- demo
- demonstrere
- demonstreret
- demonstrerer
- afhænge
- Afhængigt
- afhænger
- indsætte
- indsat
- implementering
- implementering
- udruller
- beskrive
- beskrivelse
- Design
- udpeget
- konstrueret
- ønskes
- detail
- detaljeret
- detaljer
- Bestem
- bestemmer
- udvikle
- Udvikler
- udviklere
- udvikling
- Udvikling
- diagrammer
- DICT
- DID
- afvige
- forskellige
- forskelligt
- svært
- Dimension
- størrelse
- direktiver
- direkte
- diskutere
- drøftet
- visning
- distinkt
- dyk
- forskelligartede
- DM
- do
- dokumentet
- dokumentation
- dokumenter
- gør
- gør ikke
- gør
- Don
- færdig
- fordoble
- ned
- downloade
- downloads
- udkast
- køre
- grund
- i løbet af
- dynamisk
- dynamisk
- e
- hver
- tidligere
- Tidligt
- lette
- brugervenlighed
- lettere
- nemt
- let
- nem at bruge
- ekko
- økosystem
- Effektiv
- effektivt
- effektivitet
- effektiv
- effektivt
- ubesværet
- enten
- element
- elementer
- Elon
- Elon Musk
- andet
- Integrer
- indlejret
- indlejring
- selvstændige
- medarbejdere
- beskæftiger
- bemyndige
- muliggøre
- muliggør
- muliggør
- indkapsler
- støder på
- ende til ende
- Endpoint
- engagerende
- Engine (Motor)
- Motorer
- England
- Engelsk
- Engelske Premier League
- forbedre
- forbedret
- styrke
- sikre
- sikrer
- sikring
- Enterprise
- enheder
- enhed
- Miljø
- miljøer
- Ækvivalent
- Era
- fejl
- fejl
- især
- væsentlig
- fraseparerede
- etc.
- evaluere
- evaluering
- Endog
- begivenheder
- Hver
- eksempel
- eksempler
- overstige
- Undtagen
- udføre
- henrettet
- Udfører
- udførelse
- udførelse
- eksemplificerer
- Dyrke motion
- eksisterer
- forvente
- forventninger
- forventet
- forventer
- erfaring
- eksperimenterende
- eksperter
- forklarede
- Forklarer
- udtrykkeligt
- udforskning
- udforske
- udforsket
- eksport
- udtryk
- udvide
- strækker
- omfattende
- ekstern
- ekstra
- ekstrakt
- udvinding
- Uddrag
- Ansigtet
- lette
- letter
- fabrik
- fakta
- langt
- FAST
- Favorit
- Feature
- Funktionalitet
- tilbagemeldinger
- få
- felt
- Fields
- figma
- Figur
- File (Felt)
- Filer
- udfylde
- fyldt
- fyldning
- filtrere
- filtrering
- endelige
- Endelig
- Finde
- finde
- Fornavn
- fem
- Fleksibilitet
- fleksibel
- flow
- Fokus
- fokuserede
- fokuserer
- fokusering
- følger
- efter
- følger
- mad
- Til
- formular
- format
- dannet
- Heldigvis
- fundet
- Framework
- rammer
- hyppigt
- ven
- venner
- fra
- fuld
- fuldgyldigt
- funktion
- funktionaliteter
- funktionalitet
- funktioner
- fundamental
- sjovt
- yderligere
- fremtiden
- Gevinst
- Spil
- Gates
- Generelt
- generelt
- generere
- genereret
- genererer
- generere
- generation
- genre
- Tyskland
- få
- få
- gif
- GitHub
- given
- GMT
- Go
- Goes
- gå
- godt
- kornet
- graf
- stor
- større
- vejledning
- vejlede
- retningslinjer
- hackathon
- håndtere
- Håndterer
- Håndtering
- praktisk
- Hård Ost
- skade
- seler
- Have
- have
- stærkt
- Held
- hjælpe
- hjælpsom
- hjælper
- hende
- link.
- hi
- Høj
- højt niveau
- høj kvalitet
- højeste
- stærkt
- historisk
- historie
- Hole
- hætte
- host
- Hvordan
- How To
- Men
- HTML
- http
- HTTPS
- Hub
- menneskelig
- Hundreder
- i
- ID
- idé
- ideal
- id'er
- if
- ii
- iii
- illustrere
- illustrerer
- billeder
- umiddelbar
- gennemføre
- implementering
- implementeringer
- implementeret
- importere
- forbedringer
- forbedring
- in
- dybdegående
- omfatter
- medtaget
- omfatter
- Herunder
- indarbejde
- inkorporering
- utroligt
- indeks
- indekser
- angiver
- angiver
- Individuelt
- enkeltpersoner
- oplysninger
- initial
- indlede
- innovativ
- indgang
- indgange
- indsigt
- installere
- installeret
- installation
- instans
- øjeblikkelig
- i stedet
- anvisninger
- integral
- integrere
- integreret
- Integrerer
- Integration
- integration
- integrationer
- Intelligent
- beregnet
- interagere
- interaktion
- interaktioner
- interaktiv
- interagerer
- grænseflade
- grænseflader
- internt
- Internet
- ind
- introduceret
- Introducerer
- intuitiv
- involverer
- isn
- spørgsmål
- spørgsmål
- IT
- Varer
- iterationer
- ITS
- selv
- Jackson
- JavaScript
- Job
- Jordan
- rejse
- json
- juli
- lige
- Retfærdighed
- Holde
- holder
- Nøgle
- nøgler
- Venlig
- Kend
- viden
- Viden Graph
- kendt
- etiket
- Etiketter
- Land
- Sprog
- Sprog
- stor
- større
- Efternavn
- Latency
- senere
- seneste
- League
- LÆR
- læring
- til venstre
- Legacy
- Længde
- mindre
- lad
- Lets
- brev
- Niveau
- niveauer
- Leverage
- Udnytter
- løftestang
- biblioteker
- Bibliotek
- ligesom
- Sandsynlig
- GRÆNSE
- begrænsninger
- Limited
- begrænsende
- grænser
- links
- Liste
- lytte
- Lister
- leve
- ll
- LLM
- belastning
- loader
- placeret
- placering
- log
- logget
- logning
- logik
- Lang
- længere
- Se
- leder
- UDSEENDE
- kig op
- den
- Los Angeles
- Lav
- maskine
- machine learning
- lavet
- vedligeholde
- Vedligeholdelig
- Vedligeholdelse
- fastholder
- lave
- maerker
- Making
- administrere
- ledelse
- leder
- styring
- manchester
- Manchester United
- Håndtering
- måde
- manuel
- Fabrikant
- mange
- mange mennesker
- kort
- kortlægning
- Maps
- Match
- matchende
- matematik
- matematiske
- Matters
- maksimal
- Kan..
- me
- betyde
- betyder
- midler
- måle
- Medier
- møde
- opfylder
- Memories
- Hukommelse
- nævnte
- Flet
- sammenlægning
- besked
- beskeder
- messaging
- Metadata
- metode
- metoder
- Metrics
- måske
- millioner
- mindste
- mindre
- mangler
- fejl
- Blanding
- MLB
- Mobil
- model
- modeller
- mådehold
- Moduler
- Moduler
- øjeblik
- MongoDB
- Overvåg
- overvågning
- Moon
- mere
- mest
- Mest Populære
- bevæge sig
- film
- meget
- flere
- flere kæder
- Musk
- skal
- my
- navn
- Som hedder
- navne
- national
- Natural
- Natural Language Processing
- Naviger
- navigering
- I nærheden af
- nødvendig
- Behov
- behov
- behov
- negativ
- Ny
- New York
- New York Times
- næste
- ingen
- Ingen
- intet
- Begreb
- nu
- nummer
- Obama
- objekt
- objektiv
- objekter
- observation
- opnå
- opnå
- OCR
- of
- tilbyde
- tilbyde
- Tilbud
- tit
- oh
- Okay
- OL
- on
- engang
- ONE
- kun
- open source
- OpenAI
- Produktion
- operatør
- optimeret
- Optimerer
- Option
- or
- ordrer
- organisk
- organisationer
- original
- OS
- Andet
- Andre
- Ellers
- vores
- ud
- output
- udgange
- i løbet af
- overstyring
- oversigt
- egen
- pakke
- pakker
- side
- sider
- par
- pandaer
- Papir
- Parallel
- parameter
- parametre
- Park
- del
- især
- dele
- passerer
- Bestået
- gennemløb
- Passing
- forbi
- sti
- stier
- mønstre
- Lønningsliste
- Mennesker
- per
- perfekt
- perfekt
- Udfør
- ydeevne
- udfører
- udfører
- Tilladelser
- udholdenhed
- person,
- Personlig
- perspektiv
- Fysik
- stykke
- pipeline
- Pizza
- pladsholder
- perron
- plato
- Platon Data Intelligence
- PlatoData
- Leg
- legeplads
- spiller
- Vær venlig
- plus
- Punkt
- politikker
- politik
- politisk
- pool
- Populær
- befolkede
- positiv
- mulig
- Indlæg
- Indlæg
- potentiale
- magt
- strøm
- vigtigste
- Praktisk
- praksis
- foretrække
- premier
- præsentere
- præsident
- forhindre
- forebyggelse
- tidligere
- primært
- primære
- Prime
- private
- Problem
- problemer
- Fortsæt
- behandle
- Behandlet
- Processer
- forarbejdning
- producere
- Produkt
- produktion
- Professor
- Programmering
- programmeringssprog
- projekt
- projekter
- egenskaber
- ejendom
- PROS
- prototype
- prototyping
- give
- forudsat
- udbyder
- udbydere
- giver
- leverer
- offentlige
- formål
- formål
- sætte
- Python
- Spørgsmål og svar
- kvalitet
- forespørgsler
- spørgsmål
- Spørgsmål
- Hurtig
- hurtigt
- citater
- R
- rejse
- rækkevidde
- spænder
- hellere
- bedømmelse
- Raw
- RE
- nå
- Reagerer
- Læs
- Læsning
- klar
- ægte
- realtid
- data i realtid
- rige
- grund
- årsager
- nylige
- anbefales
- registreres
- optegnelser
- Recover
- reducere
- reducerer
- reducere
- reduktion
- henvisningen
- henvisninger
- raffinere
- raffinering
- regioner
- Relationer
- frigivet
- relevans
- relevant
- pålidelighed
- pålidelig
- stole
- stole
- resterne
- huske
- påmindelse
- fjern
- udbytte
- gentag
- GENTAGNE GANGE
- omformulering
- erstatte
- indberette
- Repository
- repræsentation
- repræsenterer
- repræsenterer
- anmode
- anmodninger
- kræver
- påkrævet
- Krav
- Kræver
- redde
- forskning
- løse
- ressource
- Svar
- reagere
- svar
- reaktioner
- ansvarlige
- lydhør
- REST
- resultere
- resulterer
- Resultater
- tilbageholdende
- tilbageholdelse
- afkast
- vender tilbage
- afkast
- genanvendelige
- gennemgå
- roterer
- Ris
- Rich
- robotter
- roller
- roller
- rod
- routing
- RÆKKE
- Kør
- kører
- løber
- runtime
- s
- sikkerhedsforanstaltninger
- salg
- salgsstyrke
- Sam
- samme
- Gem
- siger
- siger
- skalerbar
- Scale
- scenarie
- scenarier
- scener
- planlægge
- score
- ridse
- sømløs
- problemfrit
- Søg
- søgemaskine
- søgninger
- søgning
- Sektion
- sektioner
- sikker
- sikkerhed
- se
- valgt
- valg
- Salg
- send
- følsom
- stemningen
- følelser
- adskille
- september
- Sequence
- Series
- tjener
- server
- tjener
- Tjenester
- sæt
- sæt
- indstilling
- indstillinger
- setup
- syv
- flere
- Del
- delt
- Shell
- skinner
- afsendt
- bør
- Vis
- udstillingsvindue
- vist
- Shows
- Sigma
- signifikant
- lignende
- Simpelt
- forenklet
- forenkle
- forenkle
- ganske enkelt
- siden
- enkelt
- Størrelse
- slæk
- lille
- mindre
- Smart
- uddrag
- So
- indtil nu
- Fodbold
- Social
- sociale medier
- Indlæg på sociale medier
- Alene
- solid
- løsninger
- SOLVE
- nogle
- noget
- sommetider
- sofistikeret
- lyde
- Kilde
- Kilder
- Space
- Spansk
- specialiserede
- specifikke
- specifikt
- detaljerne
- specificeret
- hastighed
- brugt
- delt
- splits
- Sport
- firkant
- stå
- standalone
- standard
- starte
- påbegyndt
- Starter
- Tilstand
- udsagn
- statisk
- Trin
- Steps
- Stadig
- Stands
- standsning
- stopper
- opbevaring
- butik
- opbevaret
- forhandler
- lagring
- Story
- ligetil
- strøm
- streaming
- strømline
- strømlinet
- styrker
- Strejker
- String
- struktur
- struktureret
- strukturer
- strukturering
- stil
- emne
- efterfølgende
- Succesfuld
- sådan
- Dragt
- egnede
- suite
- opsummere
- RESUMÉ
- Solnedgang
- support
- Understøttet
- Understøtter
- sikker
- Bæredygtighed
- synkronisering
- synopsis
- syntaks
- systemet
- Systemer
- bord
- skrædder
- skræddersyet
- Tag
- tager
- mål
- Opgaver
- opgaver
- hold
- hold
- fortælle
- skabelon
- skabeloner
- terminal
- terminologi
- vilkår
- prøve
- Test
- tekst
- end
- Tak
- at
- Grundlæggende
- navet
- oplysninger
- The New York Times
- Projekterne
- The Source
- verdenen
- deres
- Them
- derefter
- Der.
- Disse
- de
- ting
- denne
- dem
- selvom?
- Gennem
- hele
- tid
- tidskrævende
- gange
- Titel
- til
- sammen
- token
- tokenization
- Tokens
- også
- værktøj
- toolkit
- værktøjer
- top
- emne
- Emner
- I alt
- Byen
- Sporing
- spor
- traditionelle
- Kurser
- Transform
- transformationer
- transformer
- transformers
- overgang
- retssag
- sand
- virkelig
- prøv
- tuning
- TUR
- Drejning
- tutorial
- To gange
- to
- typen
- typer
- maskinskrift
- typisk
- ui
- Ultimativt
- upåvirket
- under
- underliggende
- forstå
- forståelse
- forstår
- forenet
- enestående
- Forenet
- Universal
- I modsætning til
- indtil
- Opdatering
- opdateringer
- uploadet
- URL
- us
- usability
- Brug
- brug
- brug tilfælde
- anvendte
- Bruger
- Brugergrænseflade
- brugere
- bruger
- ved brug af
- forsyningsselskaber
- udnytte
- udnyttet
- udnytter
- Ved hjælp af
- v1
- validering
- Validator
- Værdifuld
- værdi
- Værdier
- variabel
- række
- forskellige
- Ve
- alsidige
- udgave
- meget
- via
- video
- Specifikation
- Overtrædelser
- synlig
- Visualiser
- afgørende
- vs
- gå
- går igennem
- ønsker
- var
- Ur
- Vej..
- måder
- we
- Vejr
- web
- webbrowser
- webservices
- websites
- GODT
- Kendt
- var
- Hvad
- Hvad er
- Whats
- hvornår
- hvorvidt
- som
- mens
- WHO
- Hele
- hvorfor
- bred
- bredt
- widget
- Wikipedia
- vilje
- vindue
- Vinder
- med
- inden for
- uden
- ord
- Arbejde
- arbejdede
- workflow
- arbejdsgange
- arbejder
- virker
- world
- ville
- skriver
- skrivning
- X
- endnu
- york
- Du
- Din
- dig selv
- youtube
- Zendesk
- zephyrnet
- Zip