I sin kärna, Langkedja är ett innovativt ramverk skräddarsytt för att skapa applikationer som utnyttjar språkmodellernas möjligheter. Det är en verktygslåda som är utformad för utvecklare för att skapa applikationer som är kontextmedvetna och kapabla till sofistikerade resonemang.
Detta innebär att LangChain-applikationer kan förstå sammanhanget, såsom snabba instruktioner eller innehållsgrundande svar och använda språkmodeller för komplexa resonemangsuppgifter, som att bestämma hur de ska svara eller vilka åtgärder som ska vidtas. LangChain representerar ett enhetligt tillvägagångssätt för att utveckla intelligenta applikationer, som förenklar resan från idé till utförande med dess olika komponenter.
Förstå LangChain
LangChain är mycket mer än bara ett ramverk; det är ett fullfjädrat ekosystem som består av flera integrerade delar.
- För det första finns det LangChain-biblioteken, tillgängliga i både Python och JavaScript. Dessa bibliotek är ryggraden i LangChain, och erbjuder gränssnitt och integrationer för olika komponenter. De ger en grundläggande körtid för att kombinera dessa komponenter till sammanhängande kedjor och agenter, tillsammans med färdiga implementeringar för omedelbar användning.
- Därefter har vi LangChain-mallar. Dessa är en samling utplacerbara referensarkitekturer som är skräddarsydda för ett brett spektrum av uppgifter. Oavsett om du bygger en chatbot eller ett komplext analysverktyg erbjuder dessa mallar en solid utgångspunkt.
- LangServe går in som ett mångsidigt bibliotek för att distribuera LangChain-kedjor som REST API:er. Detta verktyg är viktigt för att omvandla dina LangChain-projekt till tillgängliga och skalbara webbtjänster.
- Slutligen fungerar LangSmith som en utvecklarplattform. Den är utformad för att felsöka, testa, utvärdera och övervaka kedjor som bygger på alla LLM-ramverk. Den sömlösa integrationen med LangChain gör det till ett oumbärligt verktyg för utvecklare som vill förfina och perfekta sina applikationer.
Tillsammans ger dessa komponenter dig möjlighet att utveckla, producera och distribuera applikationer med lätthet. Med LangChain börjar du med att skriva dina ansökningar med hjälp av biblioteken, hänvisa till mallar för vägledning. LangSmith hjälper dig sedan att inspektera, testa och övervaka dina kedjor, för att säkerställa att dina applikationer ständigt förbättras och är redo för driftsättning. Slutligen, med LangServe kan du enkelt omvandla vilken kedja som helst till ett API, vilket gör implementeringen till en lek.
I nästa avsnitt kommer vi att fördjupa oss i hur du ställer in LangChain och börjar din resa med att skapa intelligenta, språkmodelldrivna applikationer.
Automatisera manuella uppgifter och arbetsflöden med vår AI-drivna arbetsflödesbyggare, designad av Nanonets för dig och dina team.
Installation och installation
Är du redo att dyka in i LangChains värld? Att ställa in det är enkelt, och den här guiden leder dig genom processen steg-för-steg.
Det första steget i din LangChain-resa är att installera den. Du kan göra detta enkelt med pip eller conda. Kör följande kommando i din terminal:
pip install langchain
För dem som föredrar de senaste funktionerna och är bekväma med lite mer äventyr, kan du installera LangChain direkt från källan. Klona förvaret och navigera till langchain/libs/langchain
katalog. Kör sedan:
pip install -e .
För experimentella funktioner, överväg att installera langchain-experimental
. Det är ett paket som innehåller banbrytande kod och är avsett för forsknings- och experimentändamål. Installera den med:
pip install langchain-experimental
LangChain CLI är ett praktiskt verktyg för att arbeta med LangChain-mallar och LangServe-projekt. För att installera LangChain CLI, använd:
pip install langchain-cli
LangServe är avgörande för att distribuera dina LangChain-kedjor som ett REST API. Den installeras tillsammans med LangChain CLI.
LangChain kräver ofta integrationer med modellleverantörer, datalager, API:er, etc. För det här exemplet kommer vi att använda OpenAI:s modell-API:er. Installera OpenAI Python-paketet med:
pip install openai
För att komma åt API:t, ställ in din OpenAI API-nyckel som en miljövariabel:
export OPENAI_API_KEY="your_api_key"
Alternativt kan du skicka nyckeln direkt i din pythonmiljö:
import os
os.environ['OPENAI_API_KEY'] = 'your_api_key'
LangChain möjliggör skapandet av språkmodellapplikationer genom moduler. Dessa moduler kan antingen stå ensamma eller vara sammansatta för komplexa användningsfall. Dessa moduler är -
- Modell I/O: Underlättar interaktion med olika språkmodeller, hanterar deras input och output effektivt.
- hämtning: Möjliggör åtkomst till och interaktion med applikationsspecifik data, avgörande för dynamisk dataanvändning.
- Agenter: Ge applikationer möjlighet att välja lämpliga verktyg baserade på direktiv på hög nivå, vilket förbättrar beslutsfattandet.
- Kedjor: Erbjuder fördefinierade, återanvändbara kompositioner som fungerar som byggstenar för applikationsutveckling.
- Minne: Upprätthåller applikationstillstånd över flera kedjekörningar, väsentligt för sammanhangsmedvetna interaktioner.
Varje modul riktar sig mot specifika utvecklingsbehov, vilket gör LangChain till en omfattande verktygslåda för att skapa avancerade språkmodellapplikationer.
Tillsammans med ovanstående komponenter har vi också LangChain Expression Language (LCEL), vilket är ett deklarativt sätt att enkelt komponera moduler tillsammans, och detta möjliggör kedja av komponenter med hjälp av ett universellt körbart gränssnitt.
LCEL ser ut ungefär så här –
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import BaseOutputParser # Example chain
chain = ChatPromptTemplate() | ChatOpenAI() | CustomOutputParser()
Nu när vi har täckt grunderna kommer vi att fortsätta till:
- Gräv djupare i varje Langchain-modul i detalj.
- Lär dig hur du använder LangChain Expression Language.
- Utforska vanliga användningsfall och implementera dem.
- Distribuera en heltäckande applikation med LangServe.
- Kolla in LangSmith för felsökning, testning och övervakning.
Låt oss börja!
Modul I: Modell I/O
I LangChain kretsar kärnelementet i alla applikationer kring språkmodellen. Denna modul tillhandahåller de väsentliga byggstenarna för att effektivt samverka med alla språkmodeller, vilket säkerställer sömlös integration och kommunikation.
Nyckelkomponenter i modell I/O
- LLM och chattmodeller (används omväxlande):
- LLM:er:
- Definition: Rena textkompletteringsmodeller.
- Input / Output: Ta en textsträng som indata och returnera en textsträng som utdata.
- Chattmodeller
- LLM:er:
- Definition: Modeller som använder en språkmodell som bas men skiljer sig i inmatnings- och utdataformat.
- Input / Output: Acceptera en lista med chattmeddelanden som inmatning och returnera ett chattmeddelande.
- Frågar: Skapa mallar, välj dynamiskt och hantera modellingångar. Möjliggör skapandet av flexibla och kontextspecifika uppmaningar som vägleder språkmodellens svar.
- Output Parsers: Extrahera och formatera information från modellutgångar. Användbar för att konvertera råutdata från språkmodeller till strukturerad data eller specifika format som behövs av applikationen.
LLM
LangChains integration med stora språkmodeller (LLM) som OpenAI, Cohere och Hugging Face är en grundläggande aspekt av dess funktionalitet. LangChain i sig är inte värd för LLM:er men erbjuder ett enhetligt gränssnitt för att interagera med olika LLM:er.
Det här avsnittet ger en översikt över användningen av OpenAI LLM-omslaget i LangChain, även tillämpligt på andra LLM-typer. Vi har redan installerat detta i avsnittet "Komma igång". Låt oss initiera LLM.
from langchain.llms import OpenAI
llm = OpenAI()
- LLM:er implementerar Körbart gränssnitt, den grundläggande byggstenen i LangChain Expression Language (LCEL). Det betyder att de stödjer
invoke
,ainvoke
,stream
,astream
,batch
,abatch
,astream_log
samtal. - LLM accepterar strängar som indata, eller objekt som kan tvingas till strängprompter, inklusive
List[BaseMessage]
ochPromptValue
. (mer om dessa senare)
Låt oss titta på några exempel.
response = llm.invoke("List the seven wonders of the world.")
print(response)
Du kan alternativt anropa streammetoden för att streama textsvaret.
for chunk in llm.stream("Where were the 2012 Olympics held?"): print(chunk, end="", flush=True)
Chattmodeller
LangChains integration med chattmodeller, en specialiserad variant av språkmodeller, är avgörande för att skapa interaktiva chattapplikationer. Även om de använder språkmodeller internt, presenterar chattmodeller ett distinkt gränssnitt centrerat kring chattmeddelanden som in- och utdata. Det här avsnittet ger en detaljerad översikt över hur man använder OpenAI:s chattmodell i LangChain.
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI()
Chattmodeller i LangChain arbetar med olika meddelandetyper som t.ex AIMessage
, HumanMessage
, SystemMessage
, FunctionMessage
och ChatMessage
(med en godtycklig rollparameter). Allmänt, HumanMessage
, AIMessage
och SystemMessage
är de mest använda.
Chattmodeller accepterar i första hand List[BaseMessage]
som ingångar. Strängar kan konverteras till HumanMessage
och PromptValue
stöds också.
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)
Frågar
Uppmaningar är viktiga för att vägleda språkmodeller för att generera relevanta och sammanhängande resultat. De kan sträcka sig från enkla instruktioner till komplexa få-shot-exempel. I LangChain kan hantering av prompter vara en mycket strömlinjeformad process, tack vare flera dedikerade klasser och funktioner.
LangChain's PromptTemplate
class är ett mångsidigt verktyg för att skapa strängprompter. Den använder Python's str.format
syntax, vilket möjliggör dynamisk promptgenerering. Du kan definiera en mall med platshållare och fylla dem med specifika värden efter behov.
from langchain.prompts import PromptTemplate # Simple prompt with placeholders
prompt_template = PromptTemplate.from_template( "Tell me a {adjective} joke about {content}."
) # Filling placeholders to create a prompt
filled_prompt = prompt_template.format(adjective="funny", content="robots")
print(filled_prompt)
För chattmodeller är uppmaningarna mer strukturerade och involverar meddelanden med specifika roller. LangChain erbjuder ChatPromptTemplate
för det här syftet.
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)
Detta tillvägagångssätt möjliggör skapandet av interaktiva, engagerande chatbots med dynamiska svar.
Både PromptTemplate
och ChatPromptTemplate
integreras sömlöst med LangChain Expression Language (LCEL), vilket gör att de kan ingå i större, komplexa arbetsflöden. Vi kommer att diskutera mer om detta senare.
Anpassade promptmallar är ibland viktiga för uppgifter som kräver unik formatering eller specifika instruktioner. Att skapa en anpassad promptmall innebär att man definierar indatavariabler och en anpassad formateringsmetod. Denna flexibilitet gör att LangChain kan tillgodose ett brett spektrum av applikationsspecifika krav. Läs mer här.
LangChain stöder också få-shot prompting, vilket gör att modellen kan lära sig av exempel. Denna funktion är avgörande för uppgifter som kräver kontextuell förståelse eller specifika mönster. Få-shot-promptmallar kan byggas från en uppsättning exempel eller genom att använda ett exempelväljarobjekt. Läs mer här.
Output Parsers
Utdataparsers spelar en avgörande roll i Langchain, vilket gör det möjligt för användare att strukturera svaren som genereras av språkmodeller. I det här avsnittet kommer vi att utforska konceptet med utdataparsare och ge kodexempel med hjälp av Langchains PydanticOutputParser, SimpleJsonOutputParser, CommaSeparatedListOutputParser, DatetimeOutputParser och XMLOutputParser.
PydanticOutputParser
Langchain tillhandahåller PydanticOutputParser för att analysera svar i Pydantiska datastrukturer. Nedan följer ett steg-för-steg-exempel på hur du använder 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)
Utgången kommer att vara:
SimpleJsonOutputParser
Langchains SimpleJsonOutputParser används när du vill analysera JSON-liknande utdata. Här är ett exempel:
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 är praktisk när du vill extrahera kommaseparerade listor från modellsvar. Här är ett exempel:
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 är designad för att tolka datetime-information. Så här använder 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)
Dessa exempel visar hur Langchains utdataparsers kan användas för att strukturera olika typer av modellsvar, vilket gör dem lämpliga för olika applikationer och format. Utdataparsers är ett värdefullt verktyg för att förbättra användbarheten och tolkningen av språkmodellutdata i Langchain.
Automatisera manuella uppgifter och arbetsflöden med vår AI-drivna arbetsflödesbyggare, designad av Nanonets för dig och dina team.
Modul II : Hämtning
Hämtning i LangChain spelar en avgörande roll i applikationer som kräver användarspecifik data, som inte ingår i modellens träningsuppsättning. Denna process, känd som Retrieval Augmented Generation (RAG), innebär att man hämtar extern data och integrerar den i språkmodellens genereringsprocess. LangChain tillhandahåller en omfattande svit av verktyg och funktioner för att underlätta denna process, som passar både enkla och komplexa applikationer.
LangChain uppnår hämtning genom en serie komponenter som vi kommer att diskutera en efter en.
Dokumentladdare
Dokumentladdare i LangChain möjliggör extrahering av data från olika källor. Med över 100 tillgängliga laddare stöder de en rad dokumenttyper, appar och källor (privata s3-hinkar, offentliga webbplatser, databaser).
Du kan välja en dokumentladdare baserat på dina krav här..
Alla dessa laddare matar in data Dokument klasser. Vi kommer att lära oss hur du använder data som tas in i dokumentklasser senare.
Textfilladdare: Ladda en enkel .txt
fil i ett dokument.
from langchain.document_loaders import TextLoader loader = TextLoader("./sample.txt")
document = loader.load()
CSV-laddare: Ladda en CSV-fil i ett dokument.
from langchain.document_loaders.csv_loader import CSVLoader loader = CSVLoader(file_path='./example_data/sample.csv')
documents = loader.load()
Vi kan välja att anpassa analysen genom att ange fältnamn –
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-laddare: PDF Loaders i LangChain erbjuder olika metoder för att analysera och extrahera innehåll från PDF-filer. Varje laddare tillgodoser olika krav och använder olika underliggande bibliotek. Nedan finns detaljerade exempel för varje lastare.
PyPDFLoader används för grundläggande PDF-analys.
from langchain.document_loaders import PyPDFLoader loader = PyPDFLoader("example_data/layout-parser-paper.pdf")
pages = loader.load_and_split()
MathPixLoader är idealisk för att extrahera matematiskt innehåll och diagram.
from langchain.document_loaders import MathpixPDFLoader loader = MathpixPDFLoader("example_data/math-content.pdf")
data = loader.load()
PyMuPDFLoader är snabb och inkluderar detaljerad extrahering av metadata.
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 används för mer detaljerad kontroll över textextraktion.
from langchain.document_loaders import PDFMinerLoader loader = PDFMinerLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
AmazonTextractPDFParser använder AWS Textract för OCR och andra avancerade PDF-analysfunktioner.
from langchain.document_loaders import AmazonTextractPDFLoader # Requires AWS account and configuration
loader = AmazonTextractPDFLoader("example_data/complex-layout.pdf")
documents = loader.load()
PDFMinerPDFasHTMLLoader genererar HTML från PDF för semantisk analys.
from langchain.document_loaders import PDFMinerPDFasHTMLLoader loader = PDFMinerPDFasHTMLLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
PDFPlumberLoader tillhandahåller detaljerad metadata och stöder ett dokument per sida.
from langchain.document_loaders import PDFPlumberLoader loader = PDFPlumberLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
Integrerade lastare: LangChain erbjuder ett brett utbud av anpassade laddare för att direkt ladda data från dina appar (som Slack, Sigma, Notion, Confluence, Google Drive och många fler) och databaser och använda dem i LLM-applikationer.
Den kompletta listan är här..
Nedan följer ett par exempel för att illustrera detta –
Exempel I – Slack
Slack, en flitigt använd plattform för snabbmeddelanden, kan integreras i LLM-arbetsflöden och applikationer.
- Gå till din Slack Workspace Management-sida.
- Navigera till
{your_slack_domain}.slack.com/services/export
. - Välj önskat datumintervall och påbörja exporten.
- Slack meddelar via e-post och DM när exporten är klar.
- Exporten resulterar i en
.zip
filen som finns i din nedladdningsmapp eller din angivna nedladdningssökväg. - Tilldela sökvägen för den nedladdade
.zip
fil tillLOCAL_ZIPFILE
. - Använd
SlackDirectoryLoader
frånlangchain.document_loaders
paket.
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)
Exempel II – Figma
Figma, ett populärt verktyg för gränssnittsdesign, erbjuder ett REST API för dataintegration.
- Skaffa Figma-filnyckeln från URL-formatet:
https://www.figma.com/file/{filekey}/sampleFilename
. - Nod-ID:n finns i URL-parametern
?node-id={node_id}
. - Generera en åtkomsttoken enligt instruktionerna på Figma Hjälpcenter.
- Smakämnen
FigmaFileLoader
klass frånlangchain.document_loaders.figma
används för att ladda Figma-data. - Olika LangChain-moduler som
CharacterTextSplitter
,ChatOpenAI
, etc., används för bearbetning.
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()
- Smakämnen
generate_code
funktionen använder Figma-data för att skapa HTML/CSS-kod. - Den använder en mallbaserad konversation med en GPT-baserad 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)
- Smakämnen
generate_code
funktionen, när den körs, returnerar HTML/CSS-kod baserat på Figma-designinmatningen.
Låt oss nu använda vår kunskap för att skapa några dokumentuppsättningar.
Vi laddar först en PDF, BCG:s årliga hållbarhetsrapport.
Vi använder PyPDFLoader för detta.
from langchain.document_loaders import PyPDFLoader loader = PyPDFLoader("bcg-2022-annual-sustainability-report-apr-2023.pdf")
pdfpages = loader.load_and_split()
Vi kommer att mata in data från Airtable nu. Vi har en Airtable som innehåller information om olika OCR- och dataextraktionsmodeller –
Låt oss använda AirtableLoader för detta, som finns i listan över integrerade lastare.
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()
Låt oss nu gå vidare och lära oss hur man använder dessa dokumentklasser.
Dokumenttransformatorer
Dokumenttransformatorer i LangChain är viktiga verktyg utformade för att manipulera dokument, som vi skapade i vårt tidigare underavsnitt.
De används för uppgifter som att dela upp långa dokument i mindre bitar, kombinera och filtrera, vilket är avgörande för att anpassa dokument till en modells kontextfönster eller möta specifika applikationsbehov.
Ett sådant verktyg är RecursiveCharacterTextSplitter, en mångsidig textdelare som använder en teckenlista för att dela. Det tillåter parametrar som chunkstorlek, överlappning och startindex. Här är ett exempel på hur det används 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])
Ett annat verktyg är CharacterTextSplitter, som delar upp text baserat på ett specificerat tecken och inkluderar kontroller för bitstorlek och överlappning:
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 är utformad för att dela HTML-innehåll baserat på rubriktaggar, och behåller den semantiska 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 komplex manipulation kan uppnås genom att kombinera HTMLHeaderTextSplitter med en annan 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 erbjuder också specifika splitters för olika programmeringsspråk, som Python Code Splitter och 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])
För att dela text baserat på tokenantal, vilket är användbart för språkmodeller med tokengränser, används 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])
Slutligen ordnar LongContextReorder dokument för att förhindra prestandaförsämring i modeller på grund av långa sammanhang:
from langchain.document_transformers import LongContextReorder reordering = LongContextReorder()
reordered_docs = reordering.transform_documents(docs)
print(reordered_docs[0])
Dessa verktyg visar olika sätt att transformera dokument i LangChain, från enkel textdelning till komplex omordning och språkspecifik delning. För mer djupgående och specifika användningsfall bör avsnittet LangChain dokumentation och integrationer konsulteras.
I våra exempel har laddarna redan skapat bitar av dokument åt oss, och denna del är redan hanterad.
Textinbäddningsmodeller
Textinbäddningsmodeller i LangChain tillhandahåller ett standardiserat gränssnitt för olika leverantörer av inbäddningsmodeller som OpenAI, Cohere och Hugging Face. Dessa modeller omvandlar text till vektorrepresentationer, vilket möjliggör operationer som semantisk sökning genom textlikhet i vektorutrymme.
För att komma igång med textinbäddningsmodeller behöver du vanligtvis installera specifika paket och ställa in API-nycklar. Vi har redan gjort detta för OpenAI
I LangChain, den embed_documents
Metoden används för att bädda in flera texter, vilket ger en lista över vektorrepresentationer. Till exempel:
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]))
För att bädda in en enskild text, till exempel en sökfråga, embed_query
metod används. Detta är användbart för att jämföra en fråga med en uppsättning dokumentinbäddningar. Till exempel:
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])
Att förstå dessa inbäddningar är avgörande. Varje textstycke omvandlas till en vektor, vars dimension beror på vilken modell som används. Till exempel producerar OpenAI-modeller vanligtvis 1536-dimensionella vektorer. Dessa inbäddningar används sedan för att hämta relevant information.
LangChains inbäddningsfunktion är inte begränsad till OpenAI utan är designad för att fungera med olika leverantörer. Inställningen och användningen kan skilja sig något beroende på leverantör, men kärnkonceptet med att bädda in texter i vektorutrymme förblir detsamma. För detaljerad användning, inklusive avancerade konfigurationer och integrationer med olika leverantörer av inbäddningsmodeller, är LangChain-dokumentationen i avsnittet Integration en värdefull resurs.
Vektorbutiker
Vektorbutiker i LangChain stödjer effektiv lagring och sökning av textinbäddningar. LangChain integreras med över 50 vektorbutiker, vilket ger ett standardiserat gränssnitt för enkel användning.
Exempel: Lagra och söka inbäddningar
Efter att ha bäddat in texter kan vi lagra dem i en vektorbutik som Chroma
och utför likhetssökningar:
from langchain.vectorstores import Chroma db = Chroma.from_texts(embedded_texts)
similar_texts = db.similarity_search("search query")
Låt oss alternativt använda FAISS vektorlager för att skapa index för våra dokument.
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS pdfstore = FAISS.from_documents(pdfpages, embedding=OpenAIEmbeddings()) airtablestore = FAISS.from_documents(airtabledocs, embedding=OpenAIEmbeddings())
retriever
Retrievers i LangChain är gränssnitt som returnerar dokument som svar på en ostrukturerad fråga. De är mer allmänna än vektorbutiker, med fokus på hämtning snarare än lagring. Även om vektorlager kan användas som en retrievers ryggrad, finns det andra typer av retrievers också.
För att ställa in en Chroma retriever installerar du den först med hjälp av pip install chromadb
. Sedan laddar, delar du, bäddar in och hämtar dokument med hjälp av en serie Python-kommandon. Här är ett kodexempel för att ställa in 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 automatiserar snabbjustering genom att generera flera frågor för en användarinmatningsfråga och kombinerar resultaten. Här är ett exempel på dess enkla användning:
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))
Kontextuell komprimering i LangChain komprimerar hämtade dokument med hjälp av frågans sammanhang, vilket säkerställer att endast relevant information returneras. Detta innebär innehållsminskning och filtrering av mindre relevanta dokument. Följande kodexempel visar hur du använder 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 kombinerar olika hämtningsalgoritmer för att uppnå bättre prestanda. Ett exempel på att kombinera BM25 och FAISS Retrievers visas i följande kod:
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 tillåter förfrågning av dokument med flera vektorer per dokument, vilket är användbart för att fånga olika semantiska aspekter i ett dokument. Metoder för att skapa flera vektorer inkluderar att dela upp i mindre bitar, sammanfatta eller generera hypotetiska frågor. För att dela upp dokument i mindre bitar kan följande Python-kod användas:
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)))
Att generera sammanfattningar för bättre hämtning på grund av mer fokuserad innehållsrepresentation är en annan metod. Här är ett exempel på hur du skapar sammanfattningar:
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)))
Att generera hypotetiska frågor som är relevanta för varje dokument med hjälp av LLM är ett annat tillvägagångssätt. Detta kan göras med följande kod:
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 är en annan retriever som skapar en balans mellan inbäddning av noggrannhet och kontextbevarande genom att lagra små bitar och hämta sina större överordnade dokument. Dess genomförande är som följer:
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 självfrågande retriever konstruerar strukturerade frågor från naturliga språkingångar och tillämpar dem på dess underliggande VectorStore. Dess implementering visas i följande kod:
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ör webbforskning baserat på en given fråga –
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")
För våra exempel kan vi också använda standardretrievern som redan är implementerad som en del av vårt vektorlagerobjekt enligt följande –
Vi kan nu fråga retrievers. Utdata från vår fråga kommer att vara dokumentobjekt som är relevanta för frågan. Dessa kommer i slutändan att användas för att skapa relevanta svar i ytterligare avsnitt.
Automatisera manuella uppgifter och arbetsflöden med vår AI-drivna arbetsflödesbyggare, designad av Nanonets för dig och dina team.
Modul III: Agenter
LangChain introducerar ett kraftfullt koncept som kallas "Agents" som tar idén om kedjor till en helt ny nivå. Agenter använder språkmodeller för att dynamiskt bestämma sekvenser av åtgärder som ska utföras, vilket gör dem otroligt mångsidiga och adaptiva. Till skillnad från traditionella kedjor, där åtgärder är hårdkodade i kod, använder agenter språkmodeller som resonemangsmotorer för att bestämma vilka åtgärder de ska vidta och i vilken ordning.
Agenten är den centrala komponenten som ansvarar för beslutsfattande. Den utnyttjar kraften i en språkmodell och en uppmaning att bestämma nästa steg för att uppnå ett specifikt mål. Indata till en agent inkluderar vanligtvis:
- Verktyg: Beskrivningar av tillgängliga verktyg (mer om detta senare).
- Användarinmatning: Högnivåmålet eller frågan från användaren.
- Mellansteg: En historik över (åtgärd, verktygsutgång) par som exekveras för att nå den aktuella användarinmatningen.
En agents utdata kan vara nästa handling att vidta åtgärder (Agentåtgärder) eller finalen respons att skicka till användaren (AgentFinish). En handling specificerar a verktyg och ingång för det verktyget.
verktyg
Verktyg är gränssnitt som en agent kan använda för att interagera med världen. De gör det möjligt för agenter att utföra olika uppgifter, som att söka på webben, köra skalkommandon eller komma åt externa API:er. I LangChain är verktyg viktiga för att utöka agenternas kapacitet och göra det möjligt för dem att utföra olika uppgifter.
För att använda verktyg i LangChain kan du ladda dem med följande kodavsnitt:
from langchain.agents import load_tools tool_names = [...]
tools = load_tools(tool_names)
Vissa verktyg kan kräva en basspråkmodell (LLM) för att initieras. I sådana fall kan du godkänna en LLM också:
from langchain.agents import load_tools tool_names = [...]
llm = ...
tools = load_tools(tool_names, llm=llm)
Denna inställning låter dig komma åt en mängd olika verktyg och integrera dem i din agents arbetsflöden. Den kompletta listan över verktyg med användningsdokumentation är här..
Låt oss titta på några exempel på verktyg.
DuckDuckGo
DuckDuckGo-verktyget låter dig utföra webbsökningar med hjälp av dess sökmotor. Så här använder du det:
from langchain.tools import DuckDuckGoSearchRun
search = DuckDuckGoSearchRun()
search.run("manchester united vs luton town match summary")
DataForSeo
Med DataForSeo-verktygslådan kan du få sökmotorresultat med hjälp av DataForSeo API. För att använda denna verktygslåda måste du ställa in dina API-uppgifter. Så här konfigurerar du autentiseringsuppgifterna:
import os os.environ["DATAFORSEO_LOGIN"] = "<your_api_access_username>"
os.environ["DATAFORSEO_PASSWORD"] = "<your_api_access_password>"
När dina referenser är inställda kan du skapa en DataForSeoAPIWrapper
verktyg för att komma åt API:et:
from langchain.utilities.dataforseo_api_search import DataForSeoAPIWrapper wrapper = DataForSeoAPIWrapper() result = wrapper.run("Weather in Los Angeles")
Smakämnen DataForSeoAPIWrapper
verktyget hämtar sökmotorresultat från olika källor.
Du kan anpassa typen av resultat och fält som returneras i JSON-svaret. Du kan till exempel ange resultattyper, fält och ange ett maximalt antal för antalet toppresultat som ska returneras:
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")
Det här exemplet anpassar JSON-svaret genom att ange resultattyper, fält och begränsa antalet resultat.
Du kan också ange plats och språk för dina sökresultat genom att skicka ytterligare parametrar till 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")
Genom att tillhandahålla plats- och språkparametrar kan du skräddarsy dina sökresultat till specifika regioner och språk.
Du har flexibiliteten att välja den sökmotor du vill använda. Ange bara önskad sökmotor:
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 det här exemplet är sökningen anpassad för att använda Bing som sökmotor.
API-omslaget låter dig också ange vilken typ av sökning du vill utföra. Du kan till exempel göra en kartsökning:
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")
Detta anpassar sökningen för att hämta kartrelaterad information.
Skal (bash)
Shell-verktygslådan ger agenter åtkomst till skalmiljön, så att de kan utföra skalkommandon. Den här funktionen är kraftfull men bör användas med försiktighet, särskilt i sandlådemiljöer. Så här kan du använda Shell-verktyget:
from langchain.tools import ShellTool shell_tool = ShellTool() result = shell_tool.run({"commands": ["echo 'Hello World!'", "time"]})
I det här exemplet kör Shell-verktyget två skalkommandon: ekar "Hello World!" och visar aktuell tid.
Du kan tillhandahålla Shell-verktyget till en agent för att utföra mer komplexa uppgifter. Här är ett exempel på en agent som hämtar länkar från en webbsida med hjälp av Shell-verktyget:
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 det här scenariot använder agenten Shell-verktyget för att köra en sekvens av kommandon för att hämta, filtrera och sortera URL:er från en webbsida.
Exemplen som tillhandahålls visar några av de verktyg som finns tillgängliga i LangChain. Dessa verktyg utökar i slutändan agenternas kapacitet (utforskas i nästa underavsnitt) och ger dem möjlighet att utföra olika uppgifter effektivt. Beroende på dina krav kan du välja de verktyg och verktygssatser som bäst passar ditt projekts behov och integrera dem i din agents arbetsflöden.
Tillbaka till Agenter
Låt oss gå vidare till agenter nu.
AgentExecutor är körtidsmiljön för en agent. Den ansvarar för att anropa agenten, utföra de åtgärder den väljer, skicka tillbaka åtgärdsutgångarna till agenten och upprepa processen tills agenten är klar. I pseudokod kan AgentExecutor se ut ungefär så här:
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 hanterar olika komplexiteter, såsom att hantera fall där agenten väljer ett obefintligt verktyg, hantera verktygsfel, hantera agentproducerade utdata och tillhandahålla loggning och observerbarhet på alla nivåer.
Medan AgentExecutor-klassen är den primära agentkörningstiden i LangChain, finns det andra, mer experimentella körtider som stöds, inklusive:
- Planera och verkställ agent
- Baby AGI
- Auto GPT
För att få en bättre förståelse av agentramverket, låt oss bygga en grundläggande agent från början och sedan gå vidare till att utforska förbyggda agenter.
Innan vi går in i att bygga agenten är det viktigt att återgå till några viktiga terminologier och schema:
- Agent Action: Detta är en dataklass som representerar den åtgärd en agent ska vidta. Den består av en
tool
egenskap (namnet på verktyget som ska anropas) och entool_input
egenskap (indata för det verktyget). - AgentFinish: Denna dataklass indikerar att agenten har slutfört sin uppgift och bör returnera ett svar till användaren. Den innehåller vanligtvis en ordbok med returvärden, ofta med en nyckel "utgång" som innehåller svarstexten.
- Mellansteg: Det här är register över tidigare agentåtgärder och motsvarande utdata. De är avgörande för att överföra sammanhang till framtida iterationer av agenten.
I vårt exempel kommer vi att använda OpenAI Function Calling för att skapa vår agent. Detta tillvägagångssätt är tillförlitligt för att skapa agenter. Vi börjar med att skapa ett enkelt verktyg som beräknar längden på ett ord. Det här verktyget är användbart eftersom språkmodeller ibland kan göra misstag på grund av tokenisering när man räknar ordlängder.
Låt oss först ladda språkmodellen vi ska använda för att styra agenten:
from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
Låt oss testa modellen med en ordlängdsberäkning:
llm.invoke("how many letters in the word educa?")
Svaret bör ange antalet bokstäver i ordet "educa".
Därefter kommer vi att definiera en enkel Python-funktion för att beräkna längden på ett 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 skapat ett verktyg som heter get_word_length
som tar ett ord som indata och returnerar dess längd.
Nu, låt oss skapa prompten för agenten. Uppmaningen instruerar agenten om hur man resonerar och formaterar utdata. I vårt fall använder vi OpenAI Function Calling, vilket kräver minimala instruktioner. Vi kommer att definiera uppmaningen med platshållare för användarinmatning och agentscratchpad:
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"), ]
)
Nu, hur vet agenten vilka verktyg den kan använda? Vi förlitar oss på språkmodeller för OpenAI-funktionsanrop, som kräver att funktioner skickas separat. För att tillhandahålla våra verktyg till agenten formaterar vi dem som OpenAI-funktionsanrop:
from langchain.tools.render import format_tool_to_openai_function llm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools])
Nu kan vi skapa agenten genom att definiera inmatningsmappningar och ansluta komponenterna:
Detta är LCEL-språk. Vi kommer att diskutera detta i detalj senare.
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 skapat vår agent, som förstår användarinmatning, använder tillgängliga verktyg och formaterar utdata. Låt oss nu interagera med det:
agent.invoke({"input": "how many letters in the word educa?", "intermediate_steps": []})
Agenten ska svara med en AgentAction, vilket indikerar nästa åtgärd att vidta.
Vi har skapat agenten, men nu måste vi skriva en körtid för den. Den enklaste körtiden är en som kontinuerligt anropar agenten, utför åtgärder och upprepar tills agenten är klar. Här är ett exempel:
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 den här slingan anropar vi agenten upprepade gånger, utför åtgärder och uppdaterar de mellanliggande stegen tills agenten är klar. Vi hanterar även verktygsinteraktioner inom loopen.
För att förenkla denna process tillhandahåller LangChain klassen AgentExecutor, som kapslar in agentkörning och erbjuder felhantering, tidig stopp, spårning och andra förbättringar. Låt oss använda AgentExecutor för att interagera 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 förenklar exekveringsprocessen och ger ett bekvämt sätt att interagera med agenten.
Minnet diskuteras också i detalj senare.
Agenten vi har skapat hittills är statslös, vilket betyder att den inte kommer ihåg tidigare interaktioner. För att möjliggöra uppföljningsfrågor och samtal måste vi lägga till minne till agenten. Detta innebär två steg:
- Lägg till en minnesvariabel i prompten för att lagra chatthistorik.
- Håll koll på chatthistoriken under interaktioner.
Låt oss börja med att lägga till en minnesplatshållare i prompten:
from langchain.prompts import MessagesPlaceholder MEMORY_KEY = "chat_history"
prompt = ChatPromptTemplate.from_messages( [ ( "system", "You are a very powerful assistant but not great at calculating word lengths.", ), MessagesPlaceholder(variable_name=MEMORY_KEY), ("user", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]
)
Skapa nu en lista för att spåra chatthistoriken:
from langchain.schema.messages import HumanMessage, AIMessage chat_history = []
I steget att skapa agenten inkluderar vi även 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()
)
Se nu till att uppdatera chatthistoriken när du kör agenten:
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})
Detta gör det möjligt för agenten att upprätthålla en konversationshistorik och svara på uppföljningsfrågor baserat på tidigare interaktioner.
Grattis! Du har framgångsrikt skapat och kört din första end-to-end-agent i LangChain. För att fördjupa dig i LangChains möjligheter kan du utforska:
- Olika agenttyper stöds.
- Förbyggda agenter
- Hur man arbetar med verktyg och verktygsintegrationer.
Agenttyper
LangChain erbjuder olika agenttyper, var och en lämpad för specifika användningsfall. Här är några av de tillgängliga agenterna:
- Zero-shot ReAct: Denna agent använder ReAct-ramverket för att välja verktyg baserat enbart på deras beskrivningar. Det kräver beskrivningar för varje verktyg och är mycket mångsidigt.
- Strukturerad ingång ReAct: Denna agent hanterar verktyg för flera inmatningar och är lämplig för komplexa uppgifter som att navigera i en webbläsare. Den använder ett verktygsargumentschema för strukturerad inmatning.
- OpenAI-funktioner: Speciellt utformad för modeller som är finjusterade för funktionsanrop, den här agenten är kompatibel med modeller som gpt-3.5-turbo-0613 och gpt-4-0613. Vi använde detta för att skapa vår första agent ovan.
- Konversation: Denna agent är designad för konversationsinställningar och använder ReAct för val av verktyg och använder minne för att komma ihåg tidigare interaktioner.
- Självfråga med sökning: Denna agent förlitar sig på ett enda verktyg, "Intermediate Answer", som letar upp faktasvar på frågor. Det motsvarar den ursprungliga självfrågan med sökpapper.
- ReAct dokumentarkiv: Denna agent interagerar med ett dokumentarkiv med hjälp av ReAct-ramverket. Den kräver "Sök" och "Lookup"-verktyg och liknar den ursprungliga ReAct-tidningens Wikipedia-exempel.
Utforska dessa agenttyper för att hitta den som bäst passar dina behov i LangChain. Dessa agenter låter dig binda en uppsättning verktyg inom dem för att hantera åtgärder och generera svar. Läs mer om hur du bygger din egen agent med verktyg här.
Förbyggda agenter
Låt oss fortsätta vår utforskning av agenter, med fokus på förbyggda agenter tillgängliga i LangChain.
gmail
LangChain erbjuder en Gmail-verktygslåda som låter dig ansluta din LangChain-e-post till Gmail API. För att komma igång måste du ställa in dina autentiseringsuppgifter, som förklaras i Gmail API-dokumentationen. När du har laddat ner credentials.json
fil kan du fortsätta med Gmail API. Dessutom måste du installera några obligatoriska bibliotek med följande kommandon:
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 skapa Gmails verktygslåda enligt följande:
from langchain.agents.agent_toolkits import GmailToolkit toolkit = GmailToolkit()
Du kan också anpassa autentisering enligt dina behov. Bakom kulisserna skapas en googleapi-resurs med följande 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)
Verktygslådan erbjuder olika verktyg som kan användas inom en agent, inklusive:
GmailCreateDraft
: Skapa ett e-postutkast med angivna meddelandefält.GmailSendMessage
: Skicka e-postmeddelanden.GmailSearch
: Sök efter e-postmeddelanden eller trådar.GmailGetMessage
: Hämta ett e-postmeddelande via meddelande-ID.GmailGetThread
: Sök efter e-postmeddelanden.
Om du vill använda dessa verktyg inom en agent kan du initiera agenten enligt följande:
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,
)
Här är ett par exempel på hur dessa verktyg kan användas:
- Skapa ett Gmail-utkast för 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 efter det senaste e-postmeddelandet i dina utkast:
agent.run("Could you search in my drafts for the latest email?")
Dessa exempel visar funktionerna hos LangChains Gmail-verktygssats i en agent, vilket gör att du kan interagera med Gmail programmatiskt.
SQL Database Agent
Det här avsnittet ger en översikt över en agent utformad för att interagera med SQL-databaser, särskilt Chinook-databasen. Denna agent kan svara på allmänna frågor om en databas och återställa från fel. Observera att det fortfarande är under aktiv utveckling och att alla svar kanske inte är korrekta. Var försiktig när du kör den på känslig data, eftersom den kan utföra DML-satser på din databas.
För att använda den här agenten kan du initiera den enligt följande:
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,
)
Denna agent kan initieras med hjälp av ZERO_SHOT_REACT_DESCRIPTION
agenttyp. Den är utformad för att svara på frågor och ge beskrivningar. Alternativt kan du initiera agenten med hjälp av OPENAI_FUNCTIONS
agenttyp med OpenAI:s GPT-3.5-turbomodell, som vi använde i vår tidigare klient.
Ansvarsfriskrivning
- Frågekedjan kan generera infoga/uppdatera/ta bort frågor. Var försiktig och använd en anpassad prompt eller skapa en SQL-användare utan skrivbehörighet om det behövs.
- Var medveten om att att köra vissa frågor, till exempel "kör den största frågan som möjligt", kan överbelasta din SQL-databas, särskilt om den innehåller miljontals rader.
- Datalagerorienterade databaser stöder ofta kvoter på användarnivå för att begränsa resursanvändningen.
Du kan be agenten att beskriva en tabell, till exempel tabellen "playlisttrack". Här är ett exempel på hur man gör:
agent_executor.run("Describe the playlisttrack table")
Agenten kommer att tillhandahålla information om tabellens schema och exempelrader.
Om du av misstag frågar om en tabell som inte finns, kan agenten återställa och ge information om den närmast matchande tabellen. Till exempel:
agent_executor.run("Describe the playlistsong table")
Agenten hittar närmaste matchande tabell och ger information om den.
Du kan också be agenten att köra frågor på databasen. Till exempel:
agent_executor.run("List the total sales per country. Which country's customers spent the most?")
Agenten kommer att utföra frågan och tillhandahålla resultatet, till exempel det land som har den högsta totala försäljningen.
För att få det totala antalet spår i varje spellista kan du använda följande fråga:
agent_executor.run("Show the total number of tracks in each playlist. The Playlist name should be included in the result.")
Agenten kommer att returnera spellistans namn tillsammans med motsvarande totala antal spår.
I de fall agenten stöter på fel kan den återhämta sig och ge korrekta svar. Till exempel:
agent_executor.run("Who are the top 3 best selling artists?")
Även efter att ha stött på ett initialt fel kommer agenten att justera och ge det korrekta svaret, vilket i det här fallet är de tre bästsäljande artisterna.
Pandas DataFrame Agent
Det här avsnittet introducerar en agent utformad för att interagera med Pandas DataFrames för att svara på frågor. Observera att denna agent använder Python-agenten under huven för att exekvera Python-kod som genereras av en språkmodell (LLM). Var försiktig när du använder denna agent för att förhindra potentiell skada från skadlig Python-kod som genereras av LLM.
Du kan initiera Pandas DataFrame-agenten enligt följande:
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 att räkna antalet rader i DataFrame:
agent.run("how many rows are there?")
Agenten kommer att köra koden df.shape[0]
och ge svaret, till exempel "Det finns 891 rader i dataramen."
Du kan också be agenten att filtrera rader baserat på specifika kriterier, som att hitta antalet personer med fler än 3 syskon:
agent.run("how many people have more than 3 siblings")
Agenten kommer att köra koden df[df['SibSp'] > 3].shape[0]
och ge svaret, som "30 personer har fler än 3 syskon."
Om du vill beräkna kvadratroten av medelåldern kan du fråga agenten:
agent.run("whats the square root of the average age?")
Agenten kommer att beräkna medelåldern med hjälp av df['Age'].mean()
och beräkna sedan kvadratroten med hjälp av math.sqrt()
. Det kommer att ge svaret, till exempel "Kvadratroten av medelåldern är 5.449689683556195."
Låt oss skapa en kopia av DataFrame, och saknade åldersvärden fylls med medelåldern:
df1 = df.copy()
df1["Age"] = df1["Age"].fillna(df1["Age"].mean())
Sedan kan du initiera agenten med båda DataFrames och ställa en fråga till den:
agent = create_pandas_dataframe_agent(OpenAI(temperature=0), [df, df1], verbose=True)
agent.run("how many rows in the age column are different?")
Agenten kommer att jämföra ålderskolumnerna i båda DataFrames och ge svaret, till exempel "177 rader i ålderskolumnen är olika."
Jira Toolkit
Det här avsnittet förklarar hur man använder Jira-verktygslådan, som tillåter agenter att interagera med en Jira-instans. Du kan utföra olika åtgärder som att söka efter problem och skapa problem med hjälp av denna verktygslåda. Det använder biblioteket atlassian-python-api. För att använda denna verktygslåda måste du ställa in miljövariabler för din Jira-instans, inklusive JIRA_API_TOKEN, JIRA_USERNAME och JIRA_INSTANCE_URL. Dessutom kan du behöva ställa in din OpenAI API-nyckel som en miljövariabel.
För att komma igång, installera atlassian-python-api-biblioteket och ställ in de nödvändiga miljövariablerna:
%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 instruera agenten att skapa en ny fråga i ett specifikt projekt med en sammanfattning och beskrivning:
agent.run("make a new issue in project PW to remind me to make more fried rice")
Agenten kommer att utföra de nödvändiga åtgärderna för att skapa problemet och ge ett svar, till exempel "En ny fråga har skapats i projekt PW med sammanfattningen 'Gör mer stekt ris' och beskrivningen 'Påminnelse om att göra mer stekt ris'."
Detta gör att du kan interagera med din Jira-instans med hjälp av instruktioner för naturligt språk och Jira-verktygslådan.
Automatisera manuella uppgifter och arbetsflöden med vår AI-drivna arbetsflödesbyggare, designad av Nanonets för dig och dina team.
Modul IV: Kedjor
LangChain är ett verktyg designat för att använda stora språkmodeller (LLM) i komplexa applikationer. Det tillhandahåller ramverk för att skapa kedjor av komponenter, inklusive LLM och andra typer av komponenter. Två primära ramar
- The LangChain Expression Language (LCEL)
- Legacy Chain-gränssnitt
LangChain Expression Language (LCEL) är en syntax som möjliggör intuitiv sammansättning av kedjor. Den stöder avancerade funktioner som streaming, asynkrona samtal, batchning, parallellisering, återförsök, reservdelar och spårning. Till exempel kan du skapa en prompt, modell och utdataparser i LCEL som visas i följande kod:
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 är LLMChain ett alternativ som liknar LCEL för att komponera komponenter. LLMChain-exemplet är som följer:
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")
Kedjor i LangChain kan också vara tillståndsfulla genom att införliva ett minnesobjekt. Detta möjliggör databeständighet över samtal, som visas i det här exemplet:
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öder även integration med OpenAI:s funktionsanropande API:er, vilket är användbart för att få strukturerade utdata och exekvera funktioner inom en kedja. För att få strukturerade utdata kan du specificera dem med Pydantic-klasser eller JsonSchema, som illustreras nedan:
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"})
För strukturerade utdata är en äldre metod med LLMChain också tillgänglig:
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 utnyttjar OpenAI-funktioner för att skapa olika specifika kedjor för olika ändamål. Dessa inkluderar kedjor för extraktion, taggning, OpenAPI och QA med citat.
I samband med extraktion liknar processen den strukturerade produktionskedjan men fokuserar på information eller enhetsextraktion. För taggning är tanken att märka ett dokument med klasser som känslor, språk, stil, täckta ämnen eller politiska tendenser.
Ett exempel på hur taggning fungerar i LangChain kan demonstreras med en Python-kod. Processen börjar med att installera de nödvändiga paketen och ställa in miljön:
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
Schemat för taggning är definierat och specificerar egenskaperna och deras förväntade 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)
Exempel på att köra taggningskedjan med olika input visar modellens förmåga att tolka känslor, språk och 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'}
För finare kontroll kan schemat definieras mer specifikt, inklusive möjliga värden, beskrivningar och nödvändiga egenskaper. Ett exempel på denna förbättrade kontroll visas nedan:
schema = { "properties": { # Schema definitions here }, "required": ["language", "sentiment", "aggressiveness"],
} chain = create_tagging_chain(schema, llm)
Pydantiska scheman kan också användas för att definiera taggningskriterier, vilket ger ett pytoniskt sätt att specificera nödvändiga egenskaper och typer:
from enum import Enum
from pydantic import BaseModel, Field class Tags(BaseModel): # Class fields here chain = create_tagging_chain_pydantic(Tags, llm)
Dessutom kan LangChains metadatataggardokumenttransformator användas för att extrahera metadata från LangChain-dokument, vilket erbjuder liknande funktionalitet som taggningskedjan men tillämpas på ett LangChain-dokument.
Att citera hämtningskällor är en annan funktion hos LangChain, som använder OpenAI-funktioner för att extrahera citat från text. Detta visas i följande kod:
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 innebär kedja i Large Language Model-applikationer (LLM) vanligtvis att kombinera en promptmall med en LLM och eventuellt en output-parser. Det rekommenderade sättet att göra detta är genom LangChain Expression Language (LCEL), även om den äldre LLMChain-metoden också stöds.
Med hjälp av LCEL implementerar BasePromptTemplate, BaseLanguageModel och BaseOutputParser alla Runnable-gränssnittet och kan enkelt kopplas in i varandra. Här är ett exempel som visar detta:
from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.schema import StrOutputParser prompt = PromptTemplate.from_template( "What is a good name for a company that makes {product}?"
)
runnable = prompt | ChatOpenAI() | StrOutputParser()
runnable.invoke({"product": "colorful socks"})
# Output: 'VibrantSocks'
Routing i LangChain gör det möjligt att skapa icke-deterministiska kedjor där resultatet från ett tidigare steg bestämmer nästa steg. Detta hjälper till att strukturera och upprätthålla konsekvens i interaktioner med LLM. Om du till exempel har två mallar optimerade för olika typer av frågor, kan du välja mallen baserat på användarinput.
Så här kan du uppnå detta med LCEL med en RunnableBranch, som initieras med en lista med (skick, körbara) par och en standard kö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 slutliga kedjan konstrueras sedan med hjälp av olika komponenter, såsom en ämnesklassificerare, promptgren och en utdataparser, för att bestämma flödet baserat på ämnet för inmatningen:
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
Detta tillvägagångssätt exemplifierar flexibiliteten och kraften hos LangChain när det gäller att hantera komplexa frågor och dirigera dem på lämpligt sätt baserat på indata.
Inom språkmodellernas sfär är en vanlig praxis att följa upp ett första samtal med en serie efterföljande samtal, med utdata från ett samtal som indata för nästa. Detta sekventiella tillvägagångssätt är särskilt fördelaktigt när du vill bygga på informationen som genererats i tidigare interaktioner. Även om LangChain Expression Language (LCEL) är den rekommenderade metoden för att skapa dessa sekvenser, är SequentialChain-metoden fortfarande dokumenterad för sin bakåtkompatibilitet.
För att illustrera detta, låt oss överväga ett scenario där vi först genererar en pjässynopsis och sedan en recension baserad på den synopsis. Använder Python's langchain.prompts
, skapar vi två PromptTemplate
instanser: en för synopsis och en annan för recensionen. Här är koden för att ställa in dessa mallar:
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-metoden kedjar vi dessa meddelanden med ChatOpenAI
och StrOutputParser
att skapa en sekvens som först genererar en synopsis och sedan en recension. Kodavsnittet är som följer:
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"})
Om vi behöver både synopsis och recension kan vi använda RunnablePassthrough
för att skapa en separat kedja för varje och sedan kombinera 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"})
För scenarier som involverar mer komplexa sekvenser, SequentialChain
metod spelar in. Detta möjliggör flera ingångar och utgångar. Tänk på ett fall där vi behöver en synopsis baserad på en pjäs titel och era. Så här kan vi ställa in det:
from langchain.llms import OpenAI
from langchain.chains import LLMChain, SequentialChain
from langchain.prompts import PromptTemplate llm = OpenAI(temperature=0.7) synopsis_template = "You are a playwright. Given the title of play and the era it is set in, it is your job to write a synopsis for that title.nnTitle: {title}nEra: {era}nPlaywright: This is a synopsis for the above play:"
synopsis_prompt_template = PromptTemplate(input_variables=["title", "era"], template=synopsis_template)
synopsis_chain = LLMChain(llm=llm, prompt=synopsis_prompt_template, output_key="synopsis") review_template = "You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.nnPlay Synopsis:n{synopsis}nReview from a New York Times play critic of the above play:"
prompt_template = PromptTemplate(input_variables=["synopsis"], template=review_template)
review_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="review") overall_chain = SequentialChain( chains=[synopsis_chain, review_chain], input_variables=["era", "title"], output_variables=["synopsis", "review"], verbose=True,
) overall_chain({"title": "Tragedy at sunset on the beach", "era": "Victorian England"})
I scenarier där du vill behålla sammanhanget genom en kedja eller för en senare del av kedjan, SimpleMemory
kan användas. Detta är särskilt användbart för att hantera komplexa input/output-relationer. Till exempel, i ett scenario där vi vill generera inlägg på sociala medier baserat på en pjäs titel, era, sammanfattning och recension, SimpleMemory
kan hjälpa till att hantera dessa variabler:
from langchain.memory import SimpleMemory
from langchain.chains import SequentialChain template = "You are a social media manager for a theater company. Given the title of play, the era it is set in, the date, time and location, the synopsis of the play, and the review of the play, it is your job to write a social media post for that play.nnHere is some context about the time and location of the play:nDate and Time: {time}nLocation: {location}nnPlay Synopsis:n{synopsis}nReview from a New York Times play critic of the above play:n{review}nnSocial Media Post:"
prompt_template = PromptTemplate(input_variables=["synopsis", "review", "time", "location"], template=template)
social_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="social_post_text") overall_chain = SequentialChain( memory=SimpleMemory(memories={"time": "December 25th, 8pm PST", "location": "Theater in the Park"}), chains=[synopsis_chain, review_chain, social_chain], input_variables=["era", "title"], output_variables=["social_post_text"], verbose=True,
) overall_chain({"title": "Tragedy at sunset on the beach", "era": "Victorian England"})
Förutom sekventiella kedjor finns det specialiserade kedjor för att arbeta med dokument. Var och en av dessa kedjor tjänar ett annat syfte, från att kombinera dokument till att förfina svar baserade på iterativ dokumentanalys, till att kartlägga och reducera dokumentinnehåll för sammanfattning eller omrangering baserat på poängsatta svar. Dessa kedjor kan återskapas med LCEL för ytterligare flexibilitet och anpassning.
-
StuffDocumentsChain
kombinerar en lista med dokument till en enda prompt som skickas till en LLM. -
RefineDocumentsChain
uppdaterar sitt svar iterativt för varje dokument, lämpligt för uppgifter där dokument överskrider modellens kontextkapacitet. -
MapReduceDocumentsChain
tillämpar en kedja för varje dokument individuellt och kombinerar sedan resultaten. -
MapRerankDocumentsChain
poängsätter varje dokumentbaserat svar och väljer det som får högst poäng.
Här är ett exempel på hur du kan ställa in en MapReduceDocumentsChain
använder 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")
Denna konfiguration möjliggör en detaljerad och heltäckande analys av dokumentinnehållet, och utnyttjar styrkorna hos LCEL och den underliggande språkmodellen.
Automatisera manuella uppgifter och arbetsflöden med vår AI-drivna arbetsflödesbyggare, designad av Nanonets för dig och dina team.
Modul V : Minne
I LangChain är minnet en grundläggande aspekt av konversationsgränssnitt, vilket gör att system kan referera till tidigare interaktioner. Detta uppnås genom att lagra och fråga information, med två primära åtgärder: läsa och skriva. Minnessystemet interagerar med en kedja två gånger under en körning, förstärker användarinmatningar och lagrar ingångarna och utgångarna för framtida referens.
Bygga in minne i ett system
- Lagra chattmeddelanden: LangChain-minnesmodulen integrerar olika metoder för att lagra chattmeddelanden, allt från minneslistor till databaser. Detta säkerställer att alla chattinteraktioner registreras för framtida referens.
- Fråga chattmeddelanden: Förutom att lagra chattmeddelanden använder LangChain datastrukturer och algoritmer för att skapa en användbar bild av dessa meddelanden. Enkla minnessystem kan returnera senaste meddelanden, medan mer avancerade system kan sammanfatta tidigare interaktioner eller fokusera på enheter som nämns i den aktuella interaktionen.
För att demonstrera användningen av minne i LangChain, överväga ConversationBufferMemory
klass, ett enkelt minnesformulär som lagrar chattmeddelanden i en buffert. Här är ett exempel:
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 man integrerar minne i en kedja är det avgörande att förstå de variabler som returneras från minnet och hur de används i kedjan. Till exempel load_memory_variables
Metoden hjälper till att anpassa variablerna som läses från minnet med kedjans förväntningar.
End-to-end-exempel med LangChain
Överväg att använda ConversationBufferMemory
i en LLMChain
. Kedjan, i kombination med en lämplig promptmall och minnet, ger en sömlös samtalsupplevelse. Här är ett förenklat exempel:
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?"})
Det här exemplet illustrerar hur LangChains minnessystem integreras med sina kedjor för att ge en sammanhängande och kontextmedveten konversationsupplevelse.
Minnestyper i Langchain
Langchain erbjuder olika minnestyper som kan användas för att förbättra interaktionen med AI-modellerna. Varje minnestyp har sina egna parametrar och returtyper, vilket gör dem lämpliga för olika scenarier. Låt oss utforska några av minnestyperna som finns tillgängliga i Langchain tillsammans med kodexempel.
1. Konversationsbuffertminne
Denna minnestyp låter dig lagra och extrahera meddelanden från konversationer. Du kan extrahera historiken som en sträng eller som en lista med meddelanden.
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 också använda Conversation Buffer Memory i en kedja för chattliknande interaktioner.
2. Minne för konversationsbuffertfönster
Denna minnestyp håller en lista över de senaste interaktionerna och använder de senaste K-interaktionerna, vilket förhindrar att bufferten blir för 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'}
Liksom konversationsbuffertminne kan du också använda denna minnestyp i en kedja för chattliknande interaktioner.
3. Konversationsenhetsminne
Denna minnestyp kommer ihåg fakta om specifika enheter i en konversation och extraherar information med hjälp 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. Konversationskunskapsdiagramminne
Denna minnestyp använder en kunskapsgraf för att återskapa minne. Du kan extrahera aktuella enheter och kunskapstrillingar från meddelanden.
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 också använda denna minnestyp i en kedja för konversationsbaserad kunskapshämtning.
5. Minne för konversationssammanfattning
Den här minnestypen skapar en sammanfattning av konversationen över tid, användbar för att kondensera information från längre konversationer.
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. Konversationssammanfattning Buffertminne
Denna minnestyp kombinerar konversationssammanfattningen och bufferten, och upprätthåller en balans mellan de senaste interaktionerna och en sammanfattning. Den använder tokenlängd för att bestämma när interaktioner ska spolas.
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 använda dessa minnestyper för att förbättra din interaktion med AI-modeller i Langchain. Varje minnestyp tjänar ett specifikt syfte och kan väljas utifrån dina krav.
7. Konversationstokenbuffertminne
ConversationTokenBufferMemory är en annan minnestyp som håller en buffert av senaste interaktioner i minnet. Till skillnad från de tidigare minnestyperna som fokuserar på antalet interaktioner, använder den här tokenlängden för att bestämma när interaktioner ska spolas.
Använda 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 det här exemplet är minnet inställt på att begränsa interaktioner baserat på tokens längd snarare än antalet interaktioner.
Du kan också få historiken som en lista över meddelanden när du använder denna minnestyp.
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"})
Använder i en kedja:
Du kan använda ConversationTokenBufferMemory i en kedja för att förbättra interaktionen 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 det här exemplet används ConversationTokenBufferMemory i en ConversationChain för att hantera konversationen och begränsa interaktioner baserat på tokenlängd.
8. VectorStoreRetrieverMemory
VectorStoreRetrieverMemory lagrar minnen i ett vektorlager och frågar de översta K mest "framträdande" dokumenten varje gång det anropas. Den här minnestypen spårar inte explicit ordningen för interaktioner utan använder vektorhämtning för att hämta relevanta minnen.
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 det här exemplet används VectorStoreRetrieverMemory för att lagra och hämta relevant information från en konversation baserat på vektorhämtning.
Du kan också använda VectorStoreRetrieverMemory i en kedja för konversationsbaserad kunskapshämtning, som visas i de tidigare exemplen.
Dessa olika minnestyper i Langchain ger olika sätt att hantera och hämta information från konversationer, vilket förbättrar AI-modellernas förmåga att förstå och svara på användarfrågor och sammanhang. Varje minnestyp kan väljas baserat på de specifika kraven för din applikation.
Nu ska vi lära oss hur man använder minne med en LLMChain. Minne i en LLMChain tillåter modellen att komma ihåg tidigare interaktioner och sammanhang för att ge mer sammanhängande och sammanhangsmedvetna svar.
För att ställa in minne i en LLMChain måste du skapa en minnesklass, till exempel ConversationBufferMemory. Så här kan du ställa in 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 det här exemplet används ConversationBufferMemory för att lagra konversationshistoriken. De memory_key
parametern anger nyckeln som används för att lagra konversationshistoriken.
Om du använder en chattmodell istället för en kompletteringsmodell kan du strukturera dina meddelanden annorlunda för att bättre utnyttja minnet. Här är ett exempel på hur man ställer in en chattmodellbaserad 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 det här exemplet används ChatPromptTemplate för att strukturera prompten, och ConversationBufferMemory används för att lagra och hämta konversationshistoriken. Detta tillvägagångssätt är särskilt användbart för chattliknande konversationer där sammanhang och historia spelar en avgörande roll.
Minne kan också läggas till i en kedja med flera ingångar, till exempel en fråga/svarskedja. Här är ett exempel på hur man ställer in minne i en fråga/svarskedja:
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 det här exemplet besvaras en fråga med ett dokument som är uppdelat i mindre bitar. ConversationBufferMemory används för att lagra och hämta konversationshistoriken, vilket gör att modellen kan ge kontextmedvetna svar.
Genom att lägga till minne till en agent kan den komma ihåg och använda tidigare interaktioner för att svara på frågor och ge sammanhangsmedvetna svar. Så här kan du ställa in 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 det här exemplet läggs minne till en agent, vilket gör att den kan komma ihåg den tidigare konversationshistoriken och ge kontextmedvetna svar. Detta gör det möjligt för agenten att svara på uppföljningsfrågor korrekt baserat på informationen som lagras i minnet.
LangChain Expression Language
I en värld av naturlig språkbehandling och maskininlärning kan det vara en skrämmande uppgift att komponera komplexa operationskedjor. Lyckligtvis kommer LangChain Expression Language (LCEL) till undsättning, vilket ger ett deklarativt och effektivt sätt att bygga och distribuera sofistikerade pipelines för språkbehandling. LCEL är designat för att förenkla processen att komponera kedjor, vilket gör det möjligt att gå från prototyp till produktion med lätthet. I den här bloggen kommer vi att utforska vad LCEL är och varför du kanske vill använda det, tillsammans med praktiska kodexempel för att illustrera dess möjligheter.
LCEL, eller LangChain Expression Language, är ett kraftfullt verktyg för att skapa språkbearbetningskedjor. Den var specialbyggd för att stödja övergången från prototyptillverkning till produktion sömlöst, utan att kräva omfattande kodändringar. Oavsett om du bygger en enkel "prompt + LLM"-kedja eller en komplex pipeline med hundratals steg, har LCEL dig täckt.
Här är några anledningar till att använda LCEL i dina språkbearbetningsprojekt:
- Snabb Token Streaming: LCEL levererar tokens från en språkmodell till en utdataparser i realtid, vilket förbättrar responsen och effektiviteten.
- Mångsidiga API:er: LCEL stöder både synkrona och asynkrona API:er för prototyp- och produktionsanvändning, och hanterar flera förfrågningar effektivt.
- Automatisk parallellisering: LCEL optimerar parallell exekvering när det är möjligt, vilket minskar latensen i både synk- och asynkrongränssnitt.
- Pålitliga konfigurationer: Konfigurera omförsök och reservdelar för ökad kedjetillförlitlighet i stor skala, med stöd för streaming under utveckling.
- Strömma mellanresultat: Få tillgång till mellanliggande resultat under bearbetning för användaruppdateringar eller felsökningsändamål.
- Schemagenerering: LCEL genererar Pydantic- och JSONSchema-scheman för in- och utvalidering.
- Omfattande spårning: LangSmith spårar automatiskt alla steg i komplexa kedjor för observerbarhet och felsökning.
- Enkel implementering: Implementera LCEL-skapade kedjor utan ansträngning med LangServe.
Låt oss nu dyka ner i praktiska kodexempel som visar kraften i LCEL. Vi kommer att utforska vanliga uppgifter och scenarier där LCEL lyser.
Uppmaning + LLM
Den mest grundläggande sammansättningen innebär att man kombinerar en prompt och en språkmodell för att skapa en kedja som tar användarinput, lägger till den i en prompt, skickar den till en modell och returnerar råmodellens utdata. Här är ett exempel:
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 det här exemplet genererar kedjan ett skämt om björnar.
Du kan bifoga stoppsekvenser till din kedja för att kontrollera hur den bearbetar text. Till exempel:
chain = prompt | model.bind(stop=["n"])
result = chain.invoke({"foo": "bears"})
print(result)
Denna konfiguration stoppar textgenereringen när ett nyradstecken påträffas.
LCEL stöder att bifoga information om funktionsanrop till din kedja. Här är ett exempel:
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)
Det här exemplet bifogar information om funktionsanrop för att skapa ett skämt.
Prompt + LLM + OutputParser
Du kan lägga till en utdataparser för att omvandla råmodellutdata till ett mer fungerande format. Så här kan du göra det:
from langchain.schema.output_parser import StrOutputParser chain = prompt | model | StrOutputParser()
result = chain.invoke({"foo": "bears"})
print(result)
Utdata är nu i ett strängformat, vilket är mer praktiskt för nedströmsuppgifter.
När du anger en funktion som ska returneras kan du analysera den direkt med LCEL. Till exempel:
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)
Det här exemplet analyserar utdata från "skämt"-funktionen direkt.
Det här är bara några exempel på hur LCEL förenklar komplexa språkbehandlingsuppgifter. Oavsett om du bygger chatbots, genererar innehåll eller utför komplexa texttransformationer kan LCEL effektivisera ditt arbetsflöde och göra din kod mer underhållbar.
RAG (Retrieval-augmented Generation)
LCEL kan användas för att skapa hämtningsförstärkta generationskedjor, som kombinerar hämtning och språkgenereringssteg. Här är ett exempel:
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 det här exemplet hämtar kedjan relevant information från sammanhanget och genererar ett svar på frågan.
Conversational Retrieval Chain
Du kan enkelt lägga till konversationshistorik i dina kedjor. Här är ett exempel på en samtalshämtningskedja:
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 detta exempel hanterar kedjan en följdfråga i ett samtalssammanhang.
Med minne och returnerande källdokument
LCEL stöder även minne och returnerande källdokument. Så här kan du använda minnet i en kedja:
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 det här exemplet används minnet för att lagra och hämta konversationshistorik och källdokument.
Flera kedjor
Du kan sätta ihop flera kedjor med Runnables. Här är ett exempel:
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 det här exemplet kombineras två kedjor för att generera information om en stad och dess land på ett specifikt språk.
Förgrening och sammanslagning
LCEL låter dig dela och slå samman kedjor med RunnableMaps. Här är ett exempel på förgrening och sammanslagning:
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 det här exemplet används en gren- och sammanslagningskedja för att generera ett argument och utvärdera dess för- och nackdelar innan ett slutgiltigt svar genereras.
Skriver Python-kod med LCEL
En av de kraftfulla tillämpningarna av LangChain Expression Language (LCEL) är att skriva Python-kod för att lösa användarproblem. Nedan är ett exempel på hur man använder LCEL för att skriva Python-kod:
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 det här exemplet ger en användare input och LCEL genererar Python-kod för att lösa problemet. Koden exekveras sedan med en Python REPL, och den resulterande Python-koden returneras i Markdown-format.
Observera att användning av en Python REPL kan exekvera godtycklig kod, så använd den med försiktighet.
Lägga till minne till en kedja
Minne är viktigt i många konversations-AI-applikationer. Så här lägger du till minne i en godtycklig kedja:
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 det här exemplet används minnet för att lagra och hämta konversationshistorik, vilket gör att chatboten kan behålla sitt sammanhang och svara på lämpligt sätt.
Använda externa verktyg med Runnables
LCEL låter dig sömlöst integrera externa verktyg med Runnables. Här är ett exempel med sökverktyget DuckDuckGo:
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.tools import DuckDuckGoSearchRun search = DuckDuckGoSearchRun() template = """Turn the following user input into a search query for a search engine: {input}"""
prompt = ChatPromptTemplate.from_template(template) model = ChatOpenAI() chain = prompt | model | StrOutputParser() | search search_result = chain.invoke({"input": "I'd like to figure out what games are tonight"})
print(search_result)
I det här exemplet integrerar LCEL sökverktyget DuckDuckGo i kedjan, vilket gör att det kan generera en sökfråga från användarinmatning och hämta sökresultat.
LCELs flexibilitet gör det enkelt att integrera olika externa verktyg och tjänster i dina språkbehandlingspipelines, vilket förbättrar deras kapacitet och funktionalitet.
Lägga till moderering till en LLM-applikation
För att säkerställa att din LLM-applikation följer innehållspolicyer och inkluderar modereringsskydd, kan du integrera modereringskontroller i din kedja. Så här lägger du till moderering med 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 det här exemplet är OpenAIModerationChain
används för att lägga till moderering till svaret som genereras av LLM. Modereringskedjan kontrollerar svaret för innehåll som bryter mot OpenAI:s innehållspolicy. Om några överträdelser hittas kommer den att flagga svaret i enlighet med detta.
Routing genom Semantic Similarity
LCEL låter dig implementera anpassad routinglogik baserat på den semantiska likheten hos användarinmatning. Här är ett exempel på hur man dynamiskt bestämmer kedjelogiken baserat på användarinmatning:
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 det här exemplet är prompt_router
funktionen beräknar cosinuslikheten mellan användarinmatning och fördefinierade promptmallar för fysik- och matematikfrågor. Baserat på likhetspoängen väljer kedjan dynamiskt den mest relevanta promptmallen, vilket säkerställer att chatboten svarar korrekt på användarens fråga.
Använda Agenter och Runnables
LangChain låter dig skapa agenter genom att kombinera Runnables, uppmaningar, modeller och verktyg. Här är ett exempel på hur man bygger en agent och använder 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 det här exemplet skapas en agent genom att kombinera en modell, verktyg, en prompt och en anpassad logik för mellansteg och verktygskonvertering. Agenten exekveras sedan och ger ett svar på användarens fråga.
Fråga efter en SQL-databas
Du kan använda LangChain för att fråga en SQL-databas och generera SQL-frågor baserat på användarfrågor. Här är ett exempel:
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 det här exemplet används LangChain för att generera SQL-frågor baserat på användarfrågor och hämta svar från en SQL-databas. Uppmaningarna och svaren är formaterade för att ge naturliga språkinteraktioner med databasen.
Automatisera manuella uppgifter och arbetsflöden med vår AI-drivna arbetsflödesbyggare, designad av Nanonets för dig och dina team.
LangServe & LangSmith
LangServe hjälper utvecklare att distribuera LangChain runnables och kedjor som ett REST API. Detta bibliotek är integrerat med FastAPI och använder pydantic för datavalidering. Dessutom tillhandahåller den en klient som kan användas för att anropa runnables som distribueras på en server, och en JavaScript-klient är tillgänglig i LangChainJS.
Funktioner
- Inmatnings- och utdatascheman härleds automatiskt från ditt LangChain-objekt och tillämpas på varje API-anrop, med omfattande felmeddelanden.
- En API-dokumentsida med JSONSchema och Swagger är tillgänglig.
- Effektiva /invoke-, /batch- och /stream-slutpunkter med stöd för många samtidiga förfrågningar på en enda server.
- /stream_log slutpunkt för att streama alla (eller några) mellansteg från din kedja/agent.
- Lekplatssida på /lekplats med strömmande utdata och mellansteg.
- Inbyggd (valfritt) spårning till LangSmith; lägg bara till din API-nyckel (se instruktioner).
- Allt byggt med stridstestade Python-bibliotek med öppen källkod som FastAPI, Pydantic, uvloop och asyncio.
Begränsningar
- Klientåteruppringningar stöds ännu inte för händelser som har sitt ursprung på servern.
- OpenAPI-dokument kommer inte att genereras när Pydantic V2 används. FastAPI stöder inte blandning av pydantic v1 och v2 namnrymder. Se avsnittet nedan för mer information.
Använd LangChain CLI för att starta ett LangServe-projekt snabbt. För att använda langchain CLI, se till att du har en senaste version av langchain-cli installerad. Du kan installera den med pip install -U langchain-cli.
langchain app new ../path/to/directory
Få din LangServe-instans igång snabbt med LangChain-mallar. För fler exempel, se mallindex eller exempelkatalogen.
Här är en server som distribuerar en OpenAI-chattmodell, en antropisk chattmodell och en kedja som använder den antropiska modellen för att berätta ett skämt om ett ämne.
#!/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 distribuerat servern ovan kan du se de genererade OpenAPI-dokumenten med:
curl localhost:8000/docs
Se till att lägga till suffixet /docs.
from langchain.schema import SystemMessage, HumanMessage
from langchain.prompts import ChatPromptTemplate
from langchain.schema.runnable import RunnableMap
from langserve import RemoteRunnable openai = RemoteRunnable("http://localhost:8000/openai/")
anthropic = RemoteRunnable("http://localhost:8000/anthropic/")
joke_chain = RemoteRunnable("http://localhost:8000/chain/") joke_chain.invoke({"topic": "parrots"}) # or async
await joke_chain.ainvoke({"topic": "parrots"}) prompt = [ SystemMessage(content='Act like either a cat or a parrot.'), HumanMessage(content='Hello!')
] # Supports astream
async for msg in anthropic.astream(prompt): print(msg, end="", flush=True) prompt = ChatPromptTemplate.from_messages( [("system", "Tell me a long story about {topic}")]
) # Can define custom chains
chain = prompt | RunnableMap({ "openai": openai, "anthropic": anthropic,
}) chain.batch([{ "topic": "parrots" }, { "topic": "cats" }])
I TypeScript (kräver LangChain.js version 0.0.166 eller senare):
import { RemoteRunnable } from "langchain/runnables/remote"; const chain = new RemoteRunnable({ url: `http://localhost:8000/chain/invoke/`,
});
const result = await chain.invoke({ topic: "cats",
});
Python använder förfrågningar:
import requests
response = requests.post( "http://localhost:8000/chain/invoke/", json={'input': {'topic': 'cats'}}
)
response.json()
Du kan också använda curl:
curl --location --request POST 'http://localhost:8000/chain/invoke/' --header 'Content-Type: application/json' --data-raw '{ "input": { "topic": "cats" } }'
Följande kod:
...
add_routes( app, runnable, path="/my_runnable",
)
lägger till dessa slutpunkter till servern:
- POST /my_runnable/invoke – anropa den körbara på en enda ingång
- POST /my_runnable/batch – anropa den körbara på en batch av ingångar
- POST /my_runnable/stream – anropa på en enda ingång och streama utdata
- POST /my_runnable/stream_log – anropa på en enda ingång och streama utdata, inklusive utdata av mellansteg när den genereras
- GET /my_runnable/input_schema – json-schema för indata till det körbara
- GET /my_runnable/output_schema – json-schema för utdata av den körbara
- GET /my_runnable/config_schema – json-schema för konfiguration av det körbara
Du kan hitta en lekplatssida för din runnable på /my_runnable/playground. Detta exponerar ett enkelt användargränssnitt för att konfigurera och anropa din körbara med strömmande utdata och mellansteg.
För både klient och server:
pip install "langserve[all]"
eller pipinstallera "langserve[client]" för klientkod, och pipinstallera "langserve[server]" för serverkod.
Om du behöver lägga till autentisering till din server, vänligen referera till FastAPI:s säkerhetsdokumentation och mellanprogram.
Du kan distribuera till GCP Cloud Run med följande kommando:
gcloud run deploy [your-service-name] --source . --port 8001 --allow-unauthenticated --region us-central1 --set-env-vars=OPENAI_API_KEY=your_key
LangServe ger stöd för Pydantic 2 med vissa begränsningar. OpenAPI-dokument kommer inte att genereras för invoke/batch/stream/stream_log när Pydantic V2 används. Fast API stöder inte blandning av pydantic v1 och v2 namnrymder. LangChain använder v1-namnrymden i Pydantic v2. Läs följande riktlinjer för att säkerställa kompatibilitet med LangChain. Förutom dessa begränsningar förväntar vi oss att API-slutpunkterna, lekplatsen och alla andra funktioner fungerar som förväntat.
LLM-applikationer hanterar ofta filer. Det finns olika arkitekturer som kan göras för att implementera filbehandling; på hög nivå:
- Filen kan laddas upp till servern via en dedikerad slutpunkt och bearbetas med en separat slutpunkt.
- Filen kan laddas upp med antingen värde (filbyte) eller referens (t.ex. s3-url till filinnehåll).
- Bearbetningsslutpunkten kan vara blockerande eller icke-blockerande.
- Om betydande bearbetning krävs, kan bearbetningen överföras till en dedikerad processpool.
Du bör bestämma vilken arkitektur som är lämplig för din applikation. För närvarande, för att ladda upp filer efter värde till en körbar, använd base64-kodning för filen (multipart/form-data stöds inte ännu).
Här är en exempel som visar hur man använder base64-kodning för att skicka en fil till en fjärrkörbar. Kom ihåg att du alltid kan ladda upp filer genom referens (t.ex. s3 url) eller ladda upp dem som multipart/form-data till en dedikerad slutpunkt.
Ingångs- och utgångstyper är definierade på alla körbara enheter. Du kan komma åt dem via egenskaperna input_schema och output_schema. LangServe använder dessa typer för validering och dokumentation. Om du vill åsidosätta standardtyperna kan du använda metoden with_types.
Här är ett leksaksexempel för att illustrera idén:
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)
Ärv från CustomUserType om du vill att data ska deserialiseras till en pydantisk modell snarare än motsvarande dict-representation. För närvarande fungerar denna typ bara på serversidan och används för att specificera önskat avkodningsbeteende. Om den ärver från denna typ kommer servern att behålla den avkodade typen som en pydantisk modell istället för att konvertera den till 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")
Lekplatsen låter dig definiera anpassade widgets för din körbara från backend. En widget specificeras på fältnivå och skickas som en del av JSON-schemat för inmatningstypen. En widget måste innehålla en nyckel som kallas typ med värdet som ett av en välkänd lista med widgets. Andra widgetnycklar kommer att associeras med värden som beskriver sökvägar i ett JSON-objekt.
Allmänt schema:
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;
};
Tillåter att en filuppladdningsingång skapas i UI-lekplatsen för filer som laddas upp som base64-kodade strängar. Här är det fullständiga exemplet.
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
Automatisera manuella uppgifter och arbetsflöden med vår AI-drivna arbetsflödesbyggare, designad av Nanonets för dig och dina team.
Introduktion till LangSmith
LangChain gör det enkelt att prototyper av LLM-applikationer och agenter. Det kan dock vara bedrägligt svårt att leverera LLM-applikationer till produktionen. Du kommer sannolikt att behöva anpassa och upprepa dina meddelanden, kedjor och andra komponenter för att skapa en högkvalitativ produkt.
För att underlätta denna process introducerades LangSmith, en enhetlig plattform för felsökning, testning och övervakning av dina LLM-applikationer.
När kan detta komma till användning? Du kanske tycker att det är användbart när du snabbt vill felsöka en ny kedja, agent eller uppsättning verktyg, visualisera hur komponenter (kedjor, llms, retrievers, etc.) relaterar och används, utvärdera olika uppmaningar och LLM:er för en enskild komponent, kör en given kedja flera gånger över en datamängd för att säkerställa att den konsekvent uppfyller en kvalitetsindikator, eller fånga användningsspår och använd LLM:er eller analyspipelines för att generera insikter.
Förkunskaper:
- Skapa ett LangSmith-konto och skapa en API-nyckel (se nedre vänstra hörnet).
- Bekanta dig med plattformen genom att titta igenom dokumenten.
Låt oss komma igång!
Konfigurera först dina miljövariabler för att tala om för LangChain att logga spår. Detta görs genom att sätta miljövariabeln LANGCHAIN_TRACING_V2 till true. Du kan tala om för LangChain vilket projekt som ska loggas till genom att ställa in miljövariabeln LANGCHAIN_PROJECT (om detta inte är inställt kommer körningar att loggas till standardprojektet). Detta kommer automatiskt att skapa projektet åt dig om det inte finns. Du måste också ställa in miljövariablerna LANGCHAIN_ENDPOINT och LANGCHAIN_API_KEY.
OBS: Du kan också använda en kontexthanterare i python för att logga spår med:
from langchain.callbacks.manager import tracing_v2_enabled with tracing_v2_enabled(project_name="My Project"): agent.run("How many people live in canada as of 2023?")
Men i det här exemplet kommer vi att använda 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>"
Skapa LangSmith-klienten för att interagera med API:t:
from langsmith import Client client = Client()
Skapa en LangChain-komponent och logga körningar till plattformen. I det här exemplet kommer vi att skapa en agent i ReAct-stil med tillgång till ett allmänt sökverktyg (DuckDuckGo). Agentens uppmaning kan ses i navet här:
from langchain import hub
from langchain.agents import AgentExecutor
from langchain.agents.format_scratchpad import format_to_openai_function_messages
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser
from langchain.chat_models import ChatOpenAI
from langchain.tools import DuckDuckGoSearchResults
from langchain.tools.render import format_tool_to_openai_function # Fetches the latest version of this prompt
prompt = hub.pull("wfh/langsmith-agent-prompt:latest") llm = ChatOpenAI( model="gpt-3.5-turbo-16k", temperature=0,
) tools = [ DuckDuckGoSearchResults( name="duck_duck_go" ), # General internet search using DuckDuckGo
] llm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools]) runnable_agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai_function_messages( x["intermediate_steps"] ), } | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser()
) agent_executor = AgentExecutor( agent=runnable_agent, tools=tools, handle_parsing_errors=True
)
Vi kör agenten samtidigt på flera ingångar för att minska latensen. Körningar loggas till LangSmith i bakgrunden, så körfördröjningen påverkas inte:
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]
Förutsatt att du har konfigurerat din miljö framgångsrikt, bör dina agentspår visas i avsnittet Projekt i appen. grattis!
Det verkar dock som om agenten inte effektivt använder verktygen. Låt oss utvärdera detta så att vi har en baslinje.
Förutom att logga körningar låter LangSmith dig också testa och utvärdera dina LLM-applikationer.
I det här avsnittet kommer du att använda LangSmith för att skapa en benchmarkdatauppsättning och köra AI-assisterade utvärderare på en agent. Du kommer att göra det i några steg:
- Skapa en LangSmith-datauppsättning:
Nedan använder vi LangSmith-klienten för att skapa en datauppsättning från ingångsfrågorna från ovan och en listaetikett. Du kommer att använda dessa senare för att mäta prestanda för en ny agent. En datauppsättning är en samling exempel, som inte är något annat än input-output-par som du kan använda som testfall för din applikation:
outputs = [ "LangChain is an open-source framework for building applications using large language models. It is also the name of the company building LangSmith.", "LangSmith is a unified platform for debugging, testing, and monitoring language model applications and agents powered by LangChain", "July 18, 2023", "The langsmith cookbook is a github repository containing detailed examples of how to use LangSmith to debug, evaluate, and monitor large language model-powered applications.", "September 5, 2023",
] dataset_name = f"agent-qa-{unique_id}" dataset = client.create_dataset( dataset_name, description="An example dataset of questions over the LangSmith documentation.",
) for query, answer in zip(inputs, outputs): client.create_example( inputs={"input": query}, outputs={"output": answer}, dataset_id=dataset.id )
- Initiera en ny agent för att benchmarka:
LangSmith låter dig utvärdera alla LLM, kedja, agenter eller till och med en anpassad funktion. Konversationsagenter är tillståndsfulla (de har minne); för att säkerställa att detta tillstånd inte delas mellan datauppsättningskörningar kommer vi att skicka i en chain_factory (
aka en konstruktor) funktion för att initiera för varje anrop:
# 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)
- Konfigurera utvärdering:
Att manuellt jämföra resultaten av kedjor i användargränssnittet är effektivt, men det kan vara tidskrävande. Det kan vara bra att använda automatiserade mätvärden och AI-assisterad feedback för att utvärdera din komponents prestanda:
from langchain.evaluation import EvaluatorType
from langchain.smith import RunEvalConfig evaluation_config = RunEvalConfig( evaluators=[ EvaluatorType.QA, EvaluatorType.EMBEDDING_DISTANCE, RunEvalConfig.LabeledCriteria("helpfulness"), RunEvalConfig.LabeledScoreString( { "accuracy": """
Score 1: The answer is completely unrelated to the reference.
Score 3: The answer has minor relevance but does not align with the reference.
Score 5: The answer has moderate relevance but contains inaccuracies.
Score 7: The answer aligns with the reference but has minor errors or omissions.
Score 10: The answer is completely accurate and aligns perfectly with the reference.""" }, normalize_by=10, ), ], custom_evaluators=[],
)
- Kör agenten och utvärderarna:
Använd funktionen run_on_dataset (eller asynkron arun_on_dataset) för att utvärdera din modell. Det här kommer att:
- Hämta exempelrader från den angivna datamängden.
- Kör din agent (eller någon anpassad funktion) på varje exempel.
- Tillämpa utvärderare på de resulterande körspåren och motsvarande referensexempel för att generera automatisk feedback.
Resultaten kommer att synas i LangSmith-appen:
chain_results = run_on_dataset( dataset_name=dataset_name, llm_or_chain_factory=functools.partial(agent_factory, prompt=prompt), evaluation=evaluation_config, verbose=True, client=client, project_name=f"runnable-agent-test-5d466cbc-{unique_id}", tags=[ "testing-notebook", "prompt:5d466cbc", ],
)
Nu när vi har våra testkörningsresultat kan vi göra ändringar i vår agent och jämföra dem. Låt oss försöka igen med en annan prompt och se resultatet:
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 låter dig exportera data till vanliga format som CSV eller JSONL direkt i webbappen. Du kan också använda klienten för att hämta körningar för vidare analys, för att lagra i din egen databas eller för att dela med andra. Låt oss hämta körspåren från utvärderingskörningen:
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
Det här var en snabbguide för att komma igång, men det finns många fler sätt att använda LangSmith för att påskynda ditt utvecklarflöde och ge bättre resultat.
För mer information om hur du kan få ut det mesta av LangSmith, kolla in LangSmith-dokumentationen.
Gå upp i nivå med Nanonets
Även om LangChain är ett värdefullt verktyg för att integrera språkmodeller (LLM) med dina applikationer, kan det möta begränsningar när det kommer till företagsanvändningsfall. Låt oss utforska hur Nanonets går bortom LangChain för att hantera dessa utmaningar:
1. Omfattande dataanslutning:
LangChain erbjuder kontakter, men det kanske inte täcker alla arbetsplatsappar och dataformat som företag förlitar sig på. Nanonets tillhandahåller dataanslutningar för över 100 allmänt använda arbetsplatsappar, inklusive Slack, Notion, Google Suite, Salesforce, Zendesk och många fler. Den stöder också alla ostrukturerade datatyper som PDF-filer, TXT-filer, bilder, ljudfiler och videofiler, såväl som strukturerade datatyper som CSV-filer, kalkylblad, MongoDB och SQL-databaser.
2. Uppgiftsautomatisering för Workspace-appar:
Medan text/svarsgenerering fungerar utmärkt, är LangChains möjligheter begränsade när det gäller att använda naturligt språk för att utföra uppgifter i olika applikationer. Nanonets erbjuder utlösare/åtgärdsagenter för de mest populära arbetsplatsapparna, så att du kan ställa in arbetsflöden som lyssnar efter händelser och utför åtgärder. Du kan till exempel automatisera e-postsvar, CRM-poster, SQL-frågor och mer, allt med kommandon på naturliga språk.
3. Datasynkronisering i realtid:
LangChain hämtar statisk data med dataanslutningar, som kanske inte hänger med i dataändringar i källdatabasen. Däremot säkerställer Nanonets realtidssynkronisering med datakällor, vilket säkerställer att du alltid arbetar med den senaste informationen.
3. Förenklad konfiguration:
Att konfigurera elementen i LangChain pipeline, såsom retrievers och synthesizers, kan vara en komplex och tidskrävande process. Nanonets effektiviserar detta genom att tillhandahålla optimerad dataintag och indexering för varje datatyp, allt hanterat i bakgrunden av AI Assistant. Detta minskar bördan av finjustering och gör det lättare att installera och använda.
4. Enhetlig lösning:
Till skillnad från LangChain, som kan kräva unika implementeringar för varje uppgift, fungerar Nanonets som en enda lösning för att koppla ihop din data med LLM. Oavsett om du behöver skapa LLM-applikationer eller AI-arbetsflöden erbjuder Nanonets en enhetlig plattform för dina olika behov.
Nanonets AI-arbetsflöden
Nanonets Workflows är en säker, multifunktionell AI-assistent som förenklar integrationen av din kunskap och data med LLM:er och underlättar skapandet av kodfria applikationer och arbetsflöden. Det erbjuder ett lättanvänt användargränssnitt, vilket gör det tillgängligt för både individer och organisationer.
För att komma igång kan du boka ett samtal med en av våra AI-experter, som kan ge en personlig demo och testversion av Nanonets Workflows skräddarsydda för ditt specifika användningsfall.
När du väl har ställt in dig kan du använda naturligt språk för att designa och köra komplexa applikationer och arbetsflöden som drivs av LLM, och integreras sömlöst med dina appar och data.
Överladda dina team med Nanonets AI för att skapa appar och integrera din data med AI-drivna applikationer och arbetsflöden, så att dina team kan fokusera på det som verkligen betyder något.
Automatisera manuella uppgifter och arbetsflöden med vår AI-drivna arbetsflödesbyggare, designad av Nanonets för dig och dina team.
- SEO-drivet innehåll och PR-distribution. Bli förstärkt idag.
- PlatoData.Network Vertical Generative Ai. Styrka dig själv. Tillgång här.
- PlatoAiStream. Web3 Intelligence. Kunskap förstärkt. Tillgång här.
- Platoesg. Kol, CleanTech, Energi, Miljö, Sol, Avfallshantering. Tillgång här.
- PlatoHealth. Biotech och kliniska prövningar Intelligence. Tillgång här.
- Källa: https://nanonets.com/blog/langchain/
- : har
- :är
- :inte
- :var
- $UPP
- 1
- 10
- 100
- 114
- 13
- 15%
- 2000
- 2012
- 2023
- 25
- 30
- 32
- 36
- 40
- 400
- 408
- 50
- 500
- 7
- 8
- a
- ABC
- förmåga
- Able
- Om oss
- om det
- ovan
- Acceptera
- accepterar
- tillgång
- tillgänglig
- åtkomst
- åstadkomma
- i enlighet med detta
- Konto
- noggrannhet
- exakt
- exakt
- Uppnå
- uppnås
- uppnår
- tvärs
- Agera
- Handling
- åtgärder
- aktiv
- anpassning
- adaptiv
- lägga till
- lagt till
- tillsats
- Dessutom
- Annat
- Dessutom
- adress
- Lägger
- erkänna
- avancerat
- Äventyr
- Efter
- igen
- ålder
- Recensioner
- medel
- AI
- AI-assistent
- AI-modeller
- Stöd
- sikta
- algoritmer
- rikta
- Justerar
- Alla
- tillåter
- tillåta
- tillåter
- ensam
- längs
- vid sidan av
- redan
- också
- Även
- alltid
- an
- analys
- Analytisk
- analytics
- och
- Angeles
- Meddela
- årsringar
- Annan
- svara
- svar
- hymn
- Antropisk
- vilken som helst
- något
- api
- API-NYCKLAR
- API: er
- app
- tillämplig
- Ansökan
- Application Development
- tillämpningar
- tillämpas
- applicerar
- tillvägagångssätt
- tillvägagångssätt
- lämpligt
- lämpligt
- appar
- arkitektur
- ÄR
- Argumentet
- argument
- Armstrong
- runt
- array
- Artister
- AS
- be
- aspekt
- aspekter
- bistå
- Assistent
- associerad
- At
- bifoga
- uppmärksamhet
- audio
- augmented
- Autentisering
- automatisera
- Automatiserad
- automatiserar
- automatiskt
- Automation
- tillgänglig
- genomsnitt
- vänta
- medveten
- AWS
- tillbaka
- Backbone
- backend
- bakgrund
- dåligt
- Balansera
- bar
- bas
- baserat
- Baslinje
- bash
- grundläggande
- Grunderna
- BCG
- BE
- Beach
- bears
- därför att
- varit
- innan
- börja
- beteende
- bakom
- bakom kulisserna
- Där vi får lov att vara utan att konstant prestera,
- nedan
- riktmärke
- fördelaktigt
- BÄST
- Bättre
- mellan
- Bortom
- störst
- Bill
- Bill Gates
- binda
- bing
- Bit
- Svart
- Black Hole
- Blockera
- blockering
- Block
- Blogg
- bob
- Bootstrap
- födda
- Bot
- båda
- Botten
- Branch
- Ha sönder
- vind
- i korthet
- bredare
- brun
- webbläsare
- buffert
- SLUTRESULTAT
- byggare
- Byggnad
- byggt
- belastning
- företag
- men
- by
- beräkna
- beräknar
- beräkning
- beräkning
- Ring
- återanrop
- kallas
- anropande
- Samtal
- KAN
- Kan få
- Kanada
- kapacitet
- kapabel
- Kapacitet
- fånga
- Fångande
- Vid
- fall
- KATT
- tillgodose
- catering
- tillgodoser
- Katter
- försiktighet
- försiktig
- centrerad
- vissa
- kedja
- kedjor
- utmaningar
- Förändringar
- karaktär
- chatbot
- chatbots
- ta
- Kontroller
- Välja
- valda
- omständigheter
- Stad
- klass
- klasser
- klient
- cloud
- koda
- Kodning
- Kaffe
- SAMMANHÄNGANDE
- sammanhängande
- samarbeta
- Collapse
- samling
- färgstarka
- Kolumn
- Kolonner
- COM
- kombinera
- kombinerad
- kombinerar
- kombinera
- komma
- kommer
- bekväm
- Gemensam
- Kommunikation
- företag
- jämföra
- jämförande
- kompatibilitet
- kompatibel
- fullborda
- fullständigt
- fullbordan
- komplex
- komplexiteter
- komponent
- komponenter
- sammansatt
- sammansättning
- omfattande
- innefattande
- begrepp
- koncis
- konkurrent
- tillstånd
- konfiguration
- konfluens
- Kontakta
- Anslutning
- Anslutningar
- Nackdelar
- Tänk
- konsekvent
- består
- Konsol
- ständigt
- konstrukt
- innehålla
- innehåller
- innehåll
- sammanhang
- kontexter
- kontextuella
- fortsätta
- kontinuerligt
- Däremot
- kontroll
- kontroller
- Bekväm
- Konversation
- konversera
- konversations AI
- konversationer
- Konvertering
- konverterad
- omvandling
- Kärna
- Corner
- korrekt
- Motsvarande
- kunde
- räkna
- land
- Par
- täcka
- omfattas
- skapa
- skapas
- skapar
- Skapa
- skapande
- referenser
- kriterier
- Kritiker
- CRM
- avgörande
- Aktuella
- För närvarande
- beställnings
- Kunder
- anpassning
- skräddarsy
- kundanpassad
- allra senaste
- datum
- Datastruktur
- Databas
- databaser
- Datum
- datum Tid
- behandla
- som handlar om
- December
- beslutar
- Avgörande
- Beslutsfattande
- avkodning
- dedicerad
- djupare
- Standard
- definiera
- definierade
- definierande
- definitioner
- leverera
- levererar
- gräva
- demo
- demonstrera
- demonstreras
- demonstrera
- bero
- beroende
- beror
- distribuera
- utplacerade
- utplacera
- utplacering
- vecklas ut
- beskriva
- beskrivning
- Designa
- betecknad
- utformade
- önskas
- detalj
- detaljerad
- detaljer
- Bestämma
- bestämd
- utveckla
- Utvecklare
- utvecklare
- utveckla
- Utveckling
- diagrammen
- DICT
- DID
- skilja sig
- olika
- annorlunda
- svårt
- Dimensionera
- dimensioner
- direktiv
- direkt
- diskutera
- diskuteras
- visning
- distinkt
- Dyk
- flera
- DM
- do
- dokumentera
- dokumentation
- dokument
- gör
- doesn
- gör
- donation
- gjort
- dubbla
- ner
- ladda ner
- Nedladdningar
- utkast
- driv
- grund
- under
- dynamisk
- dynamiskt
- e
- varje
- Tidigare
- Tidig
- lätta
- enkel användning
- lättare
- lätt
- lätt
- LÄTTANVÄND
- missar
- ekosystemet
- Effektiv
- effektivt
- effektivitet
- effektiv
- effektivt
- enkelt
- antingen
- elementet
- element
- Elon
- Elon Musk
- annars
- embed
- inbäddade
- inbäddning
- anställd
- anställda
- sysselsätter
- ge
- möjliggöra
- möjliggör
- möjliggör
- inkapsling
- möter
- början till slut
- Slutpunkt
- engagerande
- Motor
- Motorer
- England
- Engelska
- Engelska Premier League
- förbättra
- förbättrad
- förbättra
- säkerställa
- säkerställer
- säkerställa
- Företag
- enheter
- enhet
- Miljö
- miljöer
- Motsvarande
- Era
- fel
- fel
- speciellt
- väsentlig
- främmande
- etc
- utvärdera
- utvärdering
- Även
- händelser
- Varje
- exempel
- exempel
- överstiga
- Utom
- exekvera
- exekveras
- Utför
- exekvera
- utförande
- exemplifierar
- Motionera
- existerar
- förvänta
- förväntningar
- förväntat
- förväntar
- erfarenhet
- experimentell
- experter
- förklarade
- Förklarar
- uttryckligen
- utforskning
- utforska
- utforskas
- export
- Uttrycket
- förlänga
- sträcker
- omfattande
- extern
- extra
- extrahera
- extraktion
- extrakt
- Ansikte
- främja
- underlättar
- fabrik
- fakta
- långt
- SNABB
- Favoriten
- Leverans
- Funktioner
- återkoppling
- få
- fält
- Fält
- Figma
- Figur
- Fil
- Filer
- fylla
- fyllda
- fyllning
- filtrera
- filtrering
- slutlig
- Slutligen
- hitta
- finna
- Förnamn
- fem
- Flexibilitet
- flexibel
- flöda
- Fokus
- fokuserade
- fokuserar
- fokusering
- följer
- efter
- följer
- livsmedelsproduktion
- För
- formen
- format
- bildad
- Lyckligtvis
- hittade
- Ramverk
- ramar
- ofta
- vän
- vänner
- från
- full
- fullfjädrad
- fungera
- funktionaliteter
- funktionalitet
- funktioner
- grundläggande
- rolig
- ytterligare
- framtida
- Få
- Games
- grindar
- Allmänt
- allmänhet
- generera
- genereras
- genererar
- generera
- generering
- snäll
- Tyskland
- skaffa sig
- få
- gif
- GitHub
- ges
- GMT
- Go
- Går
- kommer
- god
- grynig
- diagram
- stor
- större
- vägleda
- styra
- riktlinjer
- hackathon
- hantera
- Handtag
- Arbetsmiljö
- praktisk
- Hård
- skada
- selar
- Har
- har
- kraftigt
- Held
- hjälpa
- hjälp
- hjälper
- här
- här.
- hi
- Hög
- högnivå
- hög kvalitet
- högsta
- höggradigt
- historisk
- historia
- Hål
- huva
- värd
- Hur ser din drömresa ut
- How To
- Men
- html
- http
- HTTPS
- Nav
- humant
- Hundratals
- i
- ID
- Tanken
- idealisk
- ids
- if
- ii
- iii
- illustrera
- illustrerar
- bilder
- omedelbar
- genomföra
- genomförande
- implementeringar
- genomföras
- importera
- förbättringar
- förbättra
- in
- djupgående
- innefattar
- ingår
- innefattar
- Inklusive
- införliva
- införlivande
- oerhört
- index
- index
- indikerar
- pekar på
- Individuellt
- individer
- informationen
- inledande
- initiera
- innovativa
- ingång
- ingångar
- insikter
- installera
- installerad
- installera
- exempel
- omedelbar
- istället
- instruktioner
- integrerad
- integrera
- integrerade
- integrerar
- Integrera
- integrering
- integrationer
- Intelligent
- avsedd
- interagera
- interaktion
- interaktioner
- interaktiva
- interagerar
- Gränssnitt
- gränssnitt
- invändigt
- Internet
- in
- introducerade
- Introducerar
- intuitiv
- involverar
- isn
- fråga
- problem
- IT
- artikel
- iterationer
- DESS
- sig
- Jackson
- JavaScript
- Jobb
- Jordanien
- resa
- json
- Juli
- bara
- Rättvisa
- Ha kvar
- håller
- Nyckel
- nycklar
- Snäll
- Vet
- kunskap
- Kunskap Diagram
- känd
- etikett
- Etiketter
- land
- språk
- Språk
- Large
- större
- Efternamn
- Latens
- senare
- senaste
- League
- LÄRA SIG
- inlärning
- vänster
- Legacy
- Längd
- mindre
- Låt
- Lets
- brev
- Nivå
- nivåer
- Hävstång
- hävstångs
- hävstångs
- bibliotek
- Bibliotek
- tycka om
- sannolikt
- BEGRÄNSA
- begränsningar
- Begränsad
- begränsande
- gränser
- länkar
- Lista
- lyssna
- listor
- lever
- ll
- LLM
- läsa in
- Lastaren
- belägen
- läge
- log
- inloggad
- skogsavverkning
- Logiken
- Lång
- längre
- se
- du letar
- UTSEENDE
- slå upp
- den
- Los Angeles
- Låg
- Maskinen
- maskininlärning
- gjord
- bibehålla
- Underhållbar
- upprätthålla
- upprätthåller
- göra
- GÖR
- Framställning
- hantera
- ledning
- chef
- hantera
- manchester
- Manchester United
- Manipulation
- sätt
- manuell
- Tillverkare
- många
- många människor
- karta
- kartläggning
- kartor
- Match
- matchande
- matte
- matematisk
- Betyder Något
- maximal
- Maj..
- me
- betyda
- betyder
- betyder
- mäta
- Media
- möte
- möter
- Minnen
- Minne
- nämnts
- Sammanfoga
- sammanslagning
- meddelande
- meddelanden
- meddelandehantering
- metadata
- metod
- metoder
- Metrics
- kanske
- miljoner
- minimum
- mindre
- saknas
- misstag
- Blandning
- MLB
- Mobil
- modell
- modeller
- måttfullhet
- Modulerna
- Moduler
- ögonblick
- MongoDB
- Övervaka
- övervakning
- Månen
- mer
- mest
- Mest populär
- flytta
- film
- mycket
- multipel
- flera kedjor
- Mysk
- måste
- my
- namn
- Som heter
- namn
- nationell
- Natural
- Naturlig språkbehandling
- Navigera
- navigerande
- Nära
- nödvändigt för
- Behöver
- behövs
- behov
- negativ
- Nya
- New York
- New York Times
- Nästa
- Nej
- Ingen
- inget
- Begrepp
- nu
- antal
- Obama
- objektet
- mål
- objekt
- observationen
- få
- erhållande
- OCR
- of
- erbjudanden
- erbjuda
- Erbjudanden
- Ofta
- oh
- Okej
- OS
- on
- gång
- ONE
- endast
- öppen källkod
- OpenAI
- Verksamhet
- Operatören
- optimerad
- optimerar
- Alternativet
- or
- beställa
- ekologisk
- organisationer
- ursprungliga
- OS
- Övriga
- Övrigt
- annat
- vår
- ut
- produktion
- utgångar
- över
- åsidosätta
- Översikt
- egen
- paket
- paket
- sida
- sidor
- par
- pandor
- Papper
- Parallell
- parameter
- parametrar
- Park
- del
- särskilt
- reservdelar till din klassiker
- passera
- Godkänd
- passerar
- Förbi
- Tidigare
- bana
- banor
- mönster
- Lön
- Personer
- för
- perfekt
- perfekt
- Utföra
- prestanda
- utför
- utför
- behörigheter
- persistens
- personen
- personlig
- perspektiv
- Fysik
- bit
- rörledning
- Pizza
- platshållare
- plattform
- plato
- Platon Data Intelligence
- PlatonData
- Spela
- lekplats
- spelar
- snälla du
- plus
- Punkt
- Strategier
- policy
- politiska
- poolen
- Populära
- befolkad
- positiv
- möjlig
- Inlägg
- inlägg
- potentiell
- kraft
- drivs
- den mäktigaste
- Praktisk
- praktiken
- föredra
- Premier
- presentera
- VD
- förhindra
- förebyggande
- föregående
- primärt
- primär
- Prime
- privat
- Problem
- problem
- Fortsätt
- process
- Bearbetad
- processer
- bearbetning
- producera
- Produkt
- Produktion
- Professor
- Programmering
- programmeringsspråk
- projektet
- projekt
- egenskaper
- egenskapen
- PROS
- Prototypen
- prototyping
- ge
- förutsatt
- leverantör
- leverantörer
- ger
- tillhandahålla
- allmän
- Syftet
- syfte
- sätta
- Python
- Frågor och svar
- kvalitet
- sökfrågor
- fråga
- frågor
- Snabbt
- snabbt
- citat
- R
- höja
- område
- som sträcker sig
- snarare
- betyg
- Raw
- RE
- nå
- Reagera
- Läsa
- Läsning
- redo
- verklig
- realtid
- data i realtid
- rike
- Anledningen
- skäl
- senaste
- rekommenderas
- registreras
- register
- Recover
- minska
- minskar
- reducerande
- reduktion
- referens
- erat
- förfina
- raffinering
- regioner
- Förhållanden
- frigörs
- relevans
- relevanta
- tillförlitlighet
- pålitlig
- förlita
- förlita
- resterna
- ihåg
- påminnelse
- avlägsen
- ger
- upprepa
- UPPREPAT
- omformulering
- ersätta
- rapport
- Repository
- representation
- representerar
- representerar
- begära
- förfrågningar
- kräver
- Obligatorisk
- Krav
- Kräver
- rädda
- forskning
- Lös
- resurs
- Svara
- reagera
- respons
- svar
- ansvarig
- mottaglig
- REST
- resultera
- resulterande
- Resultat
- kvarhållande
- retentionstid
- avkastning
- tillbaka
- återgår
- återanvändbar
- översyn
- kretsar
- Ris
- Rik
- robotar
- Roll
- roller
- rot
- routing
- RAD
- Körning
- rinnande
- kör
- runtime
- s
- skyddsåtgärder
- försäljning
- Salesforce
- Sam
- Samma
- Save
- säga
- säger
- skalbar
- Skala
- scenario
- scenarier
- scener
- tidtabellen
- göra
- repa
- sömlös
- sömlöst
- Sök
- sökmotor
- sök
- söka
- §
- sektioner
- säkra
- säkerhet
- se
- vald
- Val
- Försäljningen
- sända
- känslig
- känsla
- känslor
- separat
- September
- Sekvens
- Serier
- tjänar
- server
- serverar
- Tjänster
- in
- uppsättningar
- inställning
- inställningar
- inställning
- sju
- flera
- Dela
- delas
- Shell
- skiner
- skeppas
- skall
- show
- visa
- visas
- Visar
- Sigma
- signifikant
- liknande
- Enkelt
- förenklade
- förenkla
- förenkla
- helt enkelt
- eftersom
- enda
- Storlek
- slak
- Small
- mindre
- smarta
- kodavsnitt
- So
- än så länge
- Fotboll
- Social hållbarhet
- sociala medier
- Sociala medier inlägg
- enbart
- fast
- lösning
- LÖSA
- några
- något
- ibland
- sofistikerade
- ljud
- Källa
- Källor
- Utrymme
- spanska
- specialiserad
- specifik
- specifikt
- detaljer
- specificerade
- fart
- spent
- delas
- Delar upp
- Sporter
- kvadrat
- stå
- fristående
- standard
- starta
- igång
- Starta
- Ange
- uttalanden
- statisk
- Steg
- Steg
- Fortfarande
- Sluta
- stoppa
- Stoppar
- förvaring
- lagra
- lagras
- lagrar
- misslyckande
- Historia
- okomplicerad
- ström
- streaming
- effektivisera
- strömlinjeformad
- styrkor
- Strejker
- Sträng
- struktur
- strukturerade
- strukturer
- strukturering
- stil
- ämne
- senare
- Framgångsrikt
- sådana
- följer
- lämplig
- svit
- sammanfatta
- SAMMANFATTNING
- Sunset
- stödja
- Som stöds
- Stöder
- säker
- Hållbarhet
- synkronisering
- synopsis
- syntax
- system
- System
- bord
- skräddarsydd
- skräddarsydd
- Ta
- tar
- mål
- uppgift
- uppgifter
- grupp
- lag
- tala
- mall
- mallar
- terminal
- terminologi
- villkor
- testa
- Testning
- text
- än
- Tack
- den där
- Smakämnen
- Grunderna
- navet
- den information
- The New York Times
- Projekten
- källan
- världen
- deras
- Dem
- sedan
- Där.
- Dessa
- de
- saker
- detta
- de
- fastän?
- Genom
- hela
- tid
- tidskrävande
- gånger
- Titel
- till
- tillsammans
- token
- tokenization
- tokens
- alltför
- verktyg
- toolkit
- verktyg
- topp
- ämne
- ämnen
- Totalt
- stan
- spåra
- spår
- traditionell
- Utbildning
- Förvandla
- transformationer
- transformator
- transformatorer
- övergång
- rättegång
- sann
- verkligen
- prova
- trimma
- SVÄNG
- Vrida
- handledning
- Dubbelt
- två
- Typ
- typer
- skrivmaskin
- typiskt
- ui
- Ytterst
- opåverkad
- under
- underliggande
- förstå
- förståelse
- förstår
- enhetlig
- unika
- United
- Universell
- till skillnad från
- tills
- Uppdatering
- Uppdateringar
- uppladdad
- URL
- us
- användbarhet
- Användning
- användning
- användningsfall
- Begagnade
- Användare
- Användargränssnitt
- användare
- användningar
- med hjälp av
- verktyg
- utnyttja
- utnyttjas
- Återvinnare
- Använda
- v1
- godkännande
- validator
- Värdefulla
- värde
- Värden
- variabel
- mängd
- olika
- Ve
- mångsidig
- version
- mycket
- via
- Video
- utsikt
- Överträdelser
- synlig
- visualisera
- avgörande
- vs
- gå
- genomgång
- vill
- var
- Kolla på
- Sätt..
- sätt
- we
- Väder
- webb
- webbläsare
- webbservice
- webbsidor
- VÄL
- ALLBEKANT
- były
- Vad
- Vad är
- Vad är
- när
- om
- som
- medan
- VEM
- Hela
- varför
- bred
- brett
- widget
- wikipedia
- kommer
- fönster
- Vinner
- med
- inom
- utan
- ord
- Arbete
- arbetade
- arbetsflöde
- arbetsflöden
- arbetssätt
- fungerar
- världen
- skulle
- skriva
- skrivning
- X
- ännu
- york
- Om er
- Din
- själv
- Youtube
- Zendesk
- zephyrnet
- Postnummer