I kjernen, Langkjede er et innovativt rammeverk skreddersydd for å lage applikasjoner som utnytter funksjonene til språkmodeller. Det er et verktøysett designet for utviklere for å lage applikasjoner som er kontekstbevisste og i stand til sofistikert resonnement.
Dette betyr at LangChain-applikasjoner kan forstå konteksten, for eksempel umiddelbare instruksjoner eller innholdsbaserte svar og bruke språkmodeller for komplekse resonneringsoppgaver, som å bestemme hvordan de skal svare eller hvilke handlinger som skal utføres. LangChain representerer en enhetlig tilnærming til å utvikle intelligente applikasjoner, som forenkler reisen fra konsept til utførelse med de forskjellige komponentene.
Forstå LangChain
LangChain er mye mer enn bare et rammeverk; det er et fullverdig økosystem som består av flere integrerte deler.
- For det første er det LangChain-bibliotekene, tilgjengelig i både Python og JavaScript. Disse bibliotekene er ryggraden i LangChain, og tilbyr grensesnitt og integrasjoner for ulike komponenter. De gir en grunnleggende kjøretid for å kombinere disse komponentene til sammenhengende kjeder og agenter, sammen med ferdige implementeringer for umiddelbar bruk.
- Deretter har vi LangChain-maler. Dette er en samling av distribuerbare referansearkitekturer som er skreddersydd for et bredt spekter av oppgaver. Enten du bygger en chatbot eller et komplekst analytisk verktøy, gir disse malene et solid utgangspunkt.
- LangServe trer inn som et allsidig bibliotek for å distribuere LangChain-kjeder som REST APIer. Dette verktøyet er viktig for å gjøre LangChain-prosjektene dine om til tilgjengelige og skalerbare webtjenester.
- Til slutt fungerer LangSmith som en utviklerplattform. Den er designet for å feilsøke, teste, evaluere og overvåke kjeder bygget på ethvert LLM-rammeverk. Den sømløse integrasjonen med LangChain gjør det til et uunnværlig verktøy for utviklere som ønsker å avgrense og perfeksjonere applikasjonene sine.
Sammen gir disse komponentene deg i stand til å utvikle, produsere og distribuere applikasjoner med letthet. Med LangChain starter du med å skrive søknadene dine ved hjelp av bibliotekene, og refererer til maler for veiledning. LangSmith hjelper deg deretter med å inspisere, teste og overvåke kjedene dine, og sikre at applikasjonene dine stadig forbedres og klare for distribusjon. Til slutt, med LangServe, kan du enkelt transformere hvilken som helst kjede til et API, noe som gjør distribusjon til en lek.
I de neste avsnittene vil vi gå dypere inn i hvordan du setter opp LangChain og begynner reisen din med å lage intelligente, språkmodelldrevne applikasjoner.
Automatiser manuelle oppgaver og arbeidsflyter med vår AI-drevne arbeidsflytbygger, designet av Nanonets for deg og teamene dine.
Installasjon og oppsett
Er du klar til å dykke inn i LangChain-verdenen? Det er enkelt å konfigurere det, og denne veiledningen vil lede deg gjennom prosessen steg-for-steg.
Det første trinnet i din LangChain-reise er å installere den. Du kan enkelt gjøre dette ved å bruke pip eller conda. Kjør følgende kommando i terminalen din:
pip install langchain
For de som foretrekker de nyeste funksjonene og er komfortable med litt mer eventyr, kan du installere LangChain direkte fra kilden. Klon depotet og naviger til langchain/libs/langchain
katalog. Kjør deretter:
pip install -e .
For eksperimentelle funksjoner bør du vurdere å installere langchain-experimental
. Det er en pakke som inneholder banebrytende kode og er beregnet på forskning og eksperimentelle formål. Installer den ved å bruke:
pip install langchain-experimental
LangChain CLI er et hendig verktøy for å jobbe med LangChain-maler og LangServe-prosjekter. For å installere LangChain CLI, bruk:
pip install langchain-cli
LangServe er avgjørende for å distribuere LangChain-kjedene dine som en REST API. Den blir installert sammen med LangChain CLI.
LangChain krever ofte integrasjoner med modellleverandører, datalagre, APIer osv. For dette eksempelet vil vi bruke OpenAI sine modell APIer. Installer OpenAI Python-pakken ved å bruke:
pip install openai
For å få tilgang til API-en, angi OpenAI API-nøkkelen som en miljøvariabel:
export OPENAI_API_KEY="your_api_key"
Alternativt kan du sende nøkkelen direkte i pythonmiljøet ditt:
import os
os.environ['OPENAI_API_KEY'] = 'your_api_key'
LangChain gjør det mulig å lage språkmodellapplikasjoner gjennom moduler. Disse modulene kan enten stå alene eller være sammensatt for komplekse brukstilfeller. Disse modulene er -
- Modell I/O: Forenkler interaksjon med ulike språkmodeller, og håndterer deres input og utganger effektivt.
- Henting: Gir tilgang til og interaksjon med applikasjonsspesifikke data, avgjørende for dynamisk datautnyttelse.
- Agenter: Gi applikasjoner mulighet til å velge passende verktøy basert på direktiver på høyt nivå, noe som forbedrer beslutningsevnen.
- Kjeder: Tilbyr forhåndsdefinerte, gjenbrukbare komposisjoner som fungerer som byggesteiner for applikasjonsutvikling.
- Minne: Opprettholder applikasjonstilstand på tvers av flere kjedekjøringer, avgjørende for kontekstbevisste interaksjoner.
Hver modul retter seg mot spesifikke utviklingsbehov, noe som gjør LangChain til et omfattende verktøysett for å lage avanserte språkmodellapplikasjoner.
Sammen med de ovennevnte komponentene har vi også LangChain Expression Language (LCEL), som er en deklarativ måte å enkelt komponere moduler sammen, og dette muliggjør sammenkobling av komponenter ved hjelp av et universelt Runnable-grensesnitt.
LCEL ser omtrent slik ut –
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import BaseOutputParser # Example chain
chain = ChatPromptTemplate() | ChatOpenAI() | CustomOutputParser()
Nå som vi har dekket det grunnleggende, vil vi fortsette til:
- Grav dypere inn i hver Langchain-modul i detalj.
- Lær hvordan du bruker LangChain Expression Language.
- Utforsk vanlige brukstilfeller og implementer dem.
- Distribuer en ende-til-ende-applikasjon med LangServe.
- Sjekk ut LangSmith for feilsøking, testing og overvåking.
La oss komme i gang!
Modul I : Modell I/O
I LangChain dreier kjerneelementet i enhver applikasjon seg rundt språkmodellen. Denne modulen gir de essensielle byggesteinene for effektivt grensesnitt med enhver språkmodell, og sikrer sømløs integrasjon og kommunikasjon.
Nøkkelkomponenter i modell I/O
- LLM-er og chat-modeller (brukes om hverandre):
- LLM-er:
- Definisjon: Rene tekstfullføringsmodeller.
- Input / Output: Ta en tekststreng som input og returner en tekststreng som utdata.
- Chat-modeller
- LLM-er:
- Definisjon: Modeller som bruker en språkmodell som basis, men som er forskjellige i input- og outputformater.
- Input / Output: Godta en liste over chat-meldinger som input og returner en chat-melding.
- Ledetekster: Mal, dynamisk velg og administrer modellinndata. Gir mulighet for å lage fleksible og kontekstspesifikke spørsmål som veileder språkmodellens svar.
- Utdataparsere: Trekk ut og formater informasjon fra modellutganger. Nyttig for å konvertere rå utdata fra språkmodeller til strukturerte data eller spesifikke formater som applikasjonen trenger.
LLM-er
LangChains integrasjon med store språkmodeller (LLM) som OpenAI, Cohere og Hugging Face er et grunnleggende aspekt ved funksjonaliteten. LangChain selv er ikke vert for LLM-er, men tilbyr et enhetlig grensesnitt for å samhandle med forskjellige LLM-er.
Denne delen gir en oversikt over bruk av OpenAI LLM-innpakningen i LangChain, som også kan brukes på andre LLM-typer. Vi har allerede installert dette i delen "Komme i gang". La oss initialisere LLM.
from langchain.llms import OpenAI
llm = OpenAI()
- LLM-er implementerer Kjørbart grensesnitt, den grunnleggende byggesteinen til LangChain Expression Language (LCEL). Dette betyr at de støtter
invoke
,ainvoke
,stream
,astream
,batch
,abatch
,astream_log
samtaler. - LLMs aksepterer strenger som innganger, eller objekter som kan tvinges til strengmeldinger, inkludert
List[BaseMessage]
ogPromptValue
. (mer om disse senere)
La oss se på noen eksempler.
response = llm.invoke("List the seven wonders of the world.")
print(response)
Du kan alternativt kalle strømmemetoden for å streame tekstsvaret.
for chunk in llm.stream("Where were the 2012 Olympics held?"): print(chunk, end="", flush=True)
Chat-modeller
LangChains integrasjon med chat-modeller, en spesialisert variant av språkmodeller, er avgjørende for å lage interaktive chat-applikasjoner. Mens de bruker språkmodeller internt, presenterer chat-modeller et distinkt grensesnitt sentrert rundt chat-meldinger som innganger og utganger. Denne delen gir en detaljert oversikt over bruk av OpenAIs chat-modell i LangChain.
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI()
Chattemodeller i LangChain jobber med ulike meldingstyper som f.eks AIMessage
, HumanMessage
, SystemMessage
, FunctionMessage
og ChatMessage
(med en vilkårlig rolleparameter). Som regel, HumanMessage
, AIMessage
og SystemMessage
er de mest brukte.
Chat-modeller aksepterer primært List[BaseMessage]
som innganger. Strenger kan konverteres til HumanMessage
og PromptValue
er også støttet.
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)
Ledetekster
Spørsmål er avgjørende for å veilede språkmodeller for å generere relevante og sammenhengende utdata. De kan variere fra enkle instruksjoner til komplekse få-shot-eksempler. I LangChain kan håndtering av spørsmål være en svært strømlinjeformet prosess, takket være flere dedikerte klasser og funksjoner.
LangChain sin PromptTemplate
class er et allsidig verktøy for å lage strengmeldinger. Den bruker Python's str.format
syntaks, som tillater dynamisk promptgenerering. Du kan definere en mal med plassholdere og fylle dem med spesifikke verdier etter 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 chattemodeller er forespørsler mer strukturerte, og involverer meldinger med spesifikke roller. LangChain tilbyr ChatPromptTemplate
for 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 tilnærmingen gjør det mulig å lage interaktive, engasjerende chatbots med dynamiske svar.
Begge PromptTemplate
og ChatPromptTemplate
integreres sømløst med LangChain Expression Language (LCEL), slik at de kan være en del av større, komplekse arbeidsflyter. Vi vil diskutere mer om dette senere.
Tilpassede ledetekstmaler er noen ganger avgjørende for oppgaver som krever unik formatering eller spesifikke instruksjoner. Å lage en egendefinert ledetekstmal innebærer å definere inndatavariabler og en tilpasset formateringsmetode. Denne fleksibiliteten gjør at LangChain kan imøtekomme et bredt spekter av applikasjonsspesifikke krav. Les mer her.
LangChain støtter også spørring med få skudd, noe som gjør at modellen kan lære av eksempler. Denne funksjonen er avgjørende for oppgaver som krever kontekstuell forståelse eller spesifikke mønstre. Få-shot-ledetekstmaler kan bygges fra et sett med eksempler eller ved å bruke et eksempelvelgerobjekt. Les mer her.
Utdataparsere
Utdataparsere spiller en avgjørende rolle i Langchain, og gjør det mulig for brukere å strukturere svarene som genereres av språkmodeller. I denne delen vil vi utforske konseptet med utdataparsere og gi kodeeksempler ved å bruke Langchains PydanticOutputParser, SimpleJsonOutputParser, CommaSeparatedListOutputParser, DatetimeOutputParser og XMLOutputParser.
PydanticOutputParser
Langchain tilbyr PydanticOutputParser for å analysere svar inn i Pydantiske datastrukturer. Nedenfor er et trinn-for-steg eksempel på hvordan du bruker 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)
Utgangen vil være:
SimpleJsonOutputParser
Langchains SimpleJsonOutputParser brukes når du vil analysere JSON-lignende utganger. 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 nyttig når du vil trekke ut kommaseparerte lister fra modellsvar. 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 for å analysere datetime-informasjon. Slik bruker 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 eksemplene viser hvordan Langchains utdataparsere kan brukes til å strukturere ulike typer modellresponser, noe som gjør dem egnet for forskjellige applikasjoner og formater. Utdataparsere er et verdifullt verktøy for å forbedre brukervennligheten og tolkbarheten til språkmodellutdata i Langchain.
Automatiser manuelle oppgaver og arbeidsflyter med vår AI-drevne arbeidsflytbygger, designet av Nanonets for deg og teamene dine.
Modul II : Henting
Henting i LangChain spiller en avgjørende rolle i applikasjoner som krever brukerspesifikke data, ikke inkludert i modellens treningssett. Denne prosessen, kjent som Retrieval Augmented Generation (RAG), innebærer å hente eksterne data og integrere dem i språkmodellens generasjonsprosess. LangChain tilbyr en omfattende pakke med verktøy og funksjoner for å forenkle denne prosessen, både for enkle og komplekse applikasjoner.
LangChain oppnår gjenfinning gjennom en rekke komponenter som vi vil diskutere en etter en.
Dokumentlastere
Dokumentlastere i LangChain muliggjør utvinning av data fra ulike kilder. Med over 100 lastere tilgjengelig støtter de en rekke dokumenttyper, apper og kilder (private s3-bøtter, offentlige nettsteder, databaser).
Du kan velge en dokumentlaster basert på dine behov her..
Alle disse lasterne tar inn data Document klasser. Vi lærer hvordan du bruker data som er tatt inn i dokumentklasser senere.
Tekstfillaster: Last inn en enkel .txt
fil i et dokument.
from langchain.document_loaders import TextLoader loader = TextLoader("./sample.txt")
document = loader.load()
CSV-laster: Last inn 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 velge å tilpasse parsingen ved å spesifisere feltnavn –
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-lastere: PDF-lastere i LangChain tilbyr ulike metoder for å analysere og trekke ut innhold fra PDF-filer. Hver laster tilfredsstiller forskjellige krav og bruker forskjellige underliggende biblioteker. Nedenfor er detaljerte eksempler for hver laster.
PyPDFLoader brukes til grunnleggende PDF-parsing.
from langchain.document_loaders import PyPDFLoader loader = PyPDFLoader("example_data/layout-parser-paper.pdf")
pages = loader.load_and_split()
MathPixLoader er ideell for å trekke ut matematisk innhold og diagrammer.
from langchain.document_loaders import MathpixPDFLoader loader = MathpixPDFLoader("example_data/math-content.pdf")
data = loader.load()
PyMuPDFLoader er rask og inkluderer detaljert metadatautvinning.
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 brukes for mer detaljert kontroll over tekstutvinning.
from langchain.document_loaders import PDFMinerLoader loader = PDFMinerLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
AmazonTextractPDFParser bruker AWS Textract for OCR og andre avanserte PDF-parsingsfunksjoner.
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 for semantisk analyse.
from langchain.document_loaders import PDFMinerPDFasHTMLLoader loader = PDFMinerPDFasHTMLLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
PDFPlumberLoader gir detaljerte metadata og støtter ett dokument per side.
from langchain.document_loaders import PDFPlumberLoader loader = PDFPlumberLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
Integrerte lastere: LangChain tilbyr et bredt utvalg av tilpassede lastere for å direkte laste inn data fra appene dine (som Slack, Sigma, Notion, Confluence, Google Drive og mange flere) og databaser og bruke dem i LLM-applikasjoner.
Den komplette listen er her..
Nedenfor er et par eksempler for å illustrere dette –
Eksempel I – Slakk
Slack, en mye brukt plattform for direktemeldinger, kan integreres i LLM arbeidsflyter og applikasjoner.
- Gå til Slack Workspace Management-siden.
- naviger til
{your_slack_domain}.slack.com/services/export
. - Velg ønsket datoperiode og start eksporten.
- Slack varsler via e-post og DM når eksporten er klar.
- Eksporten resulterer i en
.zip
filen som ligger i mappen Nedlastinger eller den angitte nedlastingsbanen. - Tilordne banen til den nedlastede
.zip
filen tilLOCAL_ZIPFILE
. - Bruke
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 verktøy for grensesnittdesign, tilbyr en REST API for dataintegrasjon.
- Skaff Figma-filnøkkelen fra URL-formatet:
https://www.figma.com/file/{filekey}/sampleFilename
. - Node-ID-er finnes i URL-parameteren
?node-id={node_id}
. - Generer et tilgangstoken ved å følge instruksjonene på Figma hjelpesenter.
- De
FigmaFileLoader
klasse fralangchain.document_loaders.figma
brukes til å laste Figma-data. - Ulike LangChain-moduler som
CharacterTextSplitter
,ChatOpenAI
osv., er ansatt for behandling.
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()
- De
generate_code
funksjonen bruker Figma-dataene til å lage HTML/CSS-kode. - Den bruker en malbasert samtale med en GPT-basert modell.
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)
- De
generate_code
funksjon, når den utføres, returnerer HTML/CSS-kode basert på Figma-designinndata.
La oss nå bruke kunnskapen vår til å lage noen få dokumentsett.
Vi laster først en PDF, BCGs årlige bærekraftsrapport.
Vi bruker 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 vil ta inn data fra Airtable nå. Vi har en Airtable som inneholder informasjon om ulike OCR- og dataekstraksjonsmodeller –
La oss bruke AirtableLoader til dette, som finnes i listen over integrerte lastere.
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()
La oss nå fortsette og lære hvordan du bruker disse dokumentklassene.
Dokumenttransformatorer
Dokumenttransformatorer i LangChain er essensielle verktøy designet for å manipulere dokumenter, som vi laget i forrige underseksjon.
De brukes til oppgaver som å dele opp lange dokumenter i mindre biter, kombinere og filtrere, noe som er avgjørende for å tilpasse dokumenter til en modells kontekstvindu eller møte spesifikke applikasjonsbehov.
Et slikt verktøy er RecursiveCharacterTextSplitter, en allsidig tekstsplitter som bruker en tegnliste for å dele. Den tillater parametere som delstørrelse, overlapping og startindeks. Her er et eksempel på hvordan det brukes 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 annet verktøy er CharacterTextSplitter, som deler tekst basert på et spesifisert tegn og inkluderer kontroller for delstørrelse og overlapping:
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 for å dele HTML-innhold basert på overskriftskoder, og beholde den semantiske strukturen:
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 mer kompleks manipulasjon kan oppnås ved å kombinere HTMLHeaderTextSplitter med en annen splitter, 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 tilbyr også spesifikke splittere for forskjellige programmeringsspråk, 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])
For å dele tekst basert på tokenantall, som er nyttig for språkmodeller med tokengrenser, brukes 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])
Til slutt omorganiserer LongContextReorder dokumenter for å forhindre ytelsesforringelse i modeller på grunn av lange kontekster:
from langchain.document_transformers import LongContextReorder reordering = LongContextReorder()
reordered_docs = reordering.transform_documents(docs)
print(reordered_docs[0])
Disse verktøyene viser ulike måter å transformere dokumenter i LangChain på, fra enkel tekstdeling til kompleks omorganisering og språkspesifikk deling. For mer dyptgående og spesifikke brukstilfeller bør dokumentasjons- og integrasjonsdelen for LangChain konsulteres.
I eksemplene våre har lasterne allerede laget stykker av dokumenter for oss, og denne delen er allerede håndtert.
Tekstinnbyggingsmodeller
Tekstinnbyggingsmodeller i LangChain gir et standardisert grensesnitt for ulike leverandører av innebyggingsmodeller som OpenAI, Cohere og Hugging Face. Disse modellene transformerer tekst til vektorrepresentasjoner, og muliggjør operasjoner som semantisk søk gjennom tekstlikhet i vektorrom.
For å komme i gang med tekstinnbyggingsmodeller, må du vanligvis installere spesifikke pakker og sette opp API-nøkler. Vi har allerede gjort dette for OpenAI
I LangChain er det embed_documents
metoden brukes til å bygge inn flere tekster, og gir en liste over vektorrepresentasjoner. 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 å bygge inn en enkelt tekst, for eksempel et søk, embed_query
metoden brukes. Dette er nyttig for å sammenligne en spørring med et sett med dokumentinnbygginger. 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])
Å forstå disse innebyggingene er avgjørende. Hvert tekststykke konverteres til en vektor, hvis dimensjon avhenger av modellen som brukes. For eksempel produserer OpenAI-modeller vanligvis 1536-dimensjonale vektorer. Disse innebyggingene brukes deretter for å hente relevant informasjon.
LangChains innebyggingsfunksjonalitet er ikke begrenset til OpenAI, men er designet for å fungere med ulike leverandører. Oppsettet og bruken kan variere litt avhengig av leverandøren, men kjernekonseptet med å bygge inn tekster i vektorrom forblir det samme. For detaljert bruk, inkludert avanserte konfigurasjoner og integrasjoner med ulike leverandører av innebyggingsmodeller, er LangChain-dokumentasjonen i Integrations-delen en verdifull ressurs.
Vektorbutikker
Vektorbutikker i LangChain støtter effektiv lagring og søking av tekstinnbygging. LangChain integreres med over 50 vektorbutikker, og gir et standardisert grensesnitt for enkel bruk.
Eksempel: Lagring og søk etter innebygginger
Etter å ha innebygd tekster, kan vi lagre dem i en vektorbutikk som Chroma
og utføre likhetssøk:
from langchain.vectorstores import Chroma db = Chroma.from_texts(embedded_texts)
similar_texts = db.similarity_search("search query")
La oss alternativt bruke FAISS vektorlager for å lage indekser for dokumentene våre.
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 grensesnitt som returnerer dokumenter som svar på en ustrukturert spørring. De er mer generelle enn vektorbutikker, og fokuserer på gjenfinning i stedet for lagring. Selv om vektorlagre kan brukes som en retrievers ryggrad, finnes det også andre typer retrievere.
For å sette opp en Chroma retriever, installerer du den først ved hjelp av pip install chromadb
. Deretter laster, deler, bygger du inn og henter dokumenter ved hjelp av en rekke Python-kommandoer. Her er et kodeeksempel for å sette opp 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 hurtiginnstilling ved å generere flere spørringer for en brukerinndataspørring og kombinerer resultatene. Her er et eksempel på enkel bruk:
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))
Kontekstuell komprimering i LangChain komprimerer hentede dokumenter ved å bruke konteksten til spørringen, og sikrer at kun relevant informasjon returneres. Dette innebærer innholdsreduksjon og filtrering av mindre relevante dokumenter. Følgende kodeeksempel viser hvordan du bruker 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 ulike gjenfinningsalgoritmer for å oppnå bedre ytelse. Et eksempel på å 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 gjør det mulig å spørre etter dokumenter med flere vektorer per dokument, noe som er nyttig for å fange opp forskjellige semantiske aspekter i et dokument. Metoder for å lage flere vektorer inkluderer å dele opp i mindre biter, oppsummere eller generere hypotetiske spørsmål. For å dele opp dokumenter i mindre biter, kan følgende Python-kode brukes:
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 av sammendrag for bedre gjenfinning på grunn av mer fokusert innholdsrepresentasjon er en annen metode. Her er et eksempel på generering av sammendrag:
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)))
Å generere hypotetiske spørsmål som er relevante for hvert dokument ved hjelp av LLM er en annen tilnærming. Dette kan gjø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 annen retriever som finner en balanse mellom innebygging av nøyaktighet og kontekstbevaring ved å lagre små biter og hente de større overordnede dokumentene. Implementeringen 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 selvsøkende retriever konstruerer strukturerte spørringer fra naturlige språkinndata og bruker dem til dens underliggende VectorStore. Implementeringen 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 utfører nettundersøkelser basert på en gitt spørring –
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")
For våre eksempler kan vi også bruke standard retriever som allerede er implementert som en del av vårt vektorlagerobjekt som følger –
Vi kan nå spørre etter retrieverne. Utdataene fra spørringen vår vil være dokumentobjekter som er relevante for spørringen. Disse vil til slutt bli brukt til å lage relevante svar i videre seksjoner.
Automatiser manuelle oppgaver og arbeidsflyter med vår AI-drevne arbeidsflytbygger, designet av Nanonets for deg og teamene dine.
Modul III: Agenter
LangChain introduserer et kraftig konsept kalt "Agents" som tar ideen om kjeder til et helt nytt nivå. Agenter utnytter språkmodeller for dynamisk å bestemme sekvenser av handlinger som skal utføres, noe som gjør dem utrolig allsidige og tilpasningsdyktige. I motsetning til tradisjonelle kjeder, der handlinger er hardkodet i kode, bruker agenter språkmodeller som resonneringsmotorer for å bestemme hvilke handlinger som skal utføres og i hvilken rekkefølge.
Agenten er kjernekomponenten som er ansvarlig for beslutningstaking. Den utnytter kraften til en språkmodell og en oppfordring til å bestemme de neste trinnene for å oppnå et spesifikt mål. Inndataene til en agent inkluderer vanligvis:
- Verktøy: Beskrivelser av tilgjengelige verktøy (mer om dette senere).
- Brukerinndata: Høynivåmålet eller spørringen fra brukeren.
- Mellomtrinn: En historie med (handling, verktøyutgang) par utført for å nå gjeldende brukerinndata.
Utgangen til en agent kan være den neste handling å iverksette tiltak (Agenthandlinger) eller finalen svar å sende til brukeren (AgentFinish). en handling spesifiserer a verktøy og inngang for det verktøyet.
verktøy
Verktøy er grensesnitt som en agent kan bruke for å samhandle med verden. De gjør det mulig for agenter å utføre ulike oppgaver, for eksempel å søke på nettet, kjøre skallkommandoer eller få tilgang til eksterne API-er. I LangChain er verktøy avgjørende for å utvide egenskapene til agenter og gjøre dem i stand til å utføre forskjellige oppgaver.
For å bruke verktøy i LangChain, kan du laste dem ved å bruke følgende kodebit:
from langchain.agents import load_tools tool_names = [...]
tools = load_tools(tool_names)
Noen verktøy kan kreve en grunnleggende språkmodell (LLM) for å initialiseres. I slike tilfeller kan du også bestå en LLM:
from langchain.agents import load_tools tool_names = [...]
llm = ...
tools = load_tools(tool_names, llm=llm)
Dette oppsettet lar deg få tilgang til en rekke verktøy og integrere dem i agentens arbeidsflyter. Den komplette listen over verktøy med bruksdokumentasjon er her..
La oss se på noen eksempler på verktøy.
DuckDuckGo
DuckDuckGo-verktøyet lar deg utføre nettsøk ved hjelp av søkemotoren. Slik bruker du den:
from langchain.tools import DuckDuckGoSearchRun
search = DuckDuckGoSearchRun()
search.run("manchester united vs luton town match summary")
DataForSeo
DataForSeo-verktøysettet lar deg få søkemotorresultater ved å bruke DataForSeo API. For å bruke dette verktøysettet, må du konfigurere API-legitimasjonen din. Slik konfigurerer du legitimasjonen:
import os os.environ["DATAFORSEO_LOGIN"] = "<your_api_access_username>"
os.environ["DATAFORSEO_PASSWORD"] = "<your_api_access_password>"
Når legitimasjonen din er angitt, kan du opprette en DataForSeoAPIWrapper
verktøy for å få tilgang til API:
from langchain.utilities.dataforseo_api_search import DataForSeoAPIWrapper wrapper = DataForSeoAPIWrapper() result = wrapper.run("Weather in Los Angeles")
De DataForSeoAPIWrapper
verktøyet henter søkemotorresultater fra ulike kilder.
Du kan tilpasse typen resultater og felt som returneres i JSON-svaret. Du kan for eksempel spesifisere resultattypene, feltene og angi et maksimalt antall toppresultater som 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 eksemplet tilpasser JSON-responsen ved å spesifisere resultattyper, felt og begrense antall resultater.
Du kan også spesifisere plassering og språk for søkeresultatene dine ved å sende flere parametere til API-omslaget:
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 å oppgi plasserings- og språkparametere kan du skreddersy søkeresultatene dine til bestemte regioner og språk.
Du har fleksibiliteten til å velge søkemotoren du vil bruke. Bare spesifiser ønsket søkemotor:
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 eksemplet er søket tilpasset for å bruke Bing som søkemotor.
API-innpakningen lar deg også spesifisere typen søk du vil utføre. Du kan for eksempel utføre et kartsøk:
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øket for å hente kartrelatert informasjon.
Shell (bash)
Shell-verktøysettet gir agenter tilgang til skallmiljøet, slik at de kan utføre skallkommandoer. Denne funksjonen er kraftig, men bør brukes med forsiktighet, spesielt i sandkassemiljøer. Slik kan du bruke Shell-verktøyet:
from langchain.tools import ShellTool shell_tool = ShellTool() result = shell_tool.run({"commands": ["echo 'Hello World!'", "time"]})
I dette eksemplet kjører Shell-verktøyet to skallkommandoer: ekko "Hello World!" og viser gjeldende tid.
Du kan gi Shell-verktøyet til en agent for å utføre mer komplekse oppgaver. Her er et eksempel på en agent som henter lenker fra en nettside ved hjelp av Shell-verktøyet:
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 scenariet bruker agenten Shell-verktøyet til å utføre en sekvens med kommandoer for å hente, filtrere og sortere URL-er fra en nettside.
Eksemplene som er gitt demonstrerer noen av verktøyene som er tilgjengelige i LangChain. Disse verktøyene utvider til slutt egenskapene til agenter (utforsket i neste underavsnitt) og gir dem mulighet til å utføre ulike oppgaver effektivt. Avhengig av dine krav, kan du velge verktøyene og verktøysettene som passer best til prosjektets behov og integrere dem i agentens arbeidsflyter.
Tilbake til Agenter
La oss gå videre til agenter nå.
AgentExecutor er kjøretidsmiljøet for en agent. Den er ansvarlig for å ringe agenten, utføre handlingene den velger, sende handlingsutdataene tilbake til agenten og gjenta prosessen til agenten er ferdig. I pseudokode kan AgentExecutor se omtrent slik ut:
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 ulike kompleksiteter, som å håndtere saker der agenten velger et ikke-eksisterende verktøy, håndtere verktøyfeil, administrere agentproduserte utdata og sørge for logging og observerbarhet på alle nivåer.
Mens AgentExecutor-klassen er den primære agentkjøretiden i LangChain, er det andre, mer eksperimentelle kjøretider som støttes, inkludert:
- Planlegg og utfør agent
- Baby AGI
- Auto GPT
For å få en bedre forståelse av agentrammeverket, la oss bygge en grunnleggende agent fra bunnen av, og deretter gå videre til å utforske forhåndsbygde agenter.
Før vi dykker ned i å bygge agenten, er det viktig å se på noen nøkkelterminologier og skjema:
- Agenthandling: Dette er en dataklasse som representerer handlingen en agent bør ta. Den består av en
tool
egenskap (navnet på verktøyet som skal påkalles) og entool_input
egenskap (inndata for det verktøyet). - AgentFinish: Denne dataklassen indikerer at agenten har fullført oppgaven sin og skal returnere et svar til brukeren. Den inkluderer vanligvis en ordbok med returverdier, ofte med en nøkkel "utdata" som inneholder svarteksten.
- Mellomtrinn: Dette er registreringer av tidligere agenthandlinger og tilsvarende utdata. De er avgjørende for å overføre kontekst til fremtidige iterasjoner av agenten.
I vårt eksempel vil vi bruke OpenAI Function Calling for å opprette vår agent. Denne tilnærmingen er pålitelig for oppretting av agenter. Vi starter med å lage et enkelt verktøy som beregner lengden på et ord. Dette verktøyet er nyttig fordi språkmodeller noen ganger kan gjøre feil på grunn av tokenisering når de teller ordlengder.
La oss først laste inn språkmodellen vi skal bruke for å kontrollere agenten:
from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
La oss teste modellen med en ordlengdeberegning:
llm.invoke("how many letters in the word educa?")
Svaret skal angi antall bokstaver i ordet «educa».
Deretter vil vi definere en enkel Python-funksjon for å beregne lengden på 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 laget et verktøy som heter get_word_length
som tar et ord som input og returnerer lengden.
La oss nå lage ledeteksten for agenten. Spørsmålet instruerer agenten om hvordan den skal resonnere og formatere utdataene. I vårt tilfelle bruker vi OpenAI Function Calling, som krever minimale instruksjoner. Vi definerer ledeteksten med plassholdere for brukerinndata og agent-kladdeblokk:
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"), ]
)
Nå, hvordan vet agenten hvilke verktøy den kan bruke? Vi er avhengige av OpenAI-funksjonskallingsspråkmodeller, som krever at funksjoner sendes separat. For å gi verktøyene våre til agenten, formaterer vi dem som OpenAI-funksjonskall:
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])
Nå kan vi opprette agenten ved å definere inndatatilordninger og koble komponentene:
Dette er LCEL-språket. Vi vil diskutere dette i detalj senere.
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 laget vår agent, som forstår brukerinndata, bruker tilgjengelige verktøy og formaterer utdata. La oss nå samhandle med det:
agent.invoke({"input": "how many letters in the word educa?", "intermediate_steps": []})
Agenten skal svare med en AgentAction, som indikerer neste handling som skal utføres.
Vi har opprettet agenten, men nå må vi skrive en kjøretid for den. Den enkleste kjøretiden er en som kontinuerlig kaller agenten, utfører handlinger og gjentar til agenten er ferdig. 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 sløyfen kaller vi agenten gjentatte ganger, utfører handlinger og oppdaterer de mellomliggende trinnene til agenten er ferdig. Vi håndterer også verktøyinteraksjoner innenfor loopen.
For å forenkle denne prosessen, tilbyr LangChain AgentExecutor-klassen, som innkapsler agentutførelse og tilbyr feilhåndtering, tidlig stopp, sporing og andre forbedringer. La oss bruke AgentExecutor til å samhandle 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 utførelsesprosessen og gir en praktisk måte å samhandle med agenten på.
Minne blir også diskutert i detalj senere.
Agenten vi har opprettet så langt er statsløs, noe som betyr at den ikke husker tidligere interaksjoner. For å muliggjøre oppfølgingsspørsmål og samtaler, må vi legge til minne til agenten. Dette innebærer to trinn:
- Legg til en minnevariabel i ledeteksten for å lagre chatteloggen.
- Hold styr på chat-loggen under interaksjoner.
La oss starte med å legge til en minneplassholder i ledeteksten:
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"), ]
)
Opprett nå en liste for å spore chatteloggen:
from langchain.schema.messages import HumanMessage, AIMessage chat_history = []
I trinnet for opprettelse av agent inkluderer vi også minnet:
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()
)
Nå, når du kjører agenten, sørg for å oppdatere chatteloggen:
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 gjør det mulig for agenten å opprettholde en samtalehistorikk og svare på oppfølgingsspørsmål basert på tidligere interaksjoner.
Gratulerer! Du har opprettet og utført din første ende-til-ende-agent i LangChain. For å dykke dypere inn i LangChains evner, kan du utforske:
- Ulike agenttyper støttes.
- Forhåndsbygde agenter
- Hvordan jobbe med verktøy og verktøyintegrasjoner.
Agenttyper
LangChain tilbyr ulike agenttyper, hver egnet for spesifikke brukstilfeller. Her er noen av de tilgjengelige agentene:
- Zero-shot ReAct: Denne agenten bruker ReAct-rammeverket til å velge verktøy basert utelukkende på deres beskrivelser. Det krever beskrivelser for hvert verktøy og er svært allsidig.
- Strukturert input ReAct: Denne agenten håndterer multi-input-verktøy og er egnet for komplekse oppgaver som å navigere i en nettleser. Den bruker et verktøys argumentskjema for strukturert input.
- OpenAI-funksjoner: Denne agenten er spesielt utviklet for modeller som er finjustert for funksjonsanrop, og er kompatibel med modeller som gpt-3.5-turbo-0613 og gpt-4-0613. Vi brukte dette til å lage vår første agent ovenfor.
- Muntlig: Denne agenten er designet for samtaleinnstillinger, og bruker ReAct for verktøyvalg og bruker minne til å huske tidligere interaksjoner.
- Selvspør med søk: Denne agenten er avhengig av et enkelt verktøy, "Mellomsvar", som slår opp faktasvar på spørsmål. Det tilsvarer den originale selvspørringen med søkepapir.
- ReAct dokumentlager: Denne agenten samhandler med et dokumentlager ved hjelp av ReAct-rammeverket. Det krever "Søk" og "Oppslag"-verktøy og ligner på det originale ReAct-avisens Wikipedia-eksempel.
Utforsk disse agenttypene for å finne den som best passer dine behov i LangChain. Disse agentene lar deg binde sett med verktøy i dem for å håndtere handlinger og generere svar. Lær mer om hvordan bygge din egen agent med verktøy her.
Forhåndsbygde agenter
La oss fortsette vår utforskning av agenter, med fokus på forhåndsbygde agenter tilgjengelig i LangChain.
Gmail
LangChain tilbyr et Gmail-verktøysett som lar deg koble LangChain-e-posten din til Gmail API. For å komme i gang må du konfigurere legitimasjonen din, som er forklart i Gmail API-dokumentasjonen. Når du har lastet ned credentials.json
fil, kan du fortsette med å bruke Gmail API. I tillegg må du installere noen nødvendige biblioteker ved å bruke 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 lage Gmail-verktøysettet som følger:
from langchain.agents.agent_toolkits import GmailToolkit toolkit = GmailToolkit()
Du kan også tilpasse autentisering etter dine behov. Bak kulissene opprettes en googleapi-ressurs ved å bruke 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)
Verktøysettet tilbyr ulike verktøy som kan brukes i en agent, inkludert:
GmailCreateDraft
: Lag et e-postutkast med spesifiserte meldingsfelt.GmailSendMessage
: Send e-postmeldinger.GmailSearch
: Søk etter e-postmeldinger eller tråder.GmailGetMessage
: Hent en e-post med meldings-ID.GmailGetThread
: Søk etter e-postmeldinger.
For å bruke disse verktøyene 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 verktøyene kan brukes:
- Lag et Gmail-utkast for 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øk etter den siste e-posten i utkastene dine:
agent.run("Could you search in my drafts for the latest email?")
Disse eksemplene viser egenskapene til LangChains Gmail-verktøysett i en agent, slik at du kan samhandle med Gmail programmatisk.
SQL-databaseagent
Denne delen gir en oversikt over en agent designet for å samhandle med SQL-databaser, spesielt Chinook-databasen. Denne agenten kan svare på generelle spørsmål om en database og gjenopprette fra feil. Vær oppmerksom på at den fortsatt er i aktiv utvikling, og ikke alle svar kan være riktige. Vær forsiktig når du kjører den på sensitive data, da den kan utføre DML-setninger på databasen din.
For å bruke denne agenten kan du initialisere den på følgende måte:
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 agenten kan initialiseres ved hjelp av ZERO_SHOT_REACT_DESCRIPTION
agenttype. Den er laget for å svare på spørsmål og gi beskrivelser. Alternativt kan du initialisere agenten ved å bruke OPENAI_FUNCTIONS
agenttype med OpenAIs GPT-3.5-turbomodell, som vi brukte i vår tidligere klient.
Ansvarsfraskrivelse
- Spørringskjeden kan generere insert/update/slette-spørringer. Vær forsiktig, og bruk en egendefinert ledetekst eller opprett en SQL-bruker uten skrivetillatelser om nødvendig.
- Vær oppmerksom på at å kjøre visse spørringer, for eksempel "kjør den største spørringen" kan overbelaste SQL-databasen din, spesielt hvis den inneholder millioner av rader.
- Datavarehusorienterte databaser støtter ofte kvoter på brukernivå for å begrense ressursbruken.
Du kan be agenten om å beskrive en tabell, for eksempel tabellen "spillelistespor". Her er et eksempel på hvordan du gjør det:
agent_executor.run("Describe the playlisttrack table")
Agenten vil gi informasjon om tabellens skjema og eksempelrader.
Hvis du feilaktig spør om en tabell som ikke eksisterer, kan agenten gjenopprette og gi informasjon om den nærmeste matchende tabellen. For eksempel:
agent_executor.run("Describe the playlistsong table")
Agenten vil finne nærmeste matchende tabell og gi informasjon om den.
Du kan også be agenten om å kjøre spørringer på databasen. For eksempel:
agent_executor.run("List the total sales per country. Which country's customers spent the most?")
Agenten vil utføre spørringen og gi resultatet, for eksempel landet med det høyeste totale salget.
For å få det totale antallet spor i hver spilleliste, kan du bruke følgende spørring:
agent_executor.run("Show the total number of tracks in each playlist. The Playlist name should be included in the result.")
Agenten vil returnere spillelistenavnene sammen med det tilsvarende totale antallet spor.
I tilfeller der agenten støter på feil, kan den gjenopprette og gi nøyaktige svar. For eksempel:
agent_executor.run("Who are the top 3 best selling artists?")
Selv etter å ha støtt på en første feil, vil agenten justere og gi det riktige svaret, som i dette tilfellet er de 3 bestselgende artistene.
Pandas DataFrame Agent
Denne delen introduserer en agent designet for å samhandle med Pandas DataFrames for å svare på spørsmål. Vær oppmerksom på at denne agenten bruker Python-agenten under panseret for å utføre Python-kode generert av en språkmodell (LLM). Vær forsiktig når du bruker denne agenten for å forhindre potensiell skade fra ondsinnet Python-kode generert av 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 be agenten om å telle antall rader i DataFrame:
agent.run("how many rows are there?")
Agenten vil kjøre koden df.shape[0]
og gi svaret, for eksempel "Det er 891 rader i datarammen."
Du kan også be agenten om å filtrere rader basert på spesifikke kriterier, for eksempel å finne antall personer med mer enn 3 søsken:
agent.run("how many people have more than 3 siblings")
Agenten vil kjøre koden df[df['SibSp'] > 3].shape[0]
og gi svaret, for eksempel "30 personer har mer enn 3 søsken."
Hvis du vil beregne kvadratroten av gjennomsnittsalderen, kan du spørre agenten:
agent.run("whats the square root of the average age?")
Agenten vil beregne gjennomsnittsalderen ved hjelp av df['Age'].mean()
og regn deretter ut kvadratroten ved hjelp av math.sqrt()
. Det vil gi svaret, for eksempel "Kvadratroten av gjennomsnittsalderen er 5.449689683556195."
La oss lage en kopi av DataFrame, og manglende aldersverdier fylles ut med gjennomsnittsalderen:
df1 = df.copy()
df1["Age"] = df1["Age"].fillna(df1["Age"].mean())
Deretter kan du initialisere agenten med begge DataFrames og stille den et spørsmå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 alderskolonnene i begge DataFrames og gi svaret, for eksempel "177 rader i alderskolonnen er forskjellige."
Jira Toolkit
Denne delen forklarer hvordan du bruker Jira-verktøysettet, som lar agenter samhandle med en Jira-forekomst. Du kan utføre ulike handlinger som å søke etter problemer og lage problemer ved å bruke dette verktøysettet. Den bruker atlassian-python-api-biblioteket. For å bruke dette verktøysettet må du angi miljøvariabler for Jira-forekomsten, inkludert JIRA_API_TOKEN, JIRA_USERNAME og JIRA_INSTANCE_URL. I tillegg må du kanskje angi OpenAI API-nøkkelen som en miljøvariabel.
For å komme i gang, installer atlassian-python-api-biblioteket og angi de nødvendige miljøvariablene:
%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 til å opprette et nytt problem i et spesifikt prosjekt med en oppsummering og beskrivelse:
agent.run("make a new issue in project PW to remind me to make more fried rice")
Agenten vil utføre de nødvendige handlingene for å opprette problemet og gi et svar, for eksempel "Et nytt problem har blitt opprettet i prosjekt PW med sammendraget 'Lag mer stekt ris' og beskrivelsen 'Påminnelse om å lage mer stekt ris'."
Dette lar deg samhandle med Jira-forekomsten ved å bruke instruksjoner for naturlig språk og Jira-verktøysettet.
Automatiser manuelle oppgaver og arbeidsflyter med vår AI-drevne arbeidsflytbygger, designet av Nanonets for deg og teamene dine.
Modul IV: Kjeder
LangChain er et verktøy designet for å bruke store språkmodeller (LLM) i komplekse applikasjoner. Det gir rammer for å lage kjeder av komponenter, inkludert LLM-er og andre typer komponenter. To primære rammer
- LangChain Expression Language (LCEL)
- Legacy Chain-grensesnitt
LangChain Expression Language (LCEL) er en syntaks som muliggjør intuitiv sammensetning av kjeder. Den støtter avanserte funksjoner som streaming, asynkrone anrop, batching, parallellisering, gjenforsøk, reserver og sporing. For eksempel kan du komponere en ledetekst, modell og utdataparser 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 et alternativ som ligner på LCEL for å 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")
Kjeder i LangChain kan også være stateful ved å inkorporere et minneobjekt. Dette gjør det mulig å holde data på tvers av samtaler, som vist i dette eksemplet:
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 støtter også integrasjon med OpenAIs funksjonskallende APIer, noe som er nyttig for å oppnå strukturerte utdata og utføre funksjoner i en kjede. For å få strukturerte utdata kan du spesifisere dem ved å bruke Pydantic-klasser eller JsonSchema, som illustrert 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 strukturerte utganger er en eldre tilnærming med LLMChain også tilgjengelig:
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 utnytter OpenAI-funksjoner for å lage ulike spesifikke kjeder for ulike formål. Disse inkluderer kjeder for utvinning, tagging, OpenAPI og QA med siteringer.
I forbindelse med utvinning ligner prosessen på den strukturerte produksjonskjeden, men fokuserer på informasjon eller enhetsutvinning. For tagging er ideen å merke et dokument med klasser som følelser, språk, stil, dekkede emner eller politiske tendenser.
Et eksempel på hvordan tagging fungerer i LangChain kan demonstreres med en Python-kode. Prosessen begynner med å installere de nødvendige pakkene og sette opp 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
Skjemaet for tagging er definert, og spesifiserer egenskapene 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å å kjøre merkekjeden med ulike input viser modellens evne til å tolke følelser, språk 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 kontroll kan skjemaet defineres mer spesifikt, inkludert mulige verdier, beskrivelser og nødvendige egenskaper. Et eksempel på denne forbedrede kontrollen er vist nedenfor:
schema = { "properties": { # Schema definitions here }, "required": ["language", "sentiment", "aggressiveness"],
} chain = create_tagging_chain(schema, llm)
Pydantiske skjemaer kan også brukes til å definere merkekriterier, og gir en pytonisk måte å spesifisere nødvendige egenskaper og typer:
from enum import Enum
from pydantic import BaseModel, Field class Tags(BaseModel): # Class fields here chain = create_tagging_chain_pydantic(Tags, llm)
I tillegg kan LangChains metadata-tagger-dokumenttransformator brukes til å trekke ut metadata fra LangChain-dokumenter, og tilbyr lignende funksjonalitet som tagging-kjeden, men brukt på et LangChain-dokument.
Å sitere gjenfinningskilder er en annen funksjon ved LangChain, som bruker OpenAI-funksjoner for å trekke ut sitater fra tekst. Dette er demonstrert 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 kjetting i Large Language Model (LLM)-applikasjoner vanligvis å kombinere en ledetekstmal med en LLM og eventuelt en utdataparser. Den anbefalte måten å gjøre dette på er gjennom LangChain Expression Language (LCEL), selv om den eldre LLMChain-tilnærmingen også støttes.
Ved å bruke LCEL implementerer BasePromptTemplate, BaseLanguageModel og BaseOutputParser alle Runnable-grensesnittet og kan enkelt overføres til hverandre. Her er et eksempel som viser 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'
Ruting i LangChain gjør det mulig å lage ikke-deterministiske kjeder der utdata fra et tidligere trinn bestemmer neste trinn. Dette hjelper til med å strukturere og opprettholde konsistens i interaksjoner med LLM-er. Hvis du for eksempel har to maler optimalisert for ulike typer spørsmål, kan du velge malen basert på brukerinnspill.
Slik kan du oppnå dette ved å bruke LCEL med en RunnableBranch, som er initialisert med en liste over (tilstand, kjørbare) par og en standard kjørbar:
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 kjeden konstrueres deretter ved hjelp av forskjellige komponenter, for eksempel en emneklassifiserer, ledetekstgren og en utdataparser, for å bestemme flyten basert på emnet for inngangen:
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 tilnærmingen eksemplifiserer fleksibiliteten og kraften til LangChain når det gjelder å håndtere komplekse forespørsler og rute dem riktig basert på input.
Innenfor språkmodeller er en vanlig praksis å følge opp en innledende samtale med en rekke påfølgende samtaler, ved å bruke utdata fra en samtale som input for den neste. Denne sekvensielle tilnærmingen er spesielt gunstig når du ønsker å bygge på informasjonen generert i tidligere interaksjoner. Mens LangChain Expression Language (LCEL) er den anbefalte metoden for å lage disse sekvensene, er SequentialChain-metoden fortsatt dokumentert for sin bakoverkompatibilitet.
For å illustrere dette, la oss vurdere et scenario der vi først genererer en skuespillsynopsis og deretter en anmeldelse basert på den synopsen. Bruker Python's langchain.prompts
, lager vi to PromptTemplate
forekomster: en for synopsis og en annen for anmeldelsen. Her er koden for å sette opp disse malene:
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-tilnærmingen lenker vi disse meldingene med ChatOpenAI
og StrOutputParser
å lage en sekvens som først genererer en synopsis og deretter en anmeldelse. Kodebiten 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 trenger både synopsis og gjennomgang, kan vi bruke RunnablePassthrough
for å lage en egen kjede for hver og deretter 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 som involverer mer komplekse sekvenser, SequentialChain
metoden spiller inn. Dette gir mulighet for flere innganger og utganger. Tenk på et tilfelle der vi trenger en synopsis basert på et skuespills tittel og epoke. Slik kan vi sette det opp:
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 der du ønsker å opprettholde kontekst gjennom en kjede eller for en senere del av kjeden, SimpleMemory
kan bli brukt. Dette er spesielt nyttig for å håndtere komplekse input/output-relasjoner. For eksempel, i et scenario der vi ønsker å generere innlegg på sosiale medier basert på et skuespills tittel, epoke, synopsis og anmeldelse, SimpleMemory
kan hjelpe med å administrere disse variablene:
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"})
I tillegg til sekvensielle kjeder finnes det spesialiserte kjeder for arbeid med dokumenter. Hver av disse kjedene tjener et annet formål, fra å kombinere dokumenter til å avgrense svar basert på iterativ dokumentanalyse, til å kartlegge og redusere dokumentinnhold for oppsummering eller omrangering basert på scorede svar. Disse kjedene kan gjenskapes med LCEL for ekstra fleksibilitet og tilpasning.
-
StuffDocumentsChain
kombinerer en liste over dokumenter til en enkelt forespørsel som sendes til en LLM. -
RefineDocumentsChain
oppdaterer svaret sitt iterativt for hvert dokument, egnet for oppgaver der dokumenter overskrider modellens kontekstkapasitet. -
MapReduceDocumentsChain
bruker en kjede på hvert dokument individuelt og kombinerer deretter resultatene. -
MapRerankDocumentsChain
scorer hvert dokumentbasert svar og velger den med høyest poengsum.
Her er et eksempel på hvordan du kan sette opp en MapReduceDocumentsChain
bruker 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 konfigurasjonen gir mulighet for en detaljert og omfattende analyse av dokumentinnhold, og utnytter styrken til LCEL og den underliggende språkmodellen.
Automatiser manuelle oppgaver og arbeidsflyter med vår AI-drevne arbeidsflytbygger, designet av Nanonets for deg og teamene dine.
Modul V : Minne
I LangChain er minne et grunnleggende aspekt ved samtalegrensesnitt, som lar systemer referere tidligere interaksjoner. Dette oppnås gjennom å lagre og spørre etter informasjon, med to primære handlinger: lesing og skriving. Minnesystemet samhandler med en kjede to ganger under en kjøring, forsterker brukerinndata og lagrer inngangene og utgangene for fremtidig referanse.
Bygg minne inn i et system
- Lagring av chatmeldinger: LangChain-minnemodulen integrerer ulike metoder for å lagre chat-meldinger, alt fra minnelister til databaser. Dette sikrer at alle chat-interaksjoner blir registrert for fremtidig referanse.
- Spørre Chat-meldinger: Utover å lagre chat-meldinger, bruker LangChain datastrukturer og algoritmer for å lage en nyttig oversikt over disse meldingene. Enkle minnesystemer kan returnere nylige meldinger, mens mer avanserte systemer kan oppsummere tidligere interaksjoner eller fokusere på enheter nevnt i den nåværende interaksjonen.
For å demonstrere bruken av minne i LangChain, vurder ConversationBufferMemory
klasse, et enkelt minneskjema som lagrer chat-meldinger 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 minne i en kjede, er det avgjørende å forstå variablene som returneres fra minnet og hvordan de brukes i kjeden. For eksempel load_memory_variables
metoden hjelper til med å justere variablene som leses fra minnet med kjedens forventninger.
End-to-end eksempel med LangChain
Vurder å bruke ConversationBufferMemory
i en LLMChain
. Kjeden, kombinert med en passende spørremal og minnet, gir en sømløs samtaleopplevelse. 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 eksemplet illustrerer hvordan LangChains minnesystem integreres med sine kjeder for å gi en sammenhengende og kontekstuelt bevisst samtaleopplevelse.
Minnetyper i Langchain
Langchain tilbyr ulike minnetyper som kan brukes til å forbedre interaksjoner med AI-modellene. Hver minnetype har sine egne parametere og returtyper, noe som gjør dem egnet for forskjellige scenarier. La oss utforske noen av minnetypene som er tilgjengelige i Langchain sammen med kodeeksempler.
1. Samtalebufferminne
Denne minnetypen lar deg lagre og trekke ut meldinger fra samtaler. Du kan trekke ut loggen som en streng eller som en liste over meldinger.
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å bruke samtalebufferminne i en kjede for chat-lignende interaksjoner.
2. Minne for samtalebuffervindu
Denne minnetypen holder en liste over nylige interaksjoner og bruker de siste K-interaksjonene, og forhindrer at bufferen blir 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'}
I likhet med samtalebufferminne kan du også bruke denne minnetypen i en kjede for chat-lignende interaksjoner.
3. Minne for samtaleenhet
Denne minnetypen husker fakta om spesifikke enheter i en samtale og trekker ut informasjon ved hjelp av 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. Samtalekunnskapsgrafminne
Denne minnetypen bruker en kunnskapsgraf for å gjenskape minne. Du kan trekke ut gjeldende enheter og kunnskapstrillinger fra meldinger.
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å bruke denne minnetypen i en kjede for samtalebasert kunnskapsinnhenting.
5. Samtaleoppsummeringsminne
Denne minnetypen lager et sammendrag av samtalen over tid, nyttig for å kondensere informasjon fra lengre 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. Samtalesammendrag Bufferminne
Denne minnetypen kombinerer samtalesammendraget og bufferen, og opprettholder en balanse mellom nylige interaksjoner og et sammendrag. Den bruker tokenlengde for å bestemme når interaksjoner 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 bruke disse minnetypene til å forbedre interaksjonene dine med AI-modeller i Langchain. Hver minnetype tjener et bestemt formål og kan velges basert på dine behov.
7. Samtaletokenbufferminne
ConversationTokenBufferMemory er en annen minnetype som holder en buffer av nylige interaksjoner i minnet. I motsetning til de tidligere minnetypene som fokuserer på antall interaksjoner, bruker denne tokenlengde for å bestemme når interaksjoner skal tømmes.
Bruk av minne 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 eksemplet er minnet satt til å begrense interaksjoner basert på tokenlengde i stedet for antall interaksjoner.
Du kan også få historikken som en liste over meldinger når du bruker denne minnetypen.
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"})
Bruk i en kjede:
Du kan bruke ConversationTokenBufferMemory i en kjede for å forbedre interaksjoner 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 eksemplet brukes ConversationTokenBufferMemory i en ConversationChain for å administrere samtalen og begrense interaksjoner basert på tokenlengde.
8. VectorStoreRetrieverMemory
VectorStoreRetrieverMemory lagrer minner i et vektorlager og spør etter de øverste K mest "fremtredende" dokumentene hver gang det kalles. Denne minnetypen sporer ikke eksplisitt rekkefølgen av interaksjoner, men bruker vektorhenting for å hente relevante minner.
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 eksemplet brukes VectorStoreRetrieverMemory til å lagre og hente relevant informasjon fra en samtale basert på vektorhenting.
Du kan også bruke VectorStoreRetrieverMemory i en kjede for samtalebasert kunnskapshenting, som vist i de foregående eksemplene.
Disse forskjellige minnetypene i Langchain gir forskjellige måter å administrere og hente informasjon fra samtaler på, og forbedrer AI-modellenes evne til å forstå og svare på brukerforespørsler og kontekst. Hver minnetype kan velges basert på de spesifikke kravene til applikasjonen din.
Nå skal vi lære hvordan du bruker minne med en LLMChain. Minne i en LLMChain lar modellen huske tidligere interaksjoner og kontekst for å gi mer sammenhengende og kontekstbevisste svar.
For å sette opp minne i en LLMChain, må du opprette en minneklasse, for eksempel ConversationBufferMemory. Slik 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 eksemplet brukes ConversationBufferMemory til å lagre samtalehistorikken. De memory_key
parameter spesifiserer nøkkelen som brukes til å lagre samtaleloggen.
Hvis du bruker en chat-modell i stedet for en fullføringsmodell, kan du strukturere forespørslene dine annerledes for å utnytte minnet bedre. Her er et eksempel på hvordan du setter opp en chat-modellbasert LLMChain med minne:
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 eksemplet brukes ChatPromptTemplate til å strukturere ledeteksten, og ConversationBufferMemory brukes til å lagre og hente samtalehistorikken. Denne tilnærmingen er spesielt nyttig for samtaler i chat-stil der kontekst og historie spiller en avgjørende rolle.
Minne kan også legges til en kjede med flere innganger, for eksempel en spørsmål-/svarkjede. Her er et eksempel på hvordan du setter opp minne i en spørsmål-/svarkjede:
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 eksemplet besvares et spørsmål ved å bruke et dokument som er delt opp i mindre biter. ConversationBufferMemory brukes til å lagre og hente samtalehistorikken, slik at modellen kan gi kontekstbevisste svar.
Ved å legge til minne til en agent kan den huske og bruke tidligere interaksjoner for å svare på spørsmål og gi kontekstbevisste svar. Slik kan du sette opp minne 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 eksemplet legges minne til en agent, slik at den kan huske forrige samtalehistorikk og gi kontekstbevisste svar. Dette gjør at agenten kan svare nøyaktig på oppfølgingsspørsmål basert på informasjonen som er lagret i minnet.
LangChain Expression Language
I en verden av naturlig språkbehandling og maskinlæring kan det være en skremmende oppgave å komponere komplekse operasjonskjeder. Heldigvis kommer LangChain Expression Language (LCEL) til unnsetning, og gir en deklarativ og effektiv måte å bygge og distribuere sofistikerte språkbehandlingspipelines. LCEL er designet for å forenkle prosessen med å komponere kjeder, noe som gjør det mulig å gå fra prototyping til produksjon med letthet. I denne bloggen vil vi utforske hva LCEL er og hvorfor du kanskje vil bruke det, sammen med praktiske kodeeksempler for å illustrere funksjonene.
LCEL, eller LangChain Expression Language, er et kraftig verktøy for å komponere språkbehandlingskjeder. Den var spesialbygd for å støtte overgangen fra prototyping til produksjon sømløst, uten å kreve omfattende kodeendringer. Enten du bygger en enkel "prompt + LLM"-kjede eller en kompleks pipeline med hundrevis av trinn, har LCEL deg dekket.
Her er noen grunner til å bruke LCEL i språkbehandlingsprosjektene dine:
- Rask Token Streaming: LCEL leverer tokens fra en språkmodell til en utdataparser i sanntid, noe som forbedrer respons og effektivitet.
- Allsidige APIer: LCEL støtter både synkrone og asynkrone APIer for prototyping og produksjonsbruk, og håndterer flere forespørsler effektivt.
- Automatisk parallellisering: LCEL optimerer parallell kjøring når det er mulig, og reduserer ventetiden i både synkroniserings- og asynkroniseringsgrensesnitt.
- Pålitelige konfigurasjoner: Konfigurer gjenforsøk og fallbacks for forbedret kjedepålitelighet i stor skala, med strømmestøtte under utvikling.
- Strøm mellomresultater: Få tilgang til mellomresultater under behandling for brukeroppdateringer eller feilsøkingsformål.
- Schema Generation: LCEL genererer Pydantic og JSONSchema skjemaer for input og output validering.
- Omfattende sporing: LangSmith sporer automatisk alle trinn i komplekse kjeder for observerbarhet og feilsøking.
- Enkel distribusjon: Distribuer LCEL-skapte kjeder uten problemer ved hjelp av LangServe.
La oss nå dykke ned i praktiske kodeeksempler som demonstrerer kraften til LCEL. Vi vil utforske vanlige oppgaver og scenarier der LCEL skinner.
Spørre + LLM
Den mest grunnleggende sammensetningen innebærer å kombinere en ledetekst og en språkmodell for å lage en kjede som tar brukerinndata, legger den til en ledetekst, sender den til en modell og returnerer råmodellutdata. 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 eksemplet genererer kjeden en vits om bjørn.
Du kan legge ved stoppsekvenser til kjeden din for å kontrollere hvordan den behandler tekst. For eksempel:
chain = prompt | model.bind(stop=["n"])
result = chain.invoke({"foo": "bears"})
print(result)
Denne konfigurasjonen stopper tekstgenerering når et linjeskifttegn oppstår.
LCEL støtter å legge til funksjonsanropsinformasjon til kjeden din. 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 eksemplet legger ved funksjonsanropsinformasjon for å generere en vits.
Spørre + LLM + OutputParser
Du kan legge til en utdataparser for å transformere råmodellutdataene til et mer brukbart format. Slik kan du gjøre det:
from langchain.schema.output_parser import StrOutputParser chain = prompt | model | StrOutputParser()
result = chain.invoke({"foo": "bears"})
print(result)
Utdataene er nå i et strengformat, som er mer praktisk for nedstrømsoppgaver.
Når du spesifiserer en funksjon som skal returneres, kan du analysere den direkte ved å bruke 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 eksemplet analyserer utdataene fra "vits"-funksjonen direkte.
Dette er bare noen få eksempler på hvordan LCEL forenkler komplekse språkbehandlingsoppgaver. Enten du bygger chatboter, genererer innhold eller utfører komplekse teksttransformasjoner, kan LCEL strømlinjeforme arbeidsflyten din og gjøre koden mer vedlikeholdbar.
RAG (Retrieval-augmented Generation)
LCEL kan brukes til å lage gjenfinningsforsterkede generasjonskjeder, som kombinerer gjenfinnings- og språkgenereringstrinn. 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 eksemplet henter kjeden relevant informasjon fra konteksten og genererer et svar på spørsmålet.
Samtalehentingskjede
Du kan enkelt legge til samtalehistorikk til kjedene dine. Her er et eksempel på en samtaleinnhentingskjede:
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 eksemplet håndterer kjeden et oppfølgingsspørsmål innenfor en samtalekontekst.
Med minne og returnerende kildedokumenter
LCEL støtter også minne og returnerende kildedokumenter. Slik kan du bruke minne i en kjede:
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 eksemplet brukes minnet til å lagre og hente samtalehistorikk og kildedokumenter.
Flere kjeder
Du kan sette sammen flere kjeder ved å bruke 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 eksemplet kombineres to kjeder for å generere informasjon om en by og dens land på et spesifisert språk.
Forgrening og sammenslåing
LCEL lar deg dele og slå sammen kjeder ved hjelp av RunnableMaps. Her er et eksempel på forgrening og sammenslåing:
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 eksemplet brukes en forgrenings- og sammenslåingskjede til å generere et argument og evaluere fordeler og ulemper før det genereres et endelig svar.
Skrive Python-kode med LCEL
En av de kraftige applikasjonene til LangChain Expression Language (LCEL) er å skrive Python-kode for å løse brukerproblemer. Nedenfor er et eksempel på hvordan du bruker LCEL til å 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 eksemplet gir en bruker input, og LCEL genererer Python-kode for å løse problemet. Koden utføres deretter ved hjelp av en Python REPL, og den resulterende Python-koden returneres i Markdown-format.
Vær oppmerksom på at bruk av en Python REPL kan kjøre vilkårlig kode, så bruk den med forsiktighet.
Legge til minne i en kjede
Minne er essensielt i mange samtale-AI-applikasjoner. Slik legger du til minne i en vilkårlig kjede:
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 eksemplet brukes minne til å lagre og hente samtalehistorikk, slik at chatboten kan opprettholde kontekst og svare på riktig måte.
Bruke eksterne verktøy med kjørbare filer
LCEL lar deg sømløst integrere eksterne verktøy med Runnables. Her er et eksempel ved å bruke DuckDuckGo-søkeverktøyet:
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 eksemplet integrerer LCEL DuckDuckGo Search-verktøyet i kjeden, slik at det kan generere et søk fra brukerinndata og hente søkeresultater.
LCELs fleksibilitet gjør det enkelt å inkorporere ulike eksterne verktøy og tjenester i språkbehandlingspipelines, noe som forbedrer deres muligheter og funksjonalitet.
Legge til moderering til en LLM-applikasjon
For å sikre at LLM-applikasjonen din overholder innholdsretningslinjene og inkluderer moderasjonssikring, kan du integrere moderasjonssjekker i kjeden din. Slik legger du til moderering ved å bruke 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 eksemplet er OpenAIModerationChain
brukes til å legge moderasjon til responsen generert av LLM. Modereringskjeden sjekker responsen for innhold som bryter OpenAIs innholdspolicy. Hvis noen brudd blir funnet, vil den flagge svaret tilsvarende.
Ruting etter semantisk likhet
LCEL lar deg implementere tilpasset rutinglogikk basert på den semantiske likheten til brukerinndata. Her er et eksempel på hvordan du dynamisk bestemmer kjedelogikken basert på brukerinndata:
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 eksemplet er prompt_router
funksjonen beregner cosinuslikheten mellom brukerinndata og forhåndsdefinerte ledetekstmaler for fysikk- og matematikkspørsmål. Basert på likhetspoengsummen velger kjeden dynamisk den mest relevante spørsmålsmalen, og sikrer at chatboten svarer riktig på brukerens spørsmål.
Bruke Agenter og Runnables
LangChain lar deg lage agenter ved å kombinere Runnables, ledetekster, modeller og verktøy. Her er et eksempel på å bygge en agent og bruke 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 eksemplet opprettes en agent ved å kombinere en modell, verktøy, en ledetekst og en tilpasset logikk for mellomtrinn og verktøykonvertering. Agenten blir deretter utført, og gir et svar på brukerens forespørsel.
Spørre en SQL-database
Du kan bruke LangChain til å spørre en SQL-database og generere SQL-spørringer basert på brukerspørsmå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 eksemplet brukes LangChain til å generere SQL-spørringer basert på brukerspørsmål og hente svar fra en SQL-database. Spørsmålene og svarene er formatert for å gi naturlig språkinteraksjon med databasen.
Automatiser manuelle oppgaver og arbeidsflyter med vår AI-drevne arbeidsflytbygger, designet av Nanonets for deg og teamene dine.
LangServe & LangSmith
LangServe hjelper utviklere med å distribuere LangChain runnables og kjeder som et REST API. Dette biblioteket er integrert med FastAPI og bruker pydantic for datavalidering. I tillegg gir den en klient som kan brukes til å kalle inn runnables distribuert på en server, og en JavaScript-klient er tilgjengelig i LangChainJS.
Egenskaper
- Inndata- og utdataskjemaer utledes automatisk fra LangChain-objektet ditt og håndheves på hvert API-kall, med rike feilmeldinger.
- En API-dokumentside med JSONSchema og Swagger er tilgjengelig.
- Effektive endepunkter /invoke, /batch og /stream med støtte for mange samtidige forespørsler på en enkelt server.
- /stream_log endepunkt for strømming av alle (eller noen) mellomtrinn fra kjeden/agenten din.
- Lekeplass-side på /lekeplass med streaming-utgang og mellomtrinn.
- Innebygd (valgfritt) sporing til LangSmith; bare legg til API-nøkkelen din (se instruksjoner).
- Alt bygget med kamptestede Python-biblioteker med åpen kildekode som FastAPI, Pydantic, uvloop og asyncio.
Begrensninger
- Tilbakeringing av klienter støttes ennå ikke for hendelser som kommer fra serveren.
- OpenAPI-dokumenter vil ikke bli generert når du bruker Pydantic V2. FastAPI støtter ikke blanding av pydantic v1 og v2 navnerom. Se avsnittet nedenfor for mer informasjon.
Bruk LangChain CLI til å starte opp et LangServe-prosjekt raskt. For å bruke langchain CLI, sørg for at du har en nyere versjon av langchain-cli installert. Du kan installere den med pip install -U langchain-cli.
langchain app new ../path/to/directory
Kom raskt i gang med LangServe-forekomsten med LangChain-maler. For flere eksempler, se malindeksen eller eksempelkatalogen.
Her er en server som distribuerer en OpenAI chat-modell, en antropisk chat-modell og en kjede som bruker den antropiske modellen til å fortelle en vits 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 distribuert serveren ovenfor, kan du se de genererte OpenAPI-dokumentene ved å bruke:
curl localhost:8000/docs
Sørg for å legge til /docs-suffikset.
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 (krever LangChain.js versjon 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 bruker forespørsler:
import requests
response = requests.post( "http://localhost:8000/chain/invoke/", json={'input': {'topic': 'cats'}}
)
response.json()
Du kan også bruke krøll:
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",
)
legger til disse endepunktene til serveren:
- POST /my_runnable/invoke – påkall den kjørbare på en enkelt inngang
- POST /my_runnable/batch – påkall den kjørbare på en batch av innganger
- POST /my_runnable/stream – start på en enkelt inngang og strøm utdataene
- POST /my_runnable/stream_log – kall på en enkelt inngang og strøm utdataene, inkludert utdata av mellomtrinn etter hvert som det genereres
- GET /my_runnable/input_schema – json-skjema for input til det kjørbare
- GET /my_runnable/output_schema – json-skjema for utdata av det kjørbare
- GET /my_runnable/config_schema – json-skjema for konfigurasjon av det kjørbare
Du kan finne en lekeplassside for din runnable på /my_runnable/playground. Dette avslører et enkelt brukergrensesnitt for å konfigurere og påkalle kjøringen din med strømmeutgang og mellomtrinn.
For både klient og server:
pip install "langserve[all]"
eller pip install "langserve[client]" for klientkode, og pip install "langserve[server]" for serverkode.
Hvis du trenger å legge til autentisering til serveren din, vennligst referer til FastAPIs sikkerhetsdokumentasjon og mellomvaredokumentasjon.
Du kan distribuere til GCP Cloud Run ved å bruke 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 gir støtte for Pydantic 2 med noen begrensninger. OpenAPI-dokumenter vil ikke bli generert for invoke/batch/stream/stream_log når du bruker Pydantic V2. Fast API støtter ikke blanding av pydantic v1 og v2 navneområder. LangChain bruker v1-navneområdet i Pydantic v2. Vennligst les følgende retningslinjer for å sikre kompatibilitet med LangChain. Bortsett fra disse begrensningene forventer vi at API-endepunktene, lekeplassen og alle andre funksjoner fungerer som forventet.
LLM-applikasjoner omhandler ofte filer. Det er forskjellige arkitekturer som kan lages for å implementere filbehandling; på høyt nivå:
- Filen kan lastes opp til serveren via et dedikert endepunkt og behandles ved hjelp av et eget endepunkt.
- Filen kan lastes opp med enten verdi (filbyte) eller referanse (f.eks. s3 url til filinnhold).
- Behandlingsendepunktet kan være blokkerende eller ikke-blokkerende.
- Hvis det kreves betydelig behandling, kan behandlingen overføres til en dedikert prosesspool.
Du bør finne ut hva som er riktig arkitektur for applikasjonen din. For øyeblikket, for å laste opp filer etter verdi til en kjørbar, bruk base64-koding for filen (multipart/form-data støttes ikke ennå).
Her er en eksempel som viser hvordan du bruker base64-koding for å sende en fil til en ekstern kjørbar. Husk at du alltid kan laste opp filer ved referanse (f.eks. s3 url) eller laste dem opp som flerdelte/skjemadata til et dedikert endepunkt.
Input- og Output-typer er definert på alle kjørbare enheter. Du kan få tilgang til dem via egenskapene input_schema og output_schema. LangServe bruker disse typene for validering og dokumentasjon. Hvis du vil overstyre standard utledede typer, kan du bruke with_types-metoden.
Her er et lekeeksempel for å 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 vil at dataene skal deserialiseres til en pydantisk modell i stedet for den tilsvarende dikt-representasjonen. For øyeblikket fungerer denne typen kun på serversiden og brukes til å spesifisere ønsket dekodingsatferd. Hvis den arver fra denne typen, vil serveren beholde den dekodede typen som en pydantisk modell i stedet for å 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")
Lekeplassen lar deg definere egendefinerte widgets for din kjørbare fra backend. En widget spesifiseres på feltnivå og sendes som en del av JSON-skjemaet for inndatatypen. En widget må inneholde en nøkkel kalt type med verdien som en av en velkjent liste over widgets. Andre widget-nøkler vil bli assosiert med verdier som beskriver stier i et JSON-objekt.
Generelt skjema:
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;
};
Tillater opprettelse av en filopplastingsinngang i brukergrensesnittets lekeplass for filer som lastes opp som base64-kodede strenger. Her er hele eksemplet.
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 oppgaver og arbeidsflyter med vår AI-drevne arbeidsflytbygger, designet av Nanonets for deg og teamene dine.
Introduksjon til LangSmith
LangChain gjør det enkelt å prototype LLM-applikasjoner og agenter. Imidlertid kan det være villedende vanskelig å levere LLM-applikasjoner til produksjon. Du vil sannsynligvis måtte tilpasse og gjenta forespørsler, kjeder og andre komponenter for å lage et produkt av høy kvalitet.
For å hjelpe i denne prosessen ble LangSmith introdusert, en enhetlig plattform for feilsøking, testing og overvåking av LLM-applikasjonene dine.
Når kan dette komme til nytte? Du kan finne det nyttig når du raskt vil feilsøke en ny kjede, agent eller sett med verktøy, visualisere hvordan komponenter (kjeder, llms, retrievere, etc.) relaterer seg og brukes, evaluere forskjellige spørsmål og LLM-er for en enkelt komponent, kjøre en gitt kjede flere ganger over et datasett for å sikre at det konsekvent oppfyller en kvalitetslinje, eller fange opp bruksspor og bruk LLM-er eller analytiske pipelines for å generere innsikt.
Forutsetninger:
- Opprett en LangSmith-konto og lag en API-nøkkel (se nederst i venstre hjørne).
- Gjør deg kjent med plattformen ved å se gjennom dokumentene.
La oss komme i gang!
Konfigurer først miljøvariablene dine for å fortelle LangChain å logge spor. Dette gjøres ved å sette miljøvariabelen LANGCHAIN_TRACING_V2 til sann. Du kan fortelle LangChain hvilket prosjekt du skal logge på ved å angi miljøvariabelen LANGCHAIN_PROJECT (hvis dette ikke er satt, vil kjøringer logges til standardprosjektet). Dette vil automatisk opprette prosjektet for deg hvis det ikke eksisterer. Du må også angi miljøvariablene LANGCHAIN_ENDPOINT og LANGCHAIN_API_KEY.
MERK: Du kan også bruke en kontekstbehandling i python for å logge spor ved å bruke:
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?")
I dette eksemplet vil vi imidlertid bruke 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>"
Opprett LangSmith-klienten for å samhandle med APIen:
from langsmith import Client client = Client()
Lag en LangChain-komponent og logg kjøringer til plattformen. I dette eksemplet vil vi lage en ReAct-aktig agent med tilgang til et generelt søkeverktøy (DuckDuckGo). Agentens forespørsel kan sees 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 kjører agenten samtidig på flere innganger for å redusere ventetiden. Kjøringer blir logget til LangSmith i bakgrunnen, så kjøreforsinkelsen påvirkes ikke:
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]
Forutsatt at du har konfigurert miljøet ditt, bør agentsporene dine vises i Prosjekter-delen i appen. Gratulerer!
Det ser ut til at agenten ikke bruker verktøyene effektivt. La oss evaluere dette slik at vi har en grunnlinje.
I tillegg til loggkjøringer lar LangSmith deg også teste og evaluere LLM-applikasjonene dine.
I denne delen vil du utnytte LangSmith til å lage et benchmark-datasett og kjøre AI-assisterte evaluatorer på en agent. Du vil gjøre det i noen få trinn:
- Lag et LangSmith-datasett:
Nedenfor bruker vi LangSmith-klienten til å lage et datasett fra inndataspørsmålene ovenfra og en listeetiketter. Du vil bruke disse senere til å måle ytelsen for en ny agent. Et datasett er en samling eksempler, som ikke er noe annet enn input-output-par du kan bruke som testcaser til applikasjonen din:
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 å benchmarke:
LangSmith lar deg evaluere enhver LLM, kjede, agent eller til og med en tilpasset funksjon. Samtaleagenter er statelige (de har hukommelse); for å sikre at denne tilstanden ikke deles mellom datasettkjøringer, sender vi i en chain_factory (
aka en konstruktør) funksjon for å initialisere for hvert kall:
# 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:
Manuell sammenligning av resultatene til kjeder i brukergrensesnittet er effektivt, men det kan være tidkrevende. Det kan være nyttig å bruke automatiserte beregninger og AI-assistert tilbakemelding for å evaluere komponentens ytelse:
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=[],
)
- Kjør agenten og evaluatorene:
Bruk funksjonen run_on_dataset (eller asynkron arun_on_dataset) for å evaluere modellen din. Dette vil:
- Hent eksempelrader fra det angitte datasettet.
- Kjør agenten din (eller en hvilken som helst egendefinert funksjon) på hvert eksempel.
- Bruk evaluatorer på de resulterende kjøresporene og tilsvarende referanseeksempler for å generere automatisert tilbakemelding.
Resultatene 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", ],
)
Nå som vi har testresultatene våre, kan vi gjøre endringer i agenten vår og måle dem. La oss prøve dette igjen med en annen melding og se resultatene:
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 lar deg eksportere data til vanlige formater som CSV eller JSONL direkte i nettappen. Du kan også bruke klienten til å hente kjøringer for videre analyse, til å lagre i din egen database eller til å dele med andre. La oss hente kjøresporene fra evalueringskjøringen:
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 rask veiledning for å komme i gang, men det er mange flere måter å bruke LangSmith for å øke hastigheten på utviklerflyten og gi bedre resultater.
For mer informasjon om hvordan du kan få mest mulig ut av LangSmith, sjekk ut LangSmith-dokumentasjonen.
Opp på nivå med nanonetter
Selv om LangChain er et verdifullt verktøy for å integrere språkmodeller (LLM) med applikasjonene dine, kan det møte begrensninger når det gjelder bedriftsbruk. La oss utforske hvordan Nanonets går utover LangChain for å møte disse utfordringene:
1. Omfattende datatilkobling:
LangChain tilbyr koblinger, men den dekker kanskje ikke alle arbeidsområdeappene og dataformatene som bedrifter er avhengige av. Nanonets tilbyr datatilkoblinger for over 100 mye brukte arbeidsromapper, inkludert Slack, Notion, Google Suite, Salesforce, Zendesk og mange flere. Den støtter også alle ustrukturerte datatyper som PDF-er, TXT-er, bilder, lydfiler og videofiler, samt strukturerte datatyper som CSV-er, regneark, MongoDB og SQL-databaser.
2. Oppgaveautomatisering for Workspace-apper:
Mens generering av tekst/svar fungerer utmerket, er LangChains muligheter begrenset når det gjelder å bruke naturlig språk for å utføre oppgaver i ulike applikasjoner. Nanonets tilbyr trigger-/handlingsagenter for de mest populære arbeidsområdeappene, slik at du kan sette opp arbeidsflyter som lytter etter hendelser og utfører handlinger. Du kan for eksempel automatisere e-postsvar, CRM-oppføringer, SQL-spørringer og mer, alt gjennom naturlige språkkommandoer.
3. Sanntidsdatasynkronisering:
LangChain henter statiske data med datakoblinger, som kanskje ikke holder tritt med dataendringer i kildedatabasen. Derimot sikrer Nanonets sanntidssynkronisering med datakilder, og sikrer at du alltid jobber med den nyeste informasjonen.
3. Forenklet konfigurasjon:
Konfigurering av elementene i LangChain-pipelinen, som retrievere og synthesizere, kan være en kompleks og tidkrevende prosess. Nanonets effektiviserer dette ved å tilby optimalisert datainntak og indeksering for hver datatype, alt håndtert i bakgrunnen av AI-assistenten. Dette reduserer byrden med finjustering og gjør det enklere å sette opp og bruke.
4. Samlet løsning:
I motsetning til LangChain, som kan kreve unike implementeringer for hver oppgave, fungerer Nanonets som en one-stop-løsning for å koble dataene dine med LLM-er. Enten du trenger å lage LLM-applikasjoner eller AI-arbeidsflyter, tilbyr Nanonets en enhetlig plattform for dine forskjellige behov.
Nanonets AI arbeidsflyter
Nanonets Workflows er en sikker, flerbruks AI-assistent som forenkler integreringen av kunnskapen og dataene dine med LLM-er og forenkler opprettelsen av kodefrie applikasjoner og arbeidsflyter. Den tilbyr et brukervennlig brukergrensesnitt, som gjør det tilgjengelig for både enkeltpersoner og organisasjoner.
For å komme i gang kan du avtale en samtale med en av våre AI-eksperter, som kan tilby en personlig demo og prøveversjon av Nanonets Workflows skreddersydd for din spesifikke brukssituasjon.
Når den er konfigurert, kan du bruke naturlig språk til å designe og utføre komplekse applikasjoner og arbeidsflyter drevet av LLM-er, og integreres sømløst med appene og dataene dine.
Overlad teamene dine med Nanonets AI for å lage apper og integrere dataene dine med AI-drevne applikasjoner og arbeidsflyter, slik at teamene dine kan fokusere på det som virkelig betyr noe.
Automatiser manuelle oppgaver og arbeidsflyter med vår AI-drevne arbeidsflytbygger, designet av Nanonets for deg og teamene dine.
- SEO-drevet innhold og PR-distribusjon. Bli forsterket i dag.
- PlatoData.Network Vertical Generative Ai. Styrk deg selv. Tilgang her.
- PlatoAiStream. Web3 Intelligence. Kunnskap forsterket. Tilgang her.
- PlatoESG. Karbon, CleanTech, Energi, Miljø, Solenergi, Avfallshåndtering. Tilgang her.
- PlatoHelse. Bioteknologisk og klinisk etterretning. Tilgang her.
- kilde: https://nanonets.com/blog/langchain/
- : har
- :er
- :ikke
- :hvor
- $OPP
- 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 oss
- om det
- ovenfor
- Aksepterer
- godtar
- adgang
- tilgjengelig
- Tilgang
- utrette
- tilsvar
- Logg inn
- nøyaktighet
- nøyaktig
- nøyaktig
- Oppnå
- oppnådd
- oppnår
- tvers
- Handling
- Handling
- handlinger
- aktiv
- tilpasse
- adaptive
- legge til
- la til
- legge
- tillegg
- Ytterligere
- I tillegg
- adresse
- Legger
- innrømme
- avansert
- eventyr
- Etter
- en gang til
- alder
- Agent
- agenter
- AI
- AI-assistent
- AI-modeller
- Aid
- Sikter
- algoritmer
- justere
- Justerer
- Alle
- tillate
- tillate
- tillater
- alene
- langs
- sammen
- allerede
- også
- Selv
- alltid
- an
- analyse
- Analytisk
- analytics
- og
- Angeles
- Kunngjøre
- årlig
- En annen
- besvare
- svar
- anthem
- Antropisk
- noen
- hva som helst
- api
- API NØKLER
- APIer
- app
- aktuelt
- Søknad
- Applikasjonutvikling
- søknader
- anvendt
- gjelder
- tilnærming
- tilnærminger
- hensiktsmessig
- hensiktsmessig
- apps
- arkitektur
- ER
- argument
- argumenter
- Armstrong
- rundt
- Array
- Artister
- AS
- spør
- aspektet
- aspekter
- bistå
- Assistent
- assosiert
- At
- feste
- oppmerksomhet
- lyd
- augmented
- Autentisering
- automatisere
- Automatisert
- automatiserer
- automatisk
- Automatisering
- tilgjengelig
- gjennomsnittlig
- avvente
- klar
- AWS
- tilbake
- Backbone
- Backend
- bakgrunn
- dårlig
- Balansere
- Bar
- basen
- basert
- Baseline
- bash
- grunnleggende
- Grunnleggende
- BCG
- BE
- Strand
- Bears
- fordi
- vært
- før du
- begynne
- atferd
- bak
- Bak scenen
- være
- under
- benchmark
- gunstig
- BEST
- Bedre
- mellom
- Beyond
- Biggest
- Bill
- Bill Gates
- binde
- Bing
- Bit
- Svart
- Black Hole
- Blokker
- blokkering
- Blocks
- Blogg
- bob
- Bootstrap
- født
- Bot
- både
- Bunn
- Branch
- Break
- sus
- kort
- bredere
- brun
- nett~~POS=TRUNC leseren~~POS=HEADCOMP
- buffer
- bygge
- bygger
- Bygning
- bygget
- byrde
- bedrifter
- men
- by
- beregne
- beregner
- beregning
- beregningen
- ring
- tilbakeringinger
- som heter
- ringer
- Samtaler
- CAN
- Kan få
- Canada
- evner
- stand
- Kapasitet
- fangst
- fange
- saken
- saker
- CAT
- imøtekomme
- catering
- henvender seg
- Katter
- forsiktighet
- forsiktige
- sentrert
- viss
- kjede
- kjeder
- utfordringer
- Endringer
- karakter
- chatbot
- chatbots
- sjekk
- Sjekker
- Velg
- valgt ut
- omstendigheter
- City
- klasse
- klasser
- kunde
- Cloud
- kode
- Koding
- Kaffe
- SAMMENHENGENDE
- sammenhengende
- samarbeide
- Kollapse
- samling
- fargerikt
- Kolonne
- kolonner
- COM
- kombinere
- kombinert
- skurtreskerne
- kombinere
- Kom
- kommer
- komfortabel
- Felles
- Kommunikasjon
- Selskapet
- sammenligne
- sammenligne
- kompatibilitet
- kompatibel
- fullføre
- helt
- ferdigstillelse
- komplekse
- kompleksiteten
- komponent
- komponenter
- komponert
- sammensetning
- omfattende
- omfattende
- konsept
- konsis
- samtidig
- tilstand
- Konfigurasjon
- sammenløp
- Koble
- Tilkobling
- Tilkobling
- Ulemper
- Vurder
- konsekvent
- består
- Konsoll
- stadig
- konstruerer
- inneholde
- inneholder
- innhold
- kontekst
- sammenhenger
- kontekstuelle
- fortsette
- kontinuerlig
- kontrast
- kontroll
- kontroller
- Praktisk
- Samtale
- conversational
- samtale AI
- samtaler
- Konvertering
- konvertert
- konvertering
- Kjerne
- Corner
- korrigere
- Tilsvarende
- kunne
- telling
- land
- Par
- dekke
- dekket
- skape
- opprettet
- skaper
- Opprette
- skaperverket
- Credentials
- kriterier
- Kritiker
- CRM
- avgjørende
- Gjeldende
- I dag
- skikk
- Kunder
- tilpasning
- tilpasse
- tilpasset
- skjærekant
- dato
- Data struktur
- Database
- databaser
- Dato
- dato tid
- avtale
- håndtering
- Desember
- bestemme
- Avgjør
- Beslutningstaking
- Dekoding
- dedikert
- dypere
- Misligholde
- definere
- definert
- definere
- definisjoner
- levere
- leverer
- dybden
- demo
- demonstrere
- demonstrert
- demonstrere
- avhenge
- avhengig
- avhenger
- utplassere
- utplassert
- utplasserings
- distribusjon
- Distribueres
- beskrive
- beskrivelse
- utforming
- utpekt
- designet
- ønsket
- detalj
- detaljert
- detaljer
- Bestem
- bestemmes
- utvikle
- Utvikler
- utviklere
- utvikle
- Utvikling
- diagrammer
- DIKT
- gJORDE
- avvike
- forskjellig
- annerledes
- vanskelig
- Dimensjon
- dimensjoner
- direktiver
- direkte
- diskutere
- diskutert
- visning
- distinkt
- dykk
- diverse
- DM
- do
- dokument
- dokumentasjon
- dokumenter
- gjør
- doesn
- gjør
- Don
- gjort
- dobbelt
- ned
- nedlasting
- nedlastinger
- Utkast
- stasjonen
- to
- under
- dynamisk
- dynamisk
- e
- hver enkelt
- Tidligere
- Tidlig
- lette
- brukervennlighet
- enklere
- lett
- lett
- lett-å-bruke
- savner
- økosystem
- Effektiv
- effektivt
- effektivitet
- effektiv
- effektivt
- uanstrengt
- enten
- element
- elementer
- Elon
- Elon Musk
- ellers
- emalje
- embed
- innebygd
- embedding
- ansatt
- ansatte
- anvender
- bemyndige
- muliggjøre
- muliggjør
- muliggjør
- innkapsler
- støte på
- ende til ende
- Endpoint
- engasjerende
- Motor
- Motorer
- England
- Engelsk
- Engelsk Premier League
- forbedre
- forbedret
- styrke
- sikre
- sikrer
- sikrer
- Enterprise
- enheter
- enhet
- Miljø
- miljøer
- Tilsvarende
- Era
- feil
- feil
- spesielt
- avgjørende
- fraseparerte
- etc
- evaluere
- evaluering
- Selv
- hendelser
- Hver
- eksempel
- eksempler
- stige
- Unntatt
- henrette
- henrettet
- Utfører
- utførende
- gjennomføring
- eksemplifiserer
- Øvelse
- eksisterer
- forvente
- forventninger
- forventet
- forventer
- erfaring
- eksperimentell
- eksperter
- forklarte
- forklarer
- eksplisitt
- leting
- utforske
- utforsket
- eksportere
- uttrykk
- utvide
- strekker
- omfattende
- utvendig
- ekstra
- trekke ut
- utdrag
- ekstrakter
- Face
- legge til rette
- forenkler
- fabrikk
- fakta
- langt
- FAST
- Favoritt
- Trekk
- Egenskaper
- tilbakemelding
- Noen få
- felt
- Felt
- figma
- Figur
- filet
- Filer
- fyll
- fylt
- fylling
- filtrere
- filtrering
- slutt~~POS=TRUNC
- Endelig
- Finn
- finne
- Først
- fem
- fleksibilitet
- fleksibel
- flyten
- Fokus
- fokuserte
- fokuserer
- fokusering
- følge
- etter
- følger
- mat
- Til
- skjema
- format
- dannet
- Heldigvis
- funnet
- Rammeverk
- rammer
- ofte
- venn
- venner
- fra
- fullt
- fullverdig
- funksjon
- funksjonalitet
- funksjonalitet
- funksjoner
- fundamental
- morsomt
- videre
- framtid
- Gevinst
- Games
- Gates
- general
- generelt
- generere
- generert
- genererer
- genererer
- generasjonen
- genre
- Tyskland
- få
- få
- gif
- GitHub
- gitt
- GMT
- Go
- Går
- skal
- god
- granulær
- graf
- flott
- større
- veiledning
- veilede
- retningslinjer
- hackathon
- håndtere
- Håndterer
- Håndtering
- praktisk
- Hard
- skade
- seletøy
- Ha
- å ha
- tungt
- Held
- hjelpe
- nyttig
- hjelper
- her
- her.
- hi
- Høy
- høyt nivå
- høykvalitets
- høyest
- svært
- historisk
- historie
- Hole
- panser
- vert
- Hvordan
- Hvordan
- Men
- HTML
- http
- HTTPS
- Hub
- menneskelig
- Hundrevis
- i
- ID
- Tanken
- ideell
- ids
- if
- ii
- iii
- illustrere
- illustrerer
- bilder
- umiddelbar
- iverksette
- gjennomføring
- implementeringer
- implementert
- importere
- forbedringer
- bedre
- in
- dyptgående
- inkludere
- inkludert
- inkluderer
- Inkludert
- innlemme
- innlemme
- utrolig
- indeks
- indekser
- indikerer
- indikerer
- individuelt
- individer
- informasjon
- innledende
- initiere
- innovative
- inngang
- innganger
- innsikt
- installere
- installerte
- installere
- f.eks
- instant
- i stedet
- instruksjoner
- integrert
- integrere
- integrert
- Integrerer
- Integrering
- integrering
- integrasjoner
- Intelligent
- tiltenkt
- samhandle
- interaksjon
- interaksjoner
- interaktiv
- interaktiv
- Interface
- grensesnitt
- internt
- Internet
- inn
- introdusert
- Introduserer
- intuitiv
- involverer
- er n
- utstedelse
- saker
- IT
- varer
- gjentakelser
- DET ER
- selv
- Jackson
- Javascript
- Jobb
- Jordan
- reise
- JSON
- Juli
- bare
- Justice
- Hold
- holder
- nøkkel
- nøkler
- Type
- Vet
- kunnskap
- Kunnskap Graph
- kjent
- Etiketten
- etiketter
- Tomt
- Språk
- språk
- stor
- større
- Siste
- Ventetid
- seinere
- siste
- League
- LÆRE
- læring
- venstre
- Legacy
- Lengde
- mindre
- la
- Lar
- brev
- Nivå
- nivåer
- Leverage
- utnytter
- utnytte
- bibliotekene
- Bibliotek
- i likhet med
- Sannsynlig
- BEGRENSE
- begrensninger
- Begrenset
- begrense
- grenser
- lenker
- Liste
- lytte
- lister
- leve
- ll
- LLM
- laste
- loader
- ligger
- plassering
- logg
- logget
- logging
- logikk
- Lang
- lenger
- Se
- ser
- UTSEENDE
- oppslag
- den
- Los Angeles
- Lav
- maskin
- maskinlæring
- laget
- vedlikeholde
- Vedlikeholdbar
- Vedlike
- opprettholder
- gjøre
- GJØR AT
- Making
- administrer
- ledelse
- leder
- administrerende
- manchester
- Manchester United
- Manipulasjon
- måte
- håndbok
- Produsent
- mange
- mange folk
- kart
- kartlegging
- Kart
- Match
- matchende
- math
- matematiske
- Saker
- maksimal
- Kan..
- me
- bety
- betyr
- midler
- måle
- Media
- møte
- møter
- Minner
- Minne
- nevnt
- Flett
- sammenslåing
- melding
- meldinger
- meldinger
- metadata
- metode
- metoder
- Metrics
- kunne
- millioner
- minimal
- mindre
- mangler
- feil
- Blanding
- MLB
- Mobil
- modell
- modeller
- moderasjon
- Moduler
- Moduler
- øyeblikk
- MongoDB
- Overvåke
- overvåking
- Moon
- mer
- mest
- Mest populær
- flytte
- film
- mye
- flere
- flere kjeder
- Musk
- må
- my
- navn
- oppkalt
- navn
- nasjonal
- Naturlig
- Natural Language Processing
- Naviger
- navigere
- Nær
- nødvendig
- Trenger
- nødvendig
- behov
- negativ
- Ny
- New York
- New York Times
- neste
- Nei.
- none
- ingenting
- Forestilling
- nå
- Antall
- Obama
- objekt
- Målet
- gjenstander
- observasjon
- få
- å skaffe seg
- OCR
- of
- tilby
- tilby
- Tilbud
- ofte
- oh
- Okay
- OL
- on
- gang
- ONE
- bare
- åpen kildekode
- OpenAI
- Drift
- operatør
- optimalisert
- Optimaliserer
- Alternativ
- or
- rekkefølge
- organisk
- organisasjoner
- original
- OS
- Annen
- andre
- ellers
- vår
- ut
- produksjon
- utganger
- enn
- overstyring
- oversikt
- egen
- pakke
- pakker
- side
- sider
- par
- pandaer
- Papir
- Parallel
- parameter
- parametere
- Park
- del
- spesielt
- deler
- passere
- bestått
- passerer
- Passerer
- Past
- banen
- baner
- mønstre
- lønn
- Ansatte
- for
- perfekt
- perfekt
- Utfør
- ytelse
- utfører
- utfører
- tillatelser
- utholdenhet
- person
- Personlig
- perspektiv
- Fysikk
- brikke
- rørledning
- Pizza
- placeholder
- plattform
- plato
- Platon Data Intelligence
- PlatonData
- Spille
- lekeplass
- spiller
- vær så snill
- i tillegg til
- Point
- Politikk
- politikk
- politisk
- basseng
- Populær
- befolket
- positiv
- mulig
- Post
- innlegg
- potensiell
- makt
- powered
- kraftig
- Praktisk
- praksis
- trekker
- premier
- presentere
- president
- forebygge
- hindre
- forrige
- primært
- primære
- Prime
- privat
- Problem
- problemer
- fortsette
- prosess
- Bearbeidet
- Prosesser
- prosessering
- produsere
- Produkt
- Produksjon
- Professor
- Programmering
- programmerings språk
- prosjekt
- prosjekter
- egenskaper
- eiendom
- PROS
- prototype
- prototyping
- gi
- forutsatt
- leverandør
- tilbydere
- gir
- gi
- offentlig
- formål
- formål
- sette
- Python
- Q & A
- kvalitet
- spørsmål
- spørsmål
- spørsmål
- Rask
- raskt
- sitater
- R
- heve
- område
- spenner
- heller
- vurdering
- Raw
- RE
- å nå
- Reager
- Lese
- Lesning
- klar
- ekte
- sanntids
- sanntidsdata
- riket
- grunnen til
- grunner
- nylig
- anbefales
- registrert
- poster
- Gjenopprette
- redusere
- reduserer
- redusere
- reduksjon
- referanse
- refererer
- avgrense
- raffinering
- regioner
- Relasjoner
- utgitt
- relevans
- relevant
- pålitelighet
- pålitelig
- avhengige
- avhengig
- forblir
- husker
- påminnelse
- fjernkontroll
- gi
- gjenta
- GJENTATTE GANGER
- omformulering
- erstatte
- rapporterer
- Repository
- representasjon
- representerer
- representerer
- anmode
- forespørsler
- krever
- påkrevd
- Krav
- Krever
- redde
- forskning
- løse
- ressurs
- Svare
- svare
- svar
- svar
- ansvarlig
- responsive
- REST
- resultere
- resulterende
- Resultater
- støttemur
- oppbevaring
- retur
- retur
- avkastning
- gjenbruk
- anmeldelse
- dreier seg
- Ris
- Rich
- roboter
- Rolle
- roller
- root
- ruting
- RAD
- Kjør
- rennende
- går
- runtime
- s
- sikringstiltak
- salg
- Salesforce
- Sam
- samme
- Spar
- sier
- sier
- skalerbar
- Skala
- scenario
- scenarier
- Scener
- planlegge
- Resultat
- skraper
- sømløs
- sømløst
- Søk
- søkemotor
- søk
- søker
- Seksjon
- seksjoner
- sikre
- sikkerhet
- se
- valgt
- utvalg
- Å Sell
- send
- sensitive
- sentiment
- følelser
- separat
- September
- Sequence
- Serien
- betjene
- server
- serverer
- Tjenester
- sett
- sett
- innstilling
- innstillinger
- oppsett
- syv
- flere
- Del
- delt
- Shell
- skinner
- levert
- bør
- Vis
- presentere
- vist
- Viser
- Sigma
- signifikant
- lignende
- Enkelt
- forenklet
- forenkle
- forenkle
- ganske enkelt
- siden
- enkelt
- Størrelse
- slakk
- liten
- mindre
- Smart
- tekstutdrag
- So
- så langt
- Fotball
- selskap
- sosiale medier
- Sosiale medier innlegg
- utelukkende
- solid
- løsning
- LØSE
- noen
- noe
- noen ganger
- sofistikert
- lyder
- kilde
- Kilder
- Rom
- Spansk
- spesialisert
- spesifikk
- spesielt
- detaljer
- spesifisert
- fart
- brukt
- splittet
- spagaten
- Sport
- kvadrat
- stå
- stående
- Standard
- Begynn
- startet
- Start
- Tilstand
- uttalelser
- statisk
- Trinn
- Steps
- Still
- Stopp
- stoppe
- Stopper
- lagring
- oppbevare
- lagret
- butikker
- lagring
- Story
- rett fram
- stream
- streaming
- effektivisere
- strømlinjeformet
- styrker
- streik
- String
- struktur
- strukturert
- strukturer
- strukturering
- stil
- emne
- senere
- vellykket
- slik
- Dress
- egnet
- suite
- oppsummere
- SAMMENDRAG
- Solnedgang
- støtte
- Støttes
- Støtter
- sikker
- Bærekraft
- synkronisering
- synopsis
- syntaks
- system
- Systemer
- bord
- skredder
- skreddersydd
- Ta
- tar
- mål
- Oppgave
- oppgaver
- lag
- lag
- fortelle
- mal
- maler
- terminal
- terminologi
- vilkår
- test
- Testing
- tekst
- enn
- Takk
- Det
- De
- Grunnleggende
- navet
- informasjonen
- The New York Times
- Prosjektene
- Kilden
- verden
- deres
- Dem
- deretter
- Der.
- Disse
- de
- ting
- denne
- De
- selv om?
- Gjennom
- hele
- tid
- tidkrevende
- ganger
- Tittel
- til
- sammen
- token
- tokenization
- tokens
- også
- verktøy
- verktøykasse
- verktøy
- topp
- Tema
- temaer
- Totalt
- byen
- Sporing
- spor
- tradisjonelle
- Kurs
- Transform
- transformasjoner
- transformator
- transformers
- overgang
- prøve
- sant
- virkelig
- prøve
- tuning
- SVING
- Turning
- tutorial
- To ganger
- to
- typen
- typer
- Loggfila
- typisk
- ui
- Til syvende og sist
- upåvirket
- etter
- underliggende
- forstå
- forståelse
- forstår
- enhetlig
- unik
- forent
- Universell
- I motsetning til
- til
- Oppdater
- oppdateringer
- lastet opp
- URL
- us
- brukervennlighet
- bruk
- bruke
- bruk sak
- brukt
- Bruker
- Brukergrensesnitt
- Brukere
- bruker
- ved hjelp av
- verktøy
- bruke
- benyttes
- bruker
- utnytte
- v1
- validering
- Validator
- Verdifull
- verdi
- Verdier
- variabel
- variasjon
- ulike
- Ve
- allsidig
- versjon
- veldig
- av
- video
- Se
- Brudd
- synlig
- visualisere
- vital
- vs
- gå
- walkthrough
- ønsker
- var
- Se
- Vei..
- måter
- we
- Vær
- web
- nettleser
- webtjenester
- nettsteder
- VI VIL
- velkjent
- var
- Hva
- Hva er
- whats
- når
- om
- hvilken
- mens
- HVEM
- hele
- hvorfor
- bred
- allment
- widget
- Wikipedia
- vil
- vindu
- Vinner
- med
- innenfor
- uten
- ord
- Arbeid
- arbeidet
- arbeidsflyt
- arbeidsflyt
- arbeid
- virker
- verden
- ville
- skrive
- skriving
- X
- ennå
- york
- Du
- Din
- deg selv
- youtube
- Zendesk
- zephyrnet
- Zip