V jedru, LangChain je inovativno ogrodje, prilagojeno za izdelavo aplikacij, ki izkoriščajo zmogljivosti jezikovnih modelov. To je komplet orodij, namenjen razvijalcem za ustvarjanje aplikacij, ki se zavedajo konteksta in so sposobne prefinjenega sklepanja.
To pomeni, da lahko aplikacije LangChain razumejo kontekst, kot so hitra navodila ali odgovori, ki temeljijo na vsebini, in uporabljajo jezikovne modele za zapletene sklepne naloge, kot je odločanje, kako se odzvati ali katera dejanja izvesti. LangChain predstavlja enoten pristop k razvoju inteligentnih aplikacij, ki s svojimi raznolikimi komponentami poenostavlja pot od koncepta do izvedbe.
Razumevanje LangChaina
LangChain je veliko več kot le okvir; je celovit ekosistem, sestavljen iz več sestavnih delov.
- Prvič, tu so knjižnice LangChain, ki so na voljo v Pythonu in JavaScriptu. Te knjižnice so hrbtenica LangChain, saj ponujajo vmesnike in integracije za različne komponente. Zagotavljajo osnovni čas izvajanja za združevanje teh komponent v kohezivne verige in agente, skupaj s pripravljenimi implementacijami za takojšnjo uporabo.
- Nato imamo predloge LangChain. To je zbirka referenčnih arhitektur, ki jih je mogoče uvesti in so prilagojene širokemu naboru nalog. Ne glede na to, ali gradite chatbota ali zapleteno analitično orodje, te predloge ponujajo dobro izhodišče.
- LangServe nastopi kot vsestranska knjižnica za uvajanje verig LangChain kot API-jev REST. To orodje je bistveno za pretvorbo vaših projektov LangChain v dostopne in razširljive spletne storitve.
- Nazadnje, LangSmith služi kot platforma za razvijalce. Zasnovan je za odpravljanje napak, testiranje, ocenjevanje in spremljanje verig, zgrajenih na katerem koli ogrodju LLM. Zaradi brezhibne integracije z LangChain je nepogrešljivo orodje za razvijalce, ki želijo izboljšati in izpopolniti svoje aplikacije.
Te komponente skupaj vam omogočajo, da z lahkoto razvijate, izdelujete in uvajate aplikacije. Z LangChain začnete s pisanjem svojih aplikacij z uporabo knjižnic, pri čemer se za vodenje sklicujete na predloge. LangSmith vam nato pomaga pri pregledovanju, testiranju in spremljanju vaših verig ter zagotavlja, da se vaše aplikacije nenehno izboljšujejo in so pripravljene za uvedbo. Nazadnje, z LangServe lahko preprosto spremenite katero koli verigo v API, kar olajša uvajanje.
V naslednjih razdelkih se bomo poglobili v nastavitev LangChain in začeli vašo pot pri ustvarjanju inteligentnih aplikacij, ki temeljijo na jezikovnem modelu.
Avtomatizirajte ročna opravila in poteke dela z našim graditeljem potekov dela, ki ga poganja AI, ki ga je Nanonets zasnoval za vas in vaše ekipe.
Namestitev in namestitev
Ste se pripravljeni potopiti v svet LangChain? Nastavitev je enostavna in ta vodnik vas bo vodil skozi postopek korak za korakom.
Prvi korak na vaši poti LangChain je, da ga namestite. To lahko enostavno storite z uporabo pip ali conda. V terminalu zaženite naslednji ukaz:
pip install langchain
Za tiste, ki imajo raje najnovejše funkcije in jim je všeč malo več avanture, lahko LangChain namestite neposredno iz vira. Klonirajte repozitorij in se pomaknite do langchain/libs/langchain
imenik. Nato zaženite:
pip install -e .
Za poskusne funkcije razmislite o namestitvi langchain-experimental
. To je paket, ki vsebuje vrhunsko kodo in je namenjen raziskovalnim in eksperimentalnim namenom. Namestite ga z:
pip install langchain-experimental
LangChain CLI je priročno orodje za delo s predlogami LangChain in projekti LangServe. Če želite namestiti LangChain CLI, uporabite:
pip install langchain-cli
LangServe je bistvenega pomena za uvajanje vaših verig LangChain kot REST API. Namesti se poleg LangChain CLI.
LangChain pogosto zahteva integracije s ponudniki modelov, shrambami podatkov, API-ji itd. Za ta primer bomo uporabili API-je modela OpenAI. Namestite paket OpenAI Python z:
pip install openai
Za dostop do API-ja nastavite ključ OpenAI API kot spremenljivko okolja:
export OPENAI_API_KEY="your_api_key"
Druga možnost je, da posredujete ključ neposredno v svojem okolju python:
import os
os.environ['OPENAI_API_KEY'] = 'your_api_key'
LangChain omogoča ustvarjanje aplikacij jezikovnega modela prek modulov. Ti moduli so lahko samostojni ali sestavljeni za kompleksne primere uporabe. Ti moduli so –
- Model V/I: Omogoča interakcijo z različnimi jezikovnimi modeli, učinkovito obravnavanje njihovih vhodov in izhodov.
- Pridobivanje: Omogoča dostop do podatkov, specifičnih za aplikacijo, in interakcijo z njimi, kar je ključno za dinamično uporabo podatkov.
- Agenti: Omogočite aplikacijam, da izberejo ustrezna orodja na podlagi direktiv na visoki ravni, kar izboljša zmožnosti odločanja.
- Verige: ponuja vnaprej določene kompozicije za večkratno uporabo, ki služijo kot gradniki za razvoj aplikacij.
- Spomin: Ohranja stanje aplikacije med izvajanjem več verig, kar je bistveno za interakcije, ki se zavedajo konteksta.
Vsak modul cilja na posebne razvojne potrebe, zaradi česar je LangChain celovit nabor orodij za ustvarjanje naprednih jezikovnih modelov aplikacij.
Poleg zgornjih komponent imamo tudi Izrazni jezik LangChain (LCEL), ki je deklarativni način za preprosto sestavljanje modulov skupaj, kar omogoča veriženje komponent z uporabo univerzalnega vmesnika Runnable.
LCEL izgleda nekako takole –
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import BaseOutputParser # Example chain
chain = ChatPromptTemplate() | ChatOpenAI() | CustomOutputParser()
Zdaj, ko smo zajeli osnove, bomo nadaljevali z:
- Podrobneje se poglobite v vsak modul Langchain.
- Naučite se uporabljati jezik LangChain Expression Language.
- Raziščite običajne primere uporabe in jih implementirajte.
- Razmestite aplikacijo od konca do konca z LangServe.
- Oglejte si LangSmith za odpravljanje napak, testiranje in spremljanje.
Začnimo!
Modul I: Model I/O
V LangChainu se osrednji element vsake aplikacije vrti okoli jezikovnega modela. Ta modul zagotavlja bistvene gradnike za učinkovito povezovanje s katerim koli jezikovnim modelom, kar zagotavlja brezhibno integracijo in komunikacijo.
Ključne komponente modela I/O
- LLMs in modeli klepeta (uporabljajo se izmenično):
- LLM:
- Definicija: modeli za dokončanje čistega besedila.
- Input / Output: Vzemite besedilni niz kot vhod in vrnite besedilni niz kot izhod.
- Klepetalni modeli
- LLM:
- Definicija: modeli, ki kot osnovo uporabljajo jezikovni model, vendar se razlikujejo po vhodnem in izhodnem formatu.
- Input / Output: Sprejmite seznam sporočil klepeta kot vnos in vrnite sporočilo klepeta.
- Pozivi: Ustvarite predlogo, dinamično izberite in upravljajte vnose modela. Omogoča ustvarjanje prilagodljivih pozivov, specifičnih za kontekst, ki vodijo odzive jezikovnega modela.
- Izhodni razčlenjevalniki: Izvleček in oblikovanje informacij iz izhodov modela. Uporabno za pretvorbo surovega izhoda jezikovnih modelov v strukturirane podatke ali posebne formate, ki jih potrebuje aplikacija.
LLM
Integracija LangChaina z velikimi jezikovnimi modeli (LLM), kot so OpenAI, Cohere in Hugging Face, je temeljni vidik njegove funkcionalnosti. LangChain sam ne gosti LLM-jev, ampak ponuja enoten vmesnik za interakcijo z različnimi LLM-ji.
Ta razdelek ponuja pregled uporabe ovoja OpenAI LLM v LangChain, ki se uporablja tudi za druge vrste LLM. To smo že namestili v razdelku »Kako začeti«. Inicializirajmo LLM.
from langchain.llms import OpenAI
llm = OpenAI()
- LLM izvajajo Teči vmesnik, osnovni gradnik Izrazni jezik LangChain (LCEL). To pomeni, da podpirajo
invoke
,ainvoke
,stream
,astream
,batch
,abatch
,astream_log
klicev. - LLM sprejemajo strune kot vhodne podatke ali predmete, ki jih je mogoče prisiliti v nizovne pozive, vključno z
List[BaseMessage]
inPromptValue
. (več o tem pozneje)
Poglejmo si nekaj primerov.
response = llm.invoke("List the seven wonders of the world.")
print(response)
Alternativno lahko pokličete metodo toka za pretakanje besedilnega odgovora.
for chunk in llm.stream("Where were the 2012 Olympics held?"): print(chunk, end="", flush=True)
Klepetalni modeli
Integracija LangChaina z modeli klepeta, specializirano različico jezikovnih modelov, je bistvena za ustvarjanje interaktivnih aplikacij za klepet. Medtem ko interno uporabljajo jezikovne modele, modeli klepeta predstavljajo poseben vmesnik, osredotočen na sporočila klepeta kot vhode in izhode. Ta razdelek nudi podroben pregled uporabe modela klepeta OpenAI v LangChain.
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI()
Modeli klepeta v LangChainu delujejo z različnimi vrstami sporočil, kot je npr AIMessage
, HumanMessage
, SystemMessage
, FunctionMessage
in ChatMessage
(s poljubnim parametrom vloge). Na splošno HumanMessage
, AIMessage
in SystemMessage
so najpogosteje uporabljeni.
Chat modeli sprejemajo predvsem List[BaseMessage]
kot vložke. Nize je mogoče pretvoriti v HumanMessage
in PromptValue
je tudi podprt.
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)
Pozivi
Pozivi so bistveni pri usmerjanju jezikovnih modelov za ustvarjanje ustreznih in skladnih rezultatov. Lahko segajo od preprostih navodil do zapletenih primerov z nekaj posnetki. V LangChainu je lahko obravnavanje pozivov zelo poenostavljen proces, zahvaljujoč več namenskim razredom in funkcijam.
LangChaina PromptTemplate
razred je vsestransko orodje za ustvarjanje pozivov nizov. Uporablja Python str.format
sintakso, ki omogoča dinamično generiranje pozivov. Predlogo lahko določite z ogradami in jih po potrebi napolnite z določenimi vrednostmi.
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)
Za modele klepeta so pozivi bolj strukturirani in vključujejo sporočila s posebnimi vlogami. LangChain ponuja ChatPromptTemplate
Za ta namen.
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)
Ta pristop omogoča ustvarjanje interaktivnih, privlačnih chatbotov z dinamičnimi odzivi.
oba PromptTemplate
in ChatPromptTemplate
brezhibno integrirajo z jezikom LangChain Expression Language (LCEL), kar jim omogoča, da so del večjih, zapletenih delovnih tokov. O tem bomo več razpravljali kasneje.
Predloge pozivov po meri so včasih bistvene za opravila, ki zahtevajo edinstveno oblikovanje ali posebna navodila. Ustvarjanje predloge poziva po meri vključuje definiranje vhodnih spremenljivk in metode oblikovanja po meri. Ta prilagodljivost omogoča LangChainu, da zadovolji široko paleto zahtev, specifičnih za aplikacijo. Preberite več tukaj.
LangChain podpira tudi nekaj pozivov, kar omogoča modelu, da se uči iz primerov. Ta funkcija je ključnega pomena za naloge, ki zahtevajo kontekstualno razumevanje ali specifične vzorce. Predloge pozivov za nekaj posnetkov je mogoče sestaviti iz nabora primerov ali z uporabo predmeta izbirnika primerov. Preberite več tukaj.
Izhodni razčlenjevalniki
Izhodni razčlenjevalniki igrajo ključno vlogo v Langchainu, saj uporabnikom omogočajo strukturiranje odgovorov, ki jih ustvarijo jezikovni modeli. V tem razdelku bomo raziskali koncept izhodnih razčlenjevalnikov in zagotovili primere kode z uporabo Langchainovega PydanticOutputParserja, SimpleJsonOutputParserja, CommaSeparatedListOutputParserja, DatetimeOutputParserja in XMLOutputParserja.
PydanticOutputParser
Langchain ponuja PydanticOutputParser za razčlenjevanje odgovorov v podatkovne strukture Pydantic. Spodaj je korak za korakom primer, kako ga uporabiti:
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)
Rezultati bodo:
SimpleJsonOutputParser
Langchainov SimpleJsonOutputParser se uporablja, ko želite razčleniti izhode, podobne JSON. Tukaj je primer:
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 je priročen, ko želite iz odgovorov modela izvleči sezname, ločene z vejicami. Tukaj je primer:
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
Langchainov DatetimeOutputParser je zasnovan za razčlenjevanje informacij o datumu in času. Uporabite ga tako:
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)
Ti primeri prikazujejo, kako je mogoče Langchainove izhodne razčlenjevalnike uporabiti za strukturiranje različnih vrst odzivov modela, zaradi česar so primerni za različne aplikacije in formate. Razčlenjevalniki izhodov so dragoceno orodje za izboljšanje uporabnosti in interpretabilnosti izhodov jezikovnega modela v Langchainu.
Avtomatizirajte ročna opravila in poteke dela z našim graditeljem potekov dela, ki ga poganja AI, ki ga je Nanonets zasnoval za vas in vaše ekipe.
Modul II: Pridobivanje
Pridobivanje v LangChain ima ključno vlogo v aplikacijah, ki zahtevajo podatke, specifične za uporabnika, ki niso vključeni v nabor za usposabljanje modela. Ta postopek, znan kot Retrieval Augmented Generation (RAG), vključuje pridobivanje zunanjih podatkov in njihovo integracijo v proces generiranja jezikovnega modela. LangChain ponuja obsežen nabor orodij in funkcionalnosti za olajšanje tega procesa, ki skrbi za preproste in zapletene aplikacije.
LangChain dosega iskanje prek niza komponent, o katerih bomo razpravljali eno za drugo.
Nalagalniki dokumentov
Nalagalniki dokumentov v LangChainu omogočajo črpanje podatkov iz različnih virov. Z več kot 100 nalagalniki, ki so na voljo, podpirajo vrsto vrst dokumentov, aplikacij in virov (zasebna vedra s3, javna spletna mesta, zbirke podatkov).
Nalagalnik dokumentov lahko izberete glede na vaše zahteve tukaj.
Vsi ti nakladalniki zaužijejo podatke v Dokument razredi. Pozneje se bomo naučili uporabljati podatke, vnesene v razrede Document.
Nalagalnik besedilnih datotek: Naložite preprosto .txt
datoteko v dokument.
from langchain.document_loaders import TextLoader loader = TextLoader("./sample.txt")
document = loader.load()
Nalagalnik CSV: Naložite datoteko CSV v dokument.
from langchain.document_loaders.csv_loader import CSVLoader loader = CSVLoader(file_path='./example_data/sample.csv')
documents = loader.load()
Razčlenjevanje lahko prilagodimo tako, da podamo imena polj –
loader = CSVLoader(file_path='./example_data/mlb_teams_2012.csv', csv_args={ 'delimiter': ',', 'quotechar': '"', 'fieldnames': ['MLB Team', 'Payroll in millions', 'Wins']
})
documents = loader.load()
Nalagalniki PDF: Nalagalniki PDF v LangChainu ponujajo različne metode za razčlenjevanje in ekstrahiranje vsebine iz datotek PDF. Vsak nalagalnik izpolnjuje različne zahteve in uporablja različne osnovne knjižnice. Spodaj so podrobni primeri za vsak nakladalnik.
PyPDFLoader se uporablja za osnovno razčlenjevanje PDF.
from langchain.document_loaders import PyPDFLoader loader = PyPDFLoader("example_data/layout-parser-paper.pdf")
pages = loader.load_and_split()
MathPixLoader je idealen za pridobivanje matematične vsebine in diagramov.
from langchain.document_loaders import MathpixPDFLoader loader = MathpixPDFLoader("example_data/math-content.pdf")
data = loader.load()
PyMuPDFLoader je hiter in vključuje podrobno ekstrakcijo metapodatkov.
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 se uporablja za natančnejši nadzor nad ekstrakcijo besedila.
from langchain.document_loaders import PDFMinerLoader loader = PDFMinerLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
AmazonTextractPDFParser uporablja AWS Texttract za OCR in druge napredne funkcije za razčlenjevanje PDF-jev.
from langchain.document_loaders import AmazonTextractPDFLoader # Requires AWS account and configuration
loader = AmazonTextractPDFLoader("example_data/complex-layout.pdf")
documents = loader.load()
PDFMinerPDFasHTMLLoader ustvari HTML iz PDF-ja za semantično razčlenjevanje.
from langchain.document_loaders import PDFMinerPDFasHTMLLoader loader = PDFMinerPDFasHTMLLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
PDFPlumberLoader ponuja podrobne metapodatke in podpira en dokument na stran.
from langchain.document_loaders import PDFPlumberLoader loader = PDFPlumberLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
Integrirani nakladalniki: LangChain ponuja široko paleto nalagalnikov po meri za neposredno nalaganje podatkov iz vaših aplikacij (kot so Slack, Sigma, Notion, Confluence, Google Drive in številne druge) in baz podatkov ter njihovo uporabo v aplikacijah LLM.
Celoten seznam je tukaj.
Spodaj je nekaj primerov za ponazoritev tega –
Primer I – Slack
Slack, široko uporabljeno platformo za takojšnje sporočanje, je mogoče integrirati v poteke dela in aplikacije LLM.
- Pojdite na svojo stran za upravljanje delovnega prostora Slack.
- Pomaknite se na
{your_slack_domain}.slack.com/services/export
. - Izberite želeno časovno obdobje in zaženite izvoz.
- Slack obvesti po e-pošti in DM, ko je izvoz pripravljen.
- Rezultat izvoza je a
.zip
datoteko, ki se nahaja v mapi Prenosi ali na izbrani poti za prenos. - Določite pot prenesenega
.zip
datotekoLOCAL_ZIPFILE
. - Uporaba
SlackDirectoryLoader
Izlangchain.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)
Primer II – Figma
Figma, priljubljeno orodje za oblikovanje vmesnikov, ponuja REST API za integracijo podatkov.
- Pridobite ključ datoteke Figma iz zapisa URL:
https://www.figma.com/file/{filekey}/sampleFilename
. - ID-je vozlišč najdete v parametru URL-ja
?node-id={node_id}
. - Ustvarite žeton za dostop po navodilih na Center za pomoč Figma.
- O
FigmaFileLoader
razred odlangchain.document_loaders.figma
se uporablja za nalaganje podatkov Figma. - Različni moduli LangChain, kot je
CharacterTextSplitter
,ChatOpenAI
, itd., se uporabljajo za predelavo.
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()
- O
generate_code
funkcija uporablja podatke Figma za ustvarjanje kode HTML/CSS. - Uporablja predlogo pogovora z modelom, ki temelji na GPT.
def generate_code(human_input): # Template for system and human prompts system_prompt_template = "Your coding instructions..." human_prompt_template = "Code the {text}. Ensure it's mobile responsive" # Creating prompt templates system_message_prompt = SystemMessagePromptTemplate.from_template(system_prompt_template) human_message_prompt = HumanMessagePromptTemplate.from_template(human_prompt_template) # Setting up the AI model gpt_4 = ChatOpenAI(temperature=0.02, model_name="gpt-4") # Retrieving relevant documents relevant_nodes = figma_doc_retriever.get_relevant_documents(human_input) # Generating and formatting the prompt conversation = [system_message_prompt, human_message_prompt] chat_prompt = ChatPromptTemplate.from_messages(conversation) response = gpt_4(chat_prompt.format_prompt(context=relevant_nodes, text=human_input).to_messages()) return response # Example usage
response = generate_code("page top header")
print(response.content)
- O
generate_code
funkcija, ko se izvede, vrne kodo HTML/CSS na podlagi vnosa načrta Figma.
Uporabimo svoje znanje in ustvarimo nekaj nizov dokumentov.
Najprej naložimo PDF, letno poročilo o trajnosti BCG.
Za to uporabljamo PyPDFLoader.
from langchain.document_loaders import PyPDFLoader loader = PyPDFLoader("bcg-2022-annual-sustainability-report-apr-2023.pdf")
pdfpages = loader.load_and_split()
Zdaj bomo zaužili podatke iz Airtable. Imamo Airtable, ki vsebuje informacije o različnih OCR in modelih pridobivanja podatkov –
Za to uporabimo AirtableLoader, ki ga najdete na seznamu integriranih nalagalnikov.
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()
Nadaljujmo in se naučimo uporabljati te dokumentne razrede.
Transformatorji dokumentov
Pretvorniki dokumentov v LangChainu so bistvena orodja, zasnovana za manipulacijo dokumentov, ki smo jih ustvarili v prejšnjem pododdelku.
Uporabljajo se za naloge, kot je razdelitev dolgih dokumentov na manjše dele, združevanje in filtriranje, ki so ključnega pomena za prilagajanje dokumentov kontekstualnemu oknu modela ali za izpolnjevanje posebnih potreb aplikacije.
Eno takih orodij je RecursiveCharacterTextSplitter, vsestranski razdelilnik besedila, ki za razdelitev uporablja seznam znakov. Omogoča parametre, kot so velikost kosa, prekrivanje in začetni indeks. Tukaj je primer, kako se uporablja v Pythonu:
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])
Drugo orodje je CharacterTextSplitter, ki razdeli besedilo na podlagi določenega znaka in vključuje kontrolnike za velikost in prekrivanje kosov:
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 je zasnovan tako, da razdeli vsebino HTML na podlagi oznak glave, pri čemer ohrani semantično strukturo:
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])
Bolj zapleteno manipulacijo je mogoče doseči s kombinacijo HTMLHeaderTextSplitter z drugim razdelilnikom, kot je cevovodni razdelilnik:
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 ponuja tudi posebne razdelilnike za različne programske jezike, kot sta Python Code Splitter in 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])
Za razdelitev besedila na podlagi števila žetonov, kar je uporabno za jezikovne modele z omejitvami žetonov, se uporablja 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])
Nazadnje LongContextReorder preureja dokumente, da prepreči poslabšanje zmogljivosti v modelih zaradi dolgih kontekstov:
from langchain.document_transformers import LongContextReorder reordering = LongContextReorder()
reordered_docs = reordering.transform_documents(docs)
print(reordered_docs[0])
Ta orodja prikazujejo različne načine preoblikovanja dokumentov v LangChain, od preprostega razdeljevanja besedila do zapletenega preurejanja in razdeljevanja glede na jezik. Za bolj poglobljene in specifične primere uporabe si je treba ogledati razdelek o dokumentaciji in integracijah LangChain.
V naših primerih so nakladalniki za nas že ustvarili razdeljene dokumente in ta del je že obdelan.
Modeli vdelave besedila
Modeli za vdelavo besedila v LangChain zagotavljajo standardiziran vmesnik za različne ponudnike modelov za vdelavo, kot so OpenAI, Cohere in Hugging Face. Ti modeli pretvorijo besedilo v vektorske predstavitve, kar omogoča operacije, kot je semantično iskanje po podobnosti besedila v vektorskem prostoru.
Če želite začeti z modeli za vdelavo besedila, morate običajno namestiti določene pakete in nastaviti ključe API. To smo že storili za OpenAI
V LangChainu je embed_documents
Metoda se uporablja za vdelavo več besedil, kar zagotavlja seznam vektorskih predstavitev. Na primer:
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]))
Za vdelavo posameznega besedila, kot je iskalna poizvedba, embed_query
uporabljena metoda. To je uporabno za primerjavo poizvedbe z nizom vdelanih dokumentov. Na primer:
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])
Razumevanje teh vdelav je ključnega pomena. Vsak del besedila se pretvori v vektor, katerega dimenzija je odvisna od uporabljenega modela. Na primer, modeli OpenAI običajno proizvajajo 1536-dimenzionalne vektorje. Te vdelave se nato uporabijo za pridobivanje ustreznih informacij.
Funkcionalnost vdelave LangChain ni omejena na OpenAI, ampak je zasnovana za delo z različnimi ponudniki. Nastavitev in uporaba se lahko nekoliko razlikujeta glede na ponudnika, vendar osrednji koncept vdelave besedil v vektorski prostor ostaja enak. Za podrobno uporabo, vključno z naprednimi konfiguracijami in integracijami z različnimi ponudniki modelov vdelave, je dokumentacija LangChain v razdelku Integracije dragocen vir.
Vektorske trgovine
Vektorske trgovine v LangChainu podpirajo učinkovito shranjevanje in iskanje vdelanih besedil. LangChain se integrira z več kot 50 vektorskimi trgovinami in zagotavlja standardiziran vmesnik za enostavno uporabo.
Primer: shranjevanje in iskanje vdelav
Po vdelavi besedil jih lahko shranimo v vektorsko shrambo, kot je Chroma
in izvede iskanje podobnosti:
from langchain.vectorstores import Chroma db = Chroma.from_texts(embedded_texts)
similar_texts = db.similarity_search("search query")
Namesto tega uporabimo vektorsko shrambo FAISS za ustvarjanje indeksov za naše dokumente.
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS pdfstore = FAISS.from_documents(pdfpages, embedding=OpenAIEmbeddings()) airtablestore = FAISS.from_documents(airtabledocs, embedding=OpenAIEmbeddings())
Prinašalci
Retrieverji v LangChain so vmesniki, ki vrnejo dokumente kot odgovor na nestrukturirano poizvedbo. So bolj splošne kot vektorske shrambe, osredotočene so na iskanje in ne na shranjevanje. Čeprav se vektorske shrambe lahko uporabljajo kot hrbtenica prinašalcev, obstajajo tudi druge vrste prinašalcev.
Če želite nastaviti Chroma Retriever, ga najprej namestite z uporabo pip install chromadb
. Nato naložite, razdelite, vdelate in pridobite dokumente z nizom ukazov Python. Tukaj je primer kode za nastavitev Chroma retrieverja:
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 avtomatizira hitro nastavitev z ustvarjanjem več poizvedb za poizvedbo vnosa uporabnika in združuje rezultate. Tu je primer njegove preproste uporabe:
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))
Contextual Compression v LangChain stisne pridobljene dokumente z uporabo konteksta poizvedbe in zagotovi, da so vrnjene samo ustrezne informacije. To vključuje zmanjšanje vsebine in filtriranje manj ustreznih dokumentov. Naslednji primer kode prikazuje, kako uporabljati 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 združuje različne algoritme za iskanje, da doseže boljšo zmogljivost. Primer kombinacije BM25 in FAISS Retrieverjev je prikazan v naslednji kodi:
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 v LangChainu omogoča poizvedovanje po dokumentih z več vektorji na dokument, kar je uporabno za zajemanje različnih semantičnih vidikov znotraj dokumenta. Metode za ustvarjanje več vektorjev vključujejo razdelitev na manjše dele, povzemanje ali generiranje hipotetičnih vprašanj. Za razdelitev dokumentov na manjše dele lahko uporabite naslednjo kodo Python:
python
from langchain.retrievers.multi_vector import MultiVectorRetriever
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.storage import InMemoryStore
from langchain.document_loaders from TextLoader
import uuid loaders = [TextLoader("file1.txt"), TextLoader("file2.txt")]
docs = [doc for loader in loaders for doc in loader.load()]
text_splitter = RecursiveCharacterTextSplitter(chunk_size=10000)
docs = text_splitter.split_documents(docs) vectorstore = Chroma(collection_name="full_documents", embedding_function=OpenAIEmbeddings())
store = InMemoryStore()
id_key = "doc_id"
retriever = MultiVectorRetriever(vectorstore=vectorstore, docstore=store, id_key=id_key) doc_ids = [str(uuid.uuid4()) for _ in docs]
child_text_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
sub_docs = [sub_doc for doc in docs for sub_doc in child_text_splitter.split_documents([doc])]
for sub_doc in sub_docs: sub_doc.metadata[id_key] = doc_ids[sub_docs.index(sub_doc)] retriever.vectorstore.add_documents(sub_docs)
retriever.docstore.mset(list(zip(doc_ids, docs)))
Druga metoda je ustvarjanje povzetkov za boljše iskanje zaradi bolj osredotočene predstavitve vsebine. Tukaj je primer ustvarjanja povzetkov:
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)))
Ustvarjanje hipotetičnih vprašanj, ki so pomembna za vsak dokument z uporabo LLM, je drug pristop. To lahko storite z naslednjo kodo:
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 je še en retriever, ki vzpostavlja ravnotežje med natančnostjo vdelave in ohranjanjem konteksta s shranjevanjem majhnih kosov in pridobivanjem njihovih večjih nadrejenih dokumentov. Njegovo izvajanje je naslednje:
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")
Pridobivalnik, ki sam poizveduje, sestavi strukturirane poizvedbe iz vnosov v naravnem jeziku in jih uporabi v osnovni trgovini VectorStore. Njegova izvedba je prikazana v naslednji kodi:
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 izvaja spletno raziskavo na podlagi dane poizvedbe –
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")
Za naše primere lahko uporabimo tudi standardni retriever, ki je že implementiran kot del našega objekta vektorske shrambe, kot sledi –
Sedaj lahko povprašamo prinašalce. Izhod naše poizvedbe bodo predmeti dokumentov, pomembni za poizvedbo. Ti bodo na koncu uporabljeni za ustvarjanje ustreznih odgovorov v nadaljnjih razdelkih.
Avtomatizirajte ročna opravila in poteke dela z našim graditeljem potekov dela, ki ga poganja AI, ki ga je Nanonets zasnoval za vas in vaše ekipe.
Modul III : Agenti
LangChain uvaja zmogljiv koncept, imenovan »Agenti«, ki idejo o verigah dvigne na povsem novo raven. Agenti izkoriščajo jezikovne modele za dinamično določanje zaporedij dejanj, ki jih je treba izvesti, zaradi česar so neverjetno vsestranski in prilagodljivi. Za razliko od tradicionalnih verig, kjer so dejanja trdo kodirana v kodi, agenti uporabljajo jezikovne modele kot mehanizme sklepanja, da se odločijo, katera dejanja izvesti in v kakšnem vrstnem redu.
Agent je glavna komponenta, odgovorna za odločanje. Izkorišča moč jezikovnega modela in poziv za določitev naslednjih korakov za dosego določenega cilja. Vložki za agenta običajno vključujejo:
- Orodja: Opisi razpoložljivih orodij (več o tem kasneje).
- Uporabniški vnos: Cilj ali poizvedba uporabnika na visoki ravni.
- Vmesni koraki: Zgodovina parov (dejanje, izhod orodja), izvedenih za doseganje trenutnega uporabniškega vnosa.
Rezultat agenta je lahko naslednji ukrepanje ukrepati (AgentActions) ali končnico Odgovor poslati uporabniku (AgentFinish). An ukrepanje določa a orodje in vhod za to orodje.
Orodja
Orodja so vmesniki, ki jih agent lahko uporablja za interakcijo s svetom. Agentom omogočajo izvajanje različnih nalog, kot je iskanje po spletu, izvajanje ukazov lupine ali dostop do zunanjih API-jev. V LangChainu so orodja bistvenega pomena za razširitev zmogljivosti agentov in jim omogočajo izpolnjevanje različnih nalog.
Če želite uporabljati orodja v LangChain, jih lahko naložite z naslednjim delčkom:
from langchain.agents import load_tools tool_names = [...]
tools = load_tools(tool_names)
Nekatera orodja lahko za inicializacijo zahtevajo osnovni jezikovni model (LLM). V takih primerih lahko opravite tudi LLM:
from langchain.agents import load_tools tool_names = [...]
llm = ...
tools = load_tools(tool_names, llm=llm)
Ta nastavitev vam omogoča dostop do različnih orodij in njihovo integracijo v poteke dela vašega agenta. Celoten seznam orodij z dokumentacijo o uporabi je tukaj.
Oglejmo si nekaj primerov orodij.
DuckDuckGo
Orodje DuckDuckGo vam omogoča izvajanje spletnih iskanj z njegovim iskalnikom. Uporabite ga tako:
from langchain.tools import DuckDuckGoSearchRun
search = DuckDuckGoSearchRun()
search.run("manchester united vs luton town match summary")
DataForSeo
Zbirka orodij DataForSeo vam omogoča pridobivanje rezultatov iskalnika z uporabo API-ja DataForSeo. Za uporabo tega kompleta orodij boste morali nastaviti svoje poverilnice za API. Tukaj je opisano, kako konfigurirate poverilnice:
import os os.environ["DATAFORSEO_LOGIN"] = "<your_api_access_username>"
os.environ["DATAFORSEO_PASSWORD"] = "<your_api_access_password>"
Ko so vaše poverilnice nastavljene, lahko ustvarite a DataForSeoAPIWrapper
orodje za dostop do API-ja:
from langchain.utilities.dataforseo_api_search import DataForSeoAPIWrapper wrapper = DataForSeoAPIWrapper() result = wrapper.run("Weather in Los Angeles")
O DataForSeoAPIWrapper
orodje pridobi rezultate iskalnikov iz različnih virov.
Prilagodite lahko vrsto rezultatov in polj, vrnjenih v odgovoru JSON. Določite lahko na primer vrste rezultatov, polja in nastavite največje število vrnjenih najboljših rezultatov:
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")
Ta primer prilagaja odgovor JSON tako, da poda vrste rezultatov, polja in omeji število rezultatov.
Določite lahko tudi lokacijo in jezik za svoje rezultate iskanja, tako da ovoju API-ja posredujete dodatne parametre:
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")
Če navedete parametre lokacije in jezika, lahko rezultate iskanja prilagodite določenim regijam in jezikom.
Imate prilagodljivost pri izbiri iskalnika, ki ga želite uporabiti. Preprosto določite želeni iskalnik:
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")
V tem primeru je iskanje prilagojeno za uporabo Binga kot iskalnika.
Ovoj API vam omogoča tudi, da določite vrsto iskanja, ki ga želite izvesti. Na primer, lahko izvedete iskanje po zemljevidih:
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")
To prilagodi iskanje za pridobivanje informacij, povezanih z zemljevidi.
lupina (bash)
Komplet orodij Shell omogoča agentom dostop do okolja lupine, kar jim omogoča izvajanje ukazov lupine. Ta funkcija je zmogljiva, vendar jo je treba uporabljati previdno, zlasti v okoljih s peskovnikom. Tukaj je opisano, kako lahko uporabite orodje Shell:
from langchain.tools import ShellTool shell_tool = ShellTool() result = shell_tool.run({"commands": ["echo 'Hello World!'", "time"]})
V tem primeru orodje Shell izvaja dva ukaza lupine: ponavljanje »Hello World!« in prikaz trenutnega časa.
Orodje Shell lahko zagotovite agentu za opravljanje zahtevnejših nalog. Tukaj je primer agenta, ki pridobiva povezave s spletne strani z orodjem Shell:
from langchain.agents import AgentType, initialize_agent
from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(temperature=0.1) shell_tool.description = shell_tool.description + f"args {shell_tool.args}".replace( "{", "{{"
).replace("}", "}}")
self_ask_with_search = initialize_agent( [shell_tool], llm, agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)
self_ask_with_search.run( "Download the langchain.com webpage and grep for all urls. Return only a sorted list of them. Be sure to use double quotes."
)
V tem scenariju posrednik uporablja orodje Shell za izvajanje zaporedja ukazov za pridobivanje, filtriranje in razvrščanje URL-jev s spletne strani.
Navedeni primeri prikazujejo nekatera orodja, ki so na voljo v LangChainu. Ta orodja končno razširijo zmožnosti agentov (raziskanih v naslednjem pododdelku) in jim omogočijo učinkovito opravljanje različnih nalog. Glede na vaše zahteve lahko izberete orodja in komplete orodij, ki najbolj ustrezajo potrebam vašega projekta, in jih vključite v delovne tokove svojega agenta.
Nazaj k agentom
Pojdimo zdaj k agentom.
AgentExecutor je izvajalno okolje za agenta. Odgovoren je za klic agenta, izvajanje dejanj, ki jih izbere, posredovanje izhodov dejanj nazaj agentu in ponavljanje postopka, dokler agent ne konča. V psevdokodi bi lahko AgentExecutor izgledal nekako takole:
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 obravnava različne zapletenosti, kot je obravnavanje primerov, ko agent izbere neobstoječe orodje, obravnavanje napak orodij, upravljanje izhodov, ki jih ustvari agent, ter zagotavlja beleženje in opazovanje na vseh ravneh.
Čeprav je razred AgentExecutor primarno izvajalno okolje agenta v LangChainu, so podprti tudi drugi, bolj eksperimentalni izvajalni časi, vključno z:
- Agent za načrtovanje in izvedbo
- Baby AGI
- Samodejni GPT
Da bi bolje razumeli agentsko ogrodje, izdelajmo osnovnega agenta iz nič, nato pa nadaljujmo z raziskovanjem vnaprej izdelanih agentov.
Preden se poglobimo v gradnjo agenta, je bistveno, da ponovno pregledamo nekaj ključnih izrazov in shem:
- AgentAction: To je podatkovni razred, ki predstavlja dejanje, ki ga mora izvesti agent. Sestavljen je iz a
tool
lastnost (ime orodja za priklic) in atool_input
lastnost (vnos za to orodje). - AgentFinish: Ta podatkovni razred označuje, da je agent končal svojo nalogo in mora vrniti odgovor uporabniku. Običajno vključuje slovar vrnjenih vrednosti, pogosto s ključnim "izhodom", ki vsebuje besedilo odgovora.
- Vmesni koraki: To so zapisi prejšnjih dejanj posrednika in ustrezni izhodi. So ključnega pomena za posredovanje konteksta prihodnjim ponovitvam agenta.
V našem primeru bomo za ustvarjanje agenta uporabili klicanje funkcij OpenAI. Ta pristop je zanesljiv za ustvarjanje agentov. Začeli bomo z ustvarjanjem preprostega orodja, ki izračuna dolžino besede. To orodje je uporabno, ker lahko jezikovni modeli včasih naredijo napake zaradi tokenizacije pri štetju dolžin besed.
Najprej naložimo jezikovni model, ki ga bomo uporabili za nadzor agenta:
from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
Preizkusimo model z izračunom dolžine besede:
llm.invoke("how many letters in the word educa?")
V odgovoru mora biti navedeno število črk v besedi »educa«.
Nato bomo definirali preprosto funkcijo Python za izračun dolžine besede:
from langchain.agents import tool @tool
def get_word_length(word: str) -> int: """Returns the length of a word.""" return len(word)
Ustvarili smo orodje z imenom get_word_length
ki sprejme besedo kot vhod in vrne njeno dolžino.
Sedaj pa ustvarimo poziv za agenta. Poziv agentu naroči, kako naj sklepa in oblikuje izhod. V našem primeru uporabljamo klicanje funkcij OpenAI, ki zahteva minimalna navodila. Poziv bomo definirali z ogradami za uporabniški vnos in beležko agenta:
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"), ]
)
Kako agent ve, katera orodja lahko uporabi? Zanašamo se na jezikovne modele klicev funkcij OpenAI, ki zahtevajo ločeno posredovanje funkcij. Da posredniku zagotovimo naša orodja, jih bomo formatirali kot klice funkcij OpenAI:
from langchain.tools.render import format_tool_to_openai_function llm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools])
Zdaj lahko ustvarimo agenta tako, da definiramo vhodne preslikave in povežemo komponente:
To je jezik LCEL. O tem bomo podrobneje razpravljali pozneje.
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()
)
Ustvarili smo našega agenta, ki razume uporabniški vnos, uporablja razpoložljiva orodja in oblikuje izhod. Zdaj pa interakcijo z njim:
agent.invoke({"input": "how many letters in the word educa?", "intermediate_steps": []})
Agent se mora odzvati z AgentAction, ki nakazuje naslednje dejanje, ki ga je treba izvesti.
Agenta smo ustvarili, zdaj pa moramo zanj napisati izvajalno okolje. Najenostavnejše izvajalno okolje je tisto, ki nenehno kliče agenta, izvaja dejanja in se ponavlja, dokler agent ne konča. Tukaj je primer:
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)
V tej zanki vedno znova kličemo agenta, izvajamo dejanja in posodabljamo vmesne korake, dokler agent ne konča. Obravnavamo tudi interakcije orodij znotraj zanke.
Za poenostavitev tega procesa LangChain ponuja razred AgentExecutor, ki enkapsulira izvajanje agenta in ponuja obravnavanje napak, zgodnjo zaustavitev, sledenje in druge izboljšave. Uporabimo AgentExecutor za interakcijo z agentom:
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 poenostavlja postopek izvajanja in zagotavlja priročen način za interakcijo z agentom.
Pozneje bo podrobneje obravnavan tudi spomin.
Agent, ki smo ga do sedaj ustvarili, je brez stanja, kar pomeni, da se ne spomni prejšnjih interakcij. Če želimo omogočiti nadaljnja vprašanja in pogovore, moramo agentu dodati pomnilnik. To vključuje dva koraka:
- Dodajte pomnilniško spremenljivko v poziv za shranjevanje zgodovine klepeta.
- Med interakcijami spremljajte zgodovino klepeta.
Začnimo z dodajanjem pomnilniškega mesta v poziv:
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"), ]
)
Zdaj ustvarite seznam za sledenje zgodovini klepetov:
from langchain.schema.messages import HumanMessage, AIMessage chat_history = []
V koraku ustvarjanja agenta bomo vključili tudi pomnilnik:
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()
)
Zdaj, ko zaženete agenta, poskrbite, da posodobite zgodovino klepeta:
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})
To agentu omogoča, da vzdržuje zgodovino pogovorov in odgovarja na dodatna vprašanja na podlagi prejšnjih interakcij.
čestitke! Uspešno ste ustvarili in izvedli svojega prvega agenta od konca do konca v LangChainu. Če se želite poglobiti v zmožnosti LangChaina, lahko raziščete:
- Podprte so različne vrste agentov.
- Vnaprej izdelani agenti
- Kako delati z orodji in integracijami orodij.
Vrste agentov
LangChain ponuja različne vrste agentov, od katerih je vsak primeren za posebne primere uporabe. Tukaj je nekaj razpoložljivih agentov:
- Zero-shot ReAct: Ta agent uporablja okvir ReAct za izbiro orodij izključno na podlagi njihovih opisov. Zahteva opise za vsako orodje in je zelo vsestransko uporaben.
- Strukturiran vnos ReAct: Ta agent upravlja z orodji za več vnosov in je primeren za zapletene naloge, kot je krmarjenje po spletnem brskalniku. Za strukturiran vnos uporablja shemo argumentov orodij.
- Funkcije OpenAI: Posebej zasnovan za modele, natančno nastavljene za klicanje funkcij, je ta agent združljiv z modeli, kot sta gpt-3.5-turbo-0613 in gpt-4-0613. To smo uporabili za ustvarjanje našega prvega agenta zgoraj.
- Pogovorno: Ta agent, zasnovan za pogovorne nastavitve, uporablja ReAct za izbiro orodij in uporablja pomnilnik za zapomnitev prejšnjih interakcij.
- Samosprašuj z iskanjem: Ta agent se zanaša na eno samo orodje, »Vmesni odgovor«, ki poišče dejanske odgovore na vprašanja. Enakovredno je izvirnemu samospraševanju z iskalnim listom.
- Shramba dokumentov ReAct: Ta agent komunicira s shrambo dokumentov z uporabo ogrodja ReAct. Zahteva orodji »Iskanje« in »Iskanje« in je podoben primeru izvirnega dokumenta ReAct iz Wikipedije.
Raziščite te vrste agentov in poiščite tistega, ki najbolj ustreza vašim potrebam v LangChainu. Ti agenti vam omogočajo, da znotraj njih povežete nabor orodij za upravljanje dejanj in ustvarjanje odgovorov. Več o tem kako zgraditi svojega agenta z orodji tukaj.
Predizdelani agenti
Nadaljujmo z raziskovanjem agentov in se osredotočimo na vnaprej pripravljene agente, ki so na voljo v LangChainu.
Gmail
LangChain ponuja komplet orodij za Gmail, ki vam omogoča povezavo vaše e-pošte LangChain z API-jem za Gmail. Če želite začeti, boste morali nastaviti svoje poverilnice, ki so razložene v dokumentaciji API-ja za Gmail. Ko prenesete credentials.json
datoteko, lahko nadaljujete z uporabo Gmail API-ja. Poleg tega boste morali namestiti nekaj zahtevanih knjižnic z naslednjimi ukazi:
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
Zbirko orodij za Gmail lahko ustvarite na naslednji način:
from langchain.agents.agent_toolkits import GmailToolkit toolkit = GmailToolkit()
Preverjanje pristnosti lahko tudi prilagodite svojim potrebam. V zakulisju se vir googleapi ustvari z uporabo naslednjih metod:
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)
Komplet orodij ponuja različna orodja, ki jih je mogoče uporabiti znotraj agenta, vključno z:
GmailCreateDraft
: ustvarite osnutek e-pošte z določenimi polji sporočila.GmailSendMessage
: pošiljanje e-poštnih sporočil.GmailSearch
: poiščite e-poštna sporočila ali niti.GmailGetMessage
: Pridobite e-pošto po ID-ju sporočila.GmailGetThread
: poiščite e-poštna sporočila.
Za uporabo teh orodij znotraj agenta lahko agenta inicializirate na naslednji način:
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,
)
Tu je nekaj primerov uporabe teh orodij:
- Ustvarite Gmailov osnutek za urejanje:
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."
)
- Poiščite najnovejšo e-pošto v svojih osnutkih:
agent.run("Could you search in my drafts for the latest email?")
Ti primeri prikazujejo zmožnosti kompleta orodij Gmail podjetja LangChain znotraj posrednika, kar vam omogoča programsko interakcijo z Gmailom.
Agent baze podatkov SQL
Ta razdelek ponuja pregled agenta, zasnovanega za interakcijo z bazami podatkov SQL, zlasti z bazo podatkov Chinook. Ta agent lahko odgovori na splošna vprašanja o zbirki podatkov in obnovi napake. Upoštevajte, da je še vedno v aktivnem razvoju in morda niso vsi odgovori pravilni. Bodite previdni, ko ga izvajate na občutljivih podatkih, saj lahko izvede stavke DML v vaši bazi podatkov.
Če želite uporabiti tega agenta, ga lahko inicializirate na naslednji način:
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,
)
Ta agent je mogoče inicializirati z uporabo ZERO_SHOT_REACT_DESCRIPTION
vrsta agenta. Namenjen je odgovarjanju na vprašanja in zagotavljanju opisov. Druga možnost je, da agenta inicializirate z uporabo OPENAI_FUNCTIONS
tip agenta z modelom GPT-3.5-turbo OpenAI, ki smo ga uporabili v prejšnjem odjemalcu.
Zavrnitev odgovornosti
- Veriga poizvedb lahko ustvari poizvedbe za vstavljanje/posodabljanje/brisanje. Bodite previdni in po potrebi uporabite poziv po meri ali ustvarite uporabnika SQL brez dovoljenj za pisanje.
- Zavedajte se, da lahko izvajanje določenih poizvedb, kot je »zaženi največjo možno poizvedbo«, preobremeni vašo bazo podatkov SQL, še posebej, če vsebuje na milijone vrstic.
- Baze podatkov, usmerjene v skladišče podatkov, pogosto podpirajo kvote na ravni uporabnika za omejitev uporabe virov.
Agenta lahko prosite, da opiše tabelo, na primer tabelo »playlisttrack«. Tukaj je primer, kako to storiti:
agent_executor.run("Describe the playlisttrack table")
Agent bo zagotovil informacije o shemi tabele in vzorčnih vrsticah.
Če pomotoma vprašate za tabelo, ki ne obstaja, lahko posrednik obnovi in zagotovi informacije o tabeli, ki se najbližje ujema. Na primer:
agent_executor.run("Describe the playlistsong table")
Agent bo našel najbližjo ujemajočo se mizo in zagotovil informacije o njej.
Agenta lahko tudi prosite, naj izvaja poizvedbe v bazi podatkov. Na primer:
agent_executor.run("List the total sales per country. Which country's customers spent the most?")
Agent bo izvedel poizvedbo in zagotovil rezultat, na primer državo z največjo skupno prodajo.
Če želite pridobiti skupno število skladb na vsakem seznamu predvajanja, lahko uporabite naslednjo poizvedbo:
agent_executor.run("Show the total number of tracks in each playlist. The Playlist name should be included in the result.")
Agent bo vrnil imena seznamov predvajanja skupaj z ustreznim skupnim številom skladb.
V primerih, ko agent naleti na napake, lahko obnovi in zagotovi natančne odgovore. Na primer:
agent_executor.run("Who are the top 3 best selling artists?")
Tudi po začetni napaki se bo agent prilagodil in zagotovil pravilen odgovor, ki je v tem primeru top 3 najbolj prodajanih izvajalcev.
Agent Pandas DataFrame
Ta razdelek predstavlja agenta, zasnovanega za interakcijo s Pandas DataFrames za namene odgovarjanja na vprašanja. Upoštevajte, da ta agent uporablja agenta Python pod pokrovom za izvajanje kode Python, ustvarjene z jezikovnim modelom (LLM). Pri uporabi tega agenta bodite previdni, da preprečite morebitno škodo zaradi zlonamerne kode Python, ki jo ustvari LLM.
Agent Pandas DataFrame lahko inicializirate na naslednji način:
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,
# )
Agenta lahko prosite, da prešteje število vrstic v DataFrame:
agent.run("how many rows are there?")
Agent bo izvedel kodo df.shape[0]
in podajte odgovor, na primer "V podatkovnem okviru je 891 vrstic."
Zastopnika lahko tudi prosite, da filtrira vrstice na podlagi posebnih meril, kot je iskanje števila ljudi z več kot tremi brati in sestrami:
agent.run("how many people have more than 3 siblings")
Agent bo izvedel kodo df[df['SibSp'] > 3].shape[0]
in podajte odgovor, na primer "30 ljudi ima več kot 3 brate in sestre."
Če želite izračunati kvadratni koren povprečne starosti, lahko vprašate agenta:
agent.run("whats the square root of the average age?")
Agent bo izračunal povprečno starost z uporabo df['Age'].mean()
in nato izračunajte kvadratni koren z uporabo math.sqrt()
. Zagotovil bo odgovor, kot je "Kvadratni koren povprečne starosti je 5.449689683556195."
Ustvarimo kopijo DataFrame in manjkajoče starostne vrednosti se zapolnijo s srednjo starostjo:
df1 = df.copy()
df1["Age"] = df1["Age"].fillna(df1["Age"].mean())
Nato lahko agenta inicializirate z obema DataFrame in mu postavite vprašanje:
agent = create_pandas_dataframe_agent(OpenAI(temperature=0), [df, df1], verbose=True)
agent.run("how many rows in the age column are different?")
Agent bo primerjal starostne stolpce v obeh podatkovnih okvirih in zagotovil odgovor, na primer »177 vrstic v starostnem stolpcu je drugačnih«.
Zbirka orodij Jira
V tem razdelku je razloženo, kako uporabljati komplet orodij Jira, ki agentom omogoča interakcijo s primerkom Jira. S tem kompletom orodij lahko izvajate različna dejanja, kot je iskanje težav in ustvarjanje težav. Uporablja knjižnico atlassian-python-api. Za uporabo tega kompleta orodij morate nastaviti spremenljivke okolja za svoj primerek Jira, vključno z JIRA_API_TOKEN, JIRA_USERNAME in JIRA_INSTANCE_URL. Poleg tega boste morda morali nastaviti ključ OpenAI API kot spremenljivko okolja.
Za začetek namestite knjižnico atlassian-python-api in nastavite zahtevane spremenljivke okolja:
%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
)
Agentu lahko naročite, naj ustvari novo težavo v določenem projektu s povzetkom in opisom:
agent.run("make a new issue in project PW to remind me to make more fried rice")
Agent bo izvedel potrebna dejanja za ustvarjanje težave in zagotovil odgovor, na primer »V projektu PW je bila ustvarjena nova težava s povzetkom 'Naredite več ocvrtega riža' in opisom 'Opomnik za pripravo več ocvrtega riža'.«
To vam omogoča interakcijo z vašim primerkom Jira z uporabo navodil v naravnem jeziku in kompleta orodij Jira.
Avtomatizirajte ročna opravila in poteke dela z našim graditeljem potekov dela, ki ga poganja AI, ki ga je Nanonets zasnoval za vas in vaše ekipe.
Modul IV: Verige
LangChain je orodje, zasnovano za uporabo velikih jezikovnih modelov (LLM) v kompleksnih aplikacijah. Zagotavlja okvire za ustvarjanje verig komponent, vključno z LLM-ji in drugimi vrstami komponent. Dva primarna ogrodja
- Izrazni jezik LangChain (LCEL)
- Legacy Chain vmesnik
LangChain Expression Language (LCEL) je sintaksa, ki omogoča intuitivno sestavljanje verig. Podpira napredne funkcije, kot so pretakanje, asinhroni klici, pakiranje, paralelizacija, ponovni poskusi, nadomestni klici in sledenje. V LCEL lahko na primer sestavite poziv, model in izhodni razčlenjevalec, kot je prikazano v naslednji kodi:
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)
Druga možnost je LLMChain, podobna možnost LCEL za sestavljanje komponent. Primer LLMChain je naslednji:
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")
Verige v LangChainu so lahko tudi zaznavne z vključitvijo predmeta Memory. To omogoča obstojnost podatkov med klici, kot je prikazano v tem primeru:
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 podpira tudi integracijo z API-ji OpenAI za klicanje funkcij, kar je uporabno za pridobivanje strukturiranih izhodov in izvajanje funkcij znotraj verige. Za pridobivanje strukturiranih izhodov jih lahko določite z uporabo razredov Pydantic ali JsonSchema, kot je prikazano spodaj:
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"})
Za strukturirane rezultate je na voljo tudi stari pristop z uporabo LLMChain:
from langchain.chains.openai_functions import create_structured_output_chain class Person(BaseModel): name: str = Field(..., description="The person's name") age: int = Field(..., description="The person's age") chain = create_structured_output_chain(Person, llm, prompt, verbose=True)
chain.run("Sally is 13")
LangChain uporablja funkcije OpenAI za ustvarjanje različnih specifičnih verig za različne namene. Ti vključujejo verige za ekstrakcijo, označevanje, OpenAPI in QA s citati.
V kontekstu ekstrakcije je postopek podoben strukturirani izhodni verigi, vendar se osredotoča na ekstrakcijo informacij ali entitet. Pri označevanju je ideja označiti dokument z razredi, kot so čustva, jezik, slog, obravnavane teme ali politične težnje.
Primer, kako deluje označevanje v LangChain, je mogoče prikazati s kodo Python. Postopek se začne z namestitvijo potrebnih paketov in nastavitvijo okolja:
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
Definirana je shema za označevanje, ki določa lastnosti in njihove pričakovane vrste:
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)
Primeri izvajanja verige označevanja z različnimi vhodi kažejo sposobnost modela za interpretacijo čustev, jezikov in agresivnosti:
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'}
Za natančnejši nadzor je mogoče shemo definirati natančneje, vključno z možnimi vrednostmi, opisi in zahtevanimi lastnostmi. Spodaj je prikazan primer tega izboljšanega nadzora:
schema = { "properties": { # Schema definitions here }, "required": ["language", "sentiment", "aggressiveness"],
} chain = create_tagging_chain(schema, llm)
Pydantic sheme se lahko uporabljajo tudi za definiranje kriterijev označevanja, kar zagotavlja način Pythonic za določanje zahtevanih lastnosti in vrst:
from enum import Enum
from pydantic import BaseModel, Field class Tags(BaseModel): # Class fields here chain = create_tagging_chain_pydantic(Tags, llm)
Poleg tega lahko LangChainov pretvornik dokumentov za označevanje metapodatkov uporabite za ekstrahiranje metapodatkov iz dokumentov LangChain, ki ponuja podobno funkcionalnost kot veriga označevanja, vendar se uporablja za dokument LangChain.
Navajanje virov za iskanje je še ena funkcija LangChaina, ki uporablja funkcije OpenAI za pridobivanje citatov iz besedila. To je prikazano v naslednji kodi:
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
V LangChainu veriženje v aplikacijah Large Language Model (LLM) običajno vključuje kombiniranje predloge poziva z LLM in po izbiri izhodnega razčlenjevalnika. Priporočeni način za to je jezik LangChain Expression Language (LCEL), čeprav je podprt tudi starejši pristop LLMChain.
Z uporabo LCEL vsi BasePromptTemplate, BaseLanguageModel in BaseOutputParser implementirajo vmesnik Runnable in jih je mogoče preprosto napeljati drug v drugega. Tukaj je primer, ki to dokazuje:
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'
Usmerjanje v LangChainu omogoča ustvarjanje nedeterminističnih verig, kjer rezultat prejšnjega koraka določa naslednji korak. To pomaga pri strukturiranju in ohranjanju doslednosti v interakcijah z LLM. Če imate na primer dve predlogi, optimizirani za različne vrste vprašanj, lahko izberete predlogo na podlagi uporabniškega vnosa.
Tukaj je opisano, kako lahko to dosežete z uporabo LCEL z RunnableBranch, ki je inicializiran s seznamom parov (stanje, izvedljivo) in privzeto izvedljivo:
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
Končna veriga je nato sestavljena z uporabo različnih komponent, kot so klasifikator tem, veja poziva in razčlenjevalnik izhoda, da se določi tok na podlagi teme vnosa:
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
Ta pristop ponazarja prilagodljivost in moč LangChaina pri obravnavanju zapletenih poizvedb in njihovem ustreznem usmerjanju na podlagi vnosa.
Na področju jezikovnih modelov je običajna praksa, da začetnemu klicu sledi niz naslednjih klicev, pri čemer se izhod enega klica uporablja kot vhod za naslednjega. Ta zaporedni pristop je še posebej koristen, če želite graditi na informacijah, pridobljenih v prejšnjih interakcijah. Čeprav je jezik LangChain Expression Language (LCEL) priporočena metoda za ustvarjanje teh zaporedij, je metoda SequentialChain še vedno dokumentirana zaradi svoje združljivosti za nazaj.
Za ponazoritev tega razmislimo o scenariju, kjer najprej ustvarimo sinopsis igre in nato recenzijo na podlagi tega sinopsisa. Uporaba Pythona langchain.prompts
, ustvarimo dva PromptTemplate
primerki: eden za sinopsis in drugi za pregled. Tu je koda za nastavitev teh predlog:
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:"
)
V pristopu LCEL povezujemo te pozive z ChatOpenAI
in StrOutputParser
ustvariti zaporedje, ki najprej ustvari povzetek in nato recenzijo. Delček kode je naslednji:
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"})
Če potrebujemo sinopsis in pregled, lahko uporabimo RunnablePassthrough
ustvarite ločeno verigo za vsakega in jih nato združite:
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"})
Za scenarije, ki vključujejo bolj zapletena zaporedja, je SequentialChain
metoda pride v poštev. To omogoča več vhodov in izhodov. Razmislite o primeru, ko potrebujemo sinopsis, ki temelji na naslovu in obdobju predstave. Takole ga lahko nastavimo:
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"})
V scenarijih, kjer želite ohraniti kontekst v celotni verigi ali za kasnejši del verige, SimpleMemory
je lahko uporabljen. To je še posebej uporabno za upravljanje kompleksnih vhodno/izhodnih razmerij. Na primer, v scenariju, kjer želimo ustvariti objave v družabnih omrežjih na podlagi naslova predstave, obdobja, sinopsisa in ocene, SimpleMemory
lahko pomaga upravljati te spremenljivke:
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"})
Poleg zaporednih verig obstajajo specializirane verige za delo z dokumenti. Vsaka od teh verig služi drugačnemu namenu, od združevanja dokumentov do izboljšanja odgovorov na podlagi ponavljajoče se analize dokumenta do preslikave in zmanjševanja vsebine dokumenta za povzemanje ali ponovno razvrščanje na podlagi ocenjenih odgovorov. Te verige je mogoče ponovno ustvariti z LCEL za dodatno prilagodljivost in prilagajanje.
-
StuffDocumentsChain
združi seznam dokumentov v en sam poziv, posredovan LLM. -
RefineDocumentsChain
posodablja svoj odgovor iterativno za vsak dokument, kar je primerno za naloge, kjer dokumenti presegajo zmogljivost konteksta modela. -
MapReduceDocumentsChain
uporabi verigo za vsak dokument posebej in nato združi rezultate. -
MapRerankDocumentsChain
oceni vsak odgovor na podlagi dokumenta in izbere tistega z najvišjo oceno.
Tukaj je primer, kako lahko nastavite a MapReduceDocumentsChain
z uporabo 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")
Ta konfiguracija omogoča podrobno in celovito analizo vsebine dokumenta, pri čemer izkorišča prednosti LCEL in osnovnega jezikovnega modela.
Avtomatizirajte ročna opravila in poteke dela z našim graditeljem potekov dela, ki ga poganja AI, ki ga je Nanonets zasnoval za vas in vaše ekipe.
Modul V : Spomin
V LangChainu je spomin temeljni vidik pogovornih vmesnikov, ki omogoča sistemom, da se sklicujejo na pretekle interakcije. To se doseže s shranjevanjem in poizvedovanjem po informacijah z dvema primarnima dejanjema: branjem in pisanjem. Pomnilniški sistem med potekom dvakrat sodeluje z verigo, s čimer poveča uporabniške vnose in shrani vhode in izhode za prihodnjo uporabo.
Vgradnja pomnilnika v sistem
- Shranjevanje sporočil klepeta: Pomnilniški modul LangChain združuje različne metode za shranjevanje sporočil klepeta, od seznamov v pomnilniku do baz podatkov. To zagotavlja, da so vse interakcije v klepetu zabeležene za prihodnjo uporabo.
- Poizvedovanje po sporočilih klepeta: Poleg shranjevanja sporočil klepeta LangChain uporablja podatkovne strukture in algoritme za ustvarjanje uporabnega pogleda na ta sporočila. Preprosti pomnilniški sistemi lahko vrnejo nedavna sporočila, medtem ko bi naprednejši sistemi lahko povzeli pretekle interakcije ali se osredotočili na entitete, omenjene v trenutni interakciji.
Če želite prikazati uporabo pomnilnika v LangChainu, upoštevajte ConversationBufferMemory
class, preprost pomnilniški obrazec, ki shranjuje sporočila klepeta v medpomnilnik. Tukaj je primer:
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?")
Pri vključevanju pomnilnika v verigo je ključno razumeti spremenljivke, vrnjene iz pomnilnika, in kako se uporabljajo v verigi. Na primer, load_memory_variables
metoda pomaga uskladiti spremenljivke, prebrane iz pomnilnika, s pričakovanji verige.
Primer od konca do konca z LangChain
Razmislite o uporabi ConversationBufferMemory
v LLMChain
. Veriga v kombinaciji z ustrezno predlogo poziva in pomnilnikom zagotavlja brezhibno pogovorno izkušnjo. Tukaj je poenostavljen primer:
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?"})
Ta primer ponazarja, kako se pomnilniški sistem LangChain integrira s svojimi verigami, da zagotovi skladno in kontekstualno ozaveščeno pogovorno izkušnjo.
Vrste pomnilnika v Langchainu
Langchain ponuja različne vrste pomnilnika, ki jih je mogoče uporabiti za izboljšanje interakcij z modeli AI. Vsaka vrsta pomnilnika ima svoje parametre in povratne vrste, zaradi česar so primerni za različne scenarije. Raziščimo nekatere vrste pomnilnika, ki so na voljo v Langchainu, skupaj s primeri kode.
1. Medpomnilnik za pogovore
Ta vrsta pomnilnika vam omogoča shranjevanje in ekstrahiranje sporočil iz pogovorov. Zgodovino lahko izvlečete kot niz ali kot seznam sporočil.
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={})]}
Pomnilnik medpomnilnika pogovorov lahko uporabite tudi v verigi za interakcije, podobne klepetu.
2. Pomnilnik okna medpomnilnika pogovorov
Ta vrsta pomnilnika hrani seznam nedavnih interakcij in uporablja zadnjih K interakcij, kar preprečuje, da bi medpomnilnik postal prevelik.
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'}
Tako kot Conversation Buffer Memory lahko tudi to vrsto pomnilnika uporabite v verigi za interakcije, podobne klepetu.
3. Pomnilnik entitete pogovora
Ta vrsta pomnilnika si zapomni dejstva o določenih entitetah v pogovoru in izvleče informacije z uporabo 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. Grafikon pogovornega spomina
Ta vrsta pomnilnika uporablja graf znanja za ponovno ustvarjanje pomnilnika. Iz sporočil lahko izvlečete trenutne entitete in trojčke znanja.
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.'}
To vrsto pomnilnika lahko uporabite tudi v verigi za iskanje znanja na podlagi pogovorov.
5. Pomnilnik povzetka pogovora
Ta vrsta pomnilnika ustvari povzetek pogovora skozi čas, kar je uporabno za zgoščevanje informacij iz daljših pogovorov.
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. Medpomnilnik povzetka pogovora
Ta vrsta pomnilnika združuje povzetek pogovora in medpomnilnik ter ohranja ravnovesje med nedavnimi interakcijami in povzetkom. Uporablja dolžino žetona, da določi, kdaj izprazniti interakcije.
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'}
Te vrste pomnilnika lahko uporabite za izboljšanje interakcij z modeli AI v Langchainu. Vsaka vrsta pomnilnika služi določenemu namenu in jo je mogoče izbrati glede na vaše zahteve.
7. Medpomnilnik žetona pogovora
ConversationTokenBufferMemory je še ena vrsta pomnilnika, ki v pomnilniku hrani medpomnilnik nedavnih interakcij. Za razliko od prejšnjih vrst pomnilnika, ki se osredotočajo na število interakcij, ta uporablja dolžino žetona za določanje, kdaj izprazniti interakcije.
Uporaba pomnilnika z 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'}
V tem primeru je pomnilnik nastavljen tako, da omeji interakcije na podlagi dolžine žetona in ne števila interakcij.
Pri uporabi te vrste pomnilnika lahko zgodovino dobite tudi kot seznam sporočil.
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"})
Uporaba v verigi:
ConversationTokenBufferMemory lahko uporabite v verigi za izboljšanje interakcij z modelom AI.
from langchain.chains import ConversationChain conversation_with_summary = ConversationChain( llm=llm, # We set a very low max_token_limit for the purposes of testing. memory=ConversationTokenBufferMemory(llm=OpenAI(), max_token_limit=60), verbose=True,
)
conversation_with_summary.predict(input="Hi, what's up?")
V tem primeru se ConversationTokenBufferMemory uporablja v ConversationChain za upravljanje pogovora in omejevanje interakcij na podlagi dolžine žetona.
8. VectorStoreRetrieverMemory
VectorStoreRetrieverMemory shrani spomine v vektorsko shrambo in vsakič, ko je priklicana, poizveduje po K najbolj »pomembnih« dokumentih. Ta vrsta pomnilnika ne sledi eksplicitno vrstnemu redu interakcij, ampak uporablja vektorsko iskanje za pridobivanje ustreznih spominov.
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"])
V tem primeru se VectorStoreRetrieverMemory uporablja za shranjevanje in pridobivanje ustreznih informacij iz pogovora na podlagi vektorskega pridobivanja.
VectorStoreRetrieverMemory lahko uporabite tudi v verigi za pridobivanje znanja na podlagi pogovora, kot je prikazano v prejšnjih primerih.
Te različne vrste pomnilnika v Langchainu zagotavljajo različne načine za upravljanje in pridobivanje informacij iz pogovorov, kar izboljšuje zmogljivosti modelov AI pri razumevanju in odzivanju na uporabniške poizvedbe in kontekst. Vsako vrsto pomnilnika lahko izberete glede na posebne zahteve vaše aplikacije.
Zdaj se bomo naučili uporabljati pomnilnik z LLMChain. Pomnilnik v verigi LLMChain omogoča modelu, da si zapomni prejšnje interakcije in kontekst, da zagotovi bolj skladne odzive, ki se zavedajo konteksta.
Če želite nastaviti pomnilnik v LLMChain, morate ustvariti pomnilniški razred, kot je ConversationBufferMemory. To lahko nastavite tako:
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")
V tem primeru se ConversationBufferMemory uporablja za shranjevanje zgodovine pogovorov. The memory_key
parameter določa ključ, ki se uporablja za shranjevanje zgodovine pogovorov.
Če uporabljate model klepeta namesto modela v slogu dokončanja, lahko svoje pozive strukturirate drugače, da bolje izkoristite pomnilnik. Tukaj je primer, kako nastaviti LLMChain na osnovi modela klepeta s pomnilnikom:
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")
V tem primeru se ChatPromptTemplate uporablja za strukturiranje poziva, ConversationBufferMemory pa se uporablja za shranjevanje in pridobivanje zgodovine pogovorov. Ta pristop je še posebej uporaben za pogovore v slogu klepeta, kjer imata kontekst in zgodovina ključno vlogo.
Pomnilnik je mogoče dodati tudi v verigo z več vhodi, kot je veriga vprašanj/odgovorov. Tukaj je primer, kako nastaviti pomnilnik v verigi vprašanj/odgovorov:
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)
V tem primeru je na vprašanje odgovorjeno z uporabo dokumenta, razdeljenega na manjše dele. ConversationBufferMemory se uporablja za shranjevanje in pridobivanje zgodovine pogovorov, kar modelu omogoča zagotavljanje odgovorov, ki se zavedajo konteksta.
Če agentu dodate pomnilnik, mu omogočite, da si zapomni in uporabi prejšnje interakcije, da odgovori na vprašanja in zagotovi odgovore, ki se zavedajo konteksta. Tukaj je opisano, kako lahko nastavite pomnilnik v agentu:
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)
V tem primeru je agentu dodan pomnilnik, ki mu omogoča, da si zapomni prejšnjo zgodovino pogovorov in zagotovi odgovore, ki se zavedajo konteksta. To agentu omogoča, da natančno odgovori na dodatna vprašanja na podlagi informacij, shranjenih v pomnilniku.
Izrazni jezik LangChain
V svetu obdelave naravnega jezika in strojnega učenja je lahko sestavljanje zapletenih verig operacij zastrašujoča naloga. Na srečo na pomoč priskoči jezik LangChain Expression Language (LCEL), ki zagotavlja deklarativen in učinkovit način za gradnjo in uvajanje sofisticiranih cevovodov za obdelavo jezikov. LCEL je zasnovan tako, da poenostavi proces sestavljanja verig, kar omogoča enostaven prehod od izdelave prototipov do proizvodnje. V tem blogu bomo raziskali, kaj je LCEL in zakaj bi ga morda želeli uporabiti, skupaj s praktičnimi primeri kode za ponazoritev njegovih zmogljivosti.
LCEL ali LangChain Expression Language je močno orodje za sestavljanje verig jezikovne obdelave. Izdelan je bil namensko za nemoteno podporo prehoda iz izdelave prototipov v proizvodnjo, ne da bi zahteval obsežne spremembe kode. Ne glede na to, ali gradite preprosto verigo »poziv + LLM« ali zapleten cevovod s stotinami korakov, vas LCEL pokriva.
Tukaj je nekaj razlogov za uporabo LCEL v vaših projektih jezikovne obdelave:
- Hitro pretakanje žetonov: LCEL dostavi žetone iz jezikovnega modela v izhodni razčlenjevalnik v realnem času, kar izboljša odzivnost in učinkovitost.
- Vsestranski API-ji: LCEL podpira sinhrone in asinhrone API-je za izdelavo prototipov in produkcijsko uporabo ter učinkovito obravnava več zahtev.
- Samodejna paralelizacija: LCEL optimizira vzporedno izvajanje, kadar je to mogoče, in zmanjša zakasnitev v sinhronizacijskih in asinhronskih vmesnikih.
- Zanesljive konfiguracije: Konfigurirajte ponovne poskuse in nadomestne možnosti za izboljšano zanesljivost verige v velikem obsegu s podporo za pretakanje v razvoju.
- Pretok vmesnih rezultatov: dostop do vmesnih rezultatov med obdelavo za posodobitve uporabnikov ali namene odpravljanja napak.
- Generiranje sheme: LCEL ustvari sheme Pydantic in JSONSchema za validacijo vhoda in izhoda.
- Celovito sledenje: LangSmith samodejno sledi vsem korakom v zapletenih verigah za opazovanje in odpravljanje napak.
- Enostavna uvedba: z LangServe brez težav uvedite verige, ustvarjene z LCEL.
Zdaj pa se poglobimo v praktične primere kode, ki prikazujejo moč LCEL. Raziskali bomo pogoste naloge in scenarije, kjer LCEL blesti.
Poziv + LLM
Najbolj temeljna sestava vključuje združevanje poziva in jezikovnega modela za ustvarjanje verige, ki sprejme uporabniški vnos, ga doda pozivu, posreduje modelu in vrne neobdelane rezultate modela. Tukaj je primer:
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)
V tem primeru veriga ustvari šalo o medvedih.
Svoji verigi lahko pripnete zaustavitvena zaporedja, da nadzirate, kako obdeluje besedilo. Na primer:
chain = prompt | model.bind(stop=["n"])
result = chain.invoke({"foo": "bears"})
print(result)
Ta konfiguracija ustavi generiranje besedila, ko se pojavi znak za novo vrstico.
LCEL podpira pripenjanje informacij o klicu funkcije v vašo verigo. Tukaj je primer:
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)
Ta primer doda informacije o klicu funkcije za ustvarjanje šale.
Poziv + LLM + OutputParser
Dodate lahko razčlenjevalnik izhoda, da pretvorite neobdelani izhod modela v bolj uporaben format. Takole lahko to storite:
from langchain.schema.output_parser import StrOutputParser chain = prompt | model | StrOutputParser()
result = chain.invoke({"foo": "bears"})
print(result)
Izhod je zdaj v nizovnem formatu, kar je bolj priročno za nadaljnja opravila.
Ko podajate funkcijo za vrnitev, jo lahko razčlenite neposredno z LCEL. Na primer:
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)
Ta primer neposredno razčleni izhod funkcije "joke".
To je le nekaj primerov, kako LCEL poenostavi zapletene naloge jezikovne obdelave. Ne glede na to, ali gradite klepetalne robote, ustvarjate vsebino ali izvajate zapletene transformacije besedila, lahko LCEL poenostavi vaš potek dela in naredi vašo kodo bolj vzdržljivo.
RAG (Generacija, razširjena s pridobivanjem)
LCEL je mogoče uporabiti za ustvarjanje generacijskih verig, razširjenih s pridobivanjem, ki združujejo korake pridobivanja in generiranja jezika. Tukaj je primer:
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)
V tem primeru veriga pridobi ustrezne informacije iz konteksta in ustvari odgovor na vprašanje.
Pogovorna veriga iskanja
Svojim verigam lahko preprosto dodate zgodovino pogovorov. Tukaj je primer verige pogovornega iskanja:
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)
V tem primeru veriga obravnava nadaljnje vprašanje v kontekstu pogovora.
S pomnilnikom in vračanjem izvornih dokumentov
LCEL podpira tudi pomnilnik in vračanje izvornih dokumentov. Tukaj je opisano, kako lahko uporabite pomnilnik v verigi:
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)
V tem primeru se pomnilnik uporablja za shranjevanje in pridobivanje zgodovine pogovorov in izvornih dokumentov.
Več verig
Z uporabo Runnables lahko povežete več verig. Tukaj je primer:
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)
V tem primeru sta dve verigi združeni za ustvarjanje informacij o mestu in njegovi državi v določenem jeziku.
Razvejanje in spajanje
LCEL vam omogoča razdeljevanje in združevanje verig z uporabo RunnableMaps. Tukaj je primer razvejanja in združevanja:
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)
V tem primeru se veriga razvejanja in združevanja uporablja za ustvarjanje argumenta in ovrednotenje njegovih prednosti in slabosti, preden se ustvari končni odgovor.
Pisanje kode Python z LCEL
Ena izmed zmogljivih aplikacij jezika LangChain Expression Language (LCEL) je pisanje kode Python za reševanje uporabniških težav. Spodaj je primer uporabe LCEL za pisanje kode Python:
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain_experimental.utilities import PythonREPL template = """Write some python code to solve the user's problem. Return only python code in Markdown format, e.g.: ```python
....
```"""
prompt = ChatPromptTemplate.from_messages([("system", template), ("human", "{input}")]) model = ChatOpenAI() def _sanitize_output(text: str): _, after = text.split("```python") return after.split("```")[0] chain = prompt | model | StrOutputParser() | _sanitize_output | PythonREPL().run result = chain.invoke({"input": "what's 2 plus 2"})
print(result)
V tem primeru uporabnik zagotovi vnos, LCEL pa ustvari kodo Python za rešitev težave. Koda se nato izvede z uporabo Python REPL, nastala koda Python pa se vrne v formatu Markdown.
Upoštevajte, da lahko uporaba Python REPL izvede poljubno kodo, zato jo uporabljajte previdno.
Dodajanje pomnilnika v verigo
Pomnilnik je bistvenega pomena v številnih pogovornih aplikacijah AI. Tukaj je opisano, kako dodate pomnilnik poljubni verigi:
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({})
V tem primeru se pomnilnik uporablja za shranjevanje in pridobivanje zgodovine pogovorov, kar chatbotu omogoča, da vzdržuje kontekst in se ustrezno odzove.
Uporaba zunanjih orodij z Runnables
LCEL vam omogoča brezhibno integracijo zunanjih orodij z Runnables. Tukaj je primer uporabe orodja DuckDuckGo Search:
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)
V tem primeru LCEL integrira orodje DuckDuckGo Search v verigo, kar mu omogoča ustvarjanje iskalne poizvedbe iz uporabniškega vnosa in pridobivanje rezultatov iskanja.
Prilagodljivost LCEL olajša vključevanje različnih zunanjih orodij in storitev v vaše cevovode za jezikovno obdelavo, kar izboljša njihove zmogljivosti in funkcionalnost.
Dodajanje moderiranja aplikaciji LLM
Če želite zagotoviti, da vaša aplikacija LLM upošteva pravilnike o vsebini in vključuje zaščitne ukrepe za moderiranje, lahko v svojo verigo vključite preverjanja moderiranja. Tukaj je opisano, kako dodate moderiranje z uporabo 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)
V tem primeru je OpenAIModerationChain
se uporablja za dodajanje moderacije odzivu, ki ga ustvari LLM. Veriga moderiranja preveri odziv za vsebino, ki krši politiko vsebine OpenAI. Če odkrije kakršne koli kršitve, bo odgovor ustrezno označil.
Usmerjanje po pomenski podobnosti
LCEL vam omogoča implementacijo logike usmerjanja po meri na podlagi semantične podobnosti uporabniškega vnosa. Tukaj je primer, kako dinamično določiti logiko verige na podlagi uporabniškega vnosa:
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"}))
V tem primeru je prompt_router
funkcija izračuna podobnost kosinusa med uporabniškim vnosom in vnaprej določenimi pozivnimi predlogami za vprašanja fizike in matematike. Na podlagi ocene podobnosti veriga dinamično izbere najbolj ustrezno predlogo poziva, s čimer zagotovi, da se chatbot ustrezno odzove na uporabnikovo vprašanje.
Uporaba agentov in izvajalnih elementov
LangChain vam omogoča ustvarjanje agentov s kombiniranjem Runnables, pozivov, modelov in orodij. Tukaj je primer gradnje agenta in njegove uporabe:
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)
V tem primeru je agent ustvarjen s kombinacijo modela, orodij, poziva in logike po meri za vmesne korake in pretvorbo orodja. Agent se nato izvede in zagotovi odgovor na uporabnikovo poizvedbo.
Poizvedovanje po bazi podatkov SQL
LangChain lahko uporabite za poizvedovanje po bazi podatkov SQL in ustvarjanje poizvedb SQL na podlagi uporabniških vprašanj. Tukaj je primer:
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)
V tem primeru se LangChain uporablja za ustvarjanje poizvedb SQL na podlagi uporabniških vprašanj in pridobivanje odgovorov iz baze podatkov SQL. Pozivi in odgovori so oblikovani tako, da zagotavljajo naravne jezikovne interakcije z bazo podatkov.
Avtomatizirajte ročna opravila in poteke dela z našim graditeljem potekov dela, ki ga poganja AI, ki ga je Nanonets zasnoval za vas in vaše ekipe.
LangServe & LangSmith
LangServe razvijalcem pomaga pri uvajanju zagonskih elementov in verig LangChain kot REST API. Ta knjižnica je integrirana s FastAPI in uporablja pydantic za preverjanje podatkov. Poleg tega ponuja odjemalca, ki ga je mogoče uporabiti za klic v runnables, nameščene na strežniku, odjemalec JavaScript pa je na voljo v LangChainJS.
Lastnosti
- Vhodne in izhodne sheme se samodejno izpeljejo iz vašega predmeta LangChain in uveljavijo pri vsakem klicu API-ja z bogatimi sporočili o napakah.
- Na voljo je stran z dokumenti API-ja z JSONSchema in Swagger.
- Učinkovite končne točke /invoke, /batch in /stream s podporo za številne sočasne zahteve na enem strežniku.
- /stream_log končna točka za pretakanje vseh (ali nekaterih) vmesnih korakov iz vaše verige/agenta.
- Stran igrišča na /playground s pretočnim izhodom in vmesnimi koraki.
- Vgrajeno (izbirno) sledenje v LangSmith; samo dodajte svoj ključ API (glejte Navodila).
- Vse zgrajeno z odprtokodnimi knjižnicami Python, preizkušenimi v bitkah, kot so FastAPI, Pydantic, uvloop in asyncio.
Omejitve
- Povratni klici odjemalcev še niso podprti za dogodke, ki izvirajo iz strežnika.
- Dokumenti OpenAPI ne bodo ustvarjeni pri uporabi Pydantic V2. FastAPI ne podpira mešanja imenskih prostorov pydantic v1 in v2. Za več podrobnosti glejte spodnji razdelek.
Uporabite LangChain CLI za hiter zagon projekta LangServe. Za uporabo langchain CLI se prepričajte, da imate nameščeno najnovejšo različico langchain-cli. Namestite ga lahko s pip install -U langchain-cli.
langchain app new ../path/to/directory
Hitro zaženite svoj primerek LangServe s predlogami LangChain. Za več primerov si oglejte kazalo predlog ali imenik primerov.
Tukaj je strežnik, ki uporablja model klepeta OpenAI, model klepeta Anthropic in verigo, ki uporablja model Anthropic za pripovedovanje šale o temi.
#!/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)
Ko namestite zgornji strežnik, si lahko ogledate ustvarjene dokumente OpenAPI z:
curl localhost:8000/docs
Ne pozabite dodati pripone /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" }])
V TypeScript (zahteva LangChain.js različice 0.0.166 ali novejšo):
import { RemoteRunnable } from "langchain/runnables/remote"; const chain = new RemoteRunnable({ url: `http://localhost:8000/chain/invoke/`,
});
const result = await chain.invoke({ topic: "cats",
});
Python z uporabo zahtev:
import requests
response = requests.post( "http://localhost:8000/chain/invoke/", json={'input': {'topic': 'cats'}}
)
response.json()
Uporabite lahko tudi curl:
curl --location --request POST 'http://localhost:8000/chain/invoke/' --header 'Content-Type: application/json' --data-raw '{ "input": { "topic": "cats" } }'
Naslednja koda:
...
add_routes( app, runnable, path="/my_runnable",
)
strežniku doda teh končnih točk:
- POST /my_runnable/invoke – prikliči runnable pri enem vnosu
- POST /my_runnable/batch – prikliči runnable na paketu vnosov
- POST /my_runnable/stream – prikliči na en vhod in pretoči izhod
- POST /my_runnable/stream_log – prikliči na en sam vhod in pretočno pretaka izhod, vključno z izhodom vmesnih korakov, ko je ustvarjen
- GET /my_runnable/input_schema – shema json za vnos v runnable
- GET /my_runnable/output_schema – shema json za izpis runnable
- GET /my_runnable/config_schema – shema json za konfiguracijo runnable
Stran z igriščem za svoj runnable najdete na /my_runnable/playground. To razkrije preprost uporabniški vmesnik za konfiguriranje in priklic vašega zagonskega elementa s pretočnim izhodom in vmesnimi koraki.
Za odjemalca in strežnik:
pip install "langserve[all]"
ali pip install “langserve[client]” za kodo odjemalca in pip install “langserve[server]” za kodo strežnika.
Če morate svojemu strežniku dodati preverjanje pristnosti, si oglejte varnostno dokumentacijo FastAPI in dokumentacijo o vmesni programski opremi.
V GCP Cloud Run lahko uvedete z naslednjim ukazom:
gcloud run deploy [your-service-name] --source . --port 8001 --allow-unauthenticated --region us-central1 --set-env-vars=OPENAI_API_KEY=your_key
LangServe nudi podporo za Pydantic 2 z nekaterimi omejitvami. Dokumenti OpenAPI ne bodo ustvarjeni za invoke/batch/stream/stream_log pri uporabi Pydantic V2. Fast API ne podpira mešanja imenskih prostorov pydantic v1 in v2. LangChain uporablja imenski prostor v1 v Pydantic v2. Preberite naslednje smernice, da zagotovite združljivost z LangChain. Razen teh omejitev pričakujemo, da bodo končne točke API-ja, igrišče in vse druge funkcije delovale po pričakovanjih.
LLM aplikacije se pogosto ukvarjajo z datotekami. Obstajajo različne arhitekture, ki jih je mogoče narediti za izvajanje obdelave datotek; na visoki ravni:
- Datoteko je mogoče naložiti na strežnik prek namenske končne točke in obdelati z uporabo ločene končne točke.
- Datoteka se lahko naloži z vrednostjo (bajti datoteke) ali sklicem (npr. s3 url do vsebine datoteke).
- Končna točka obdelave lahko blokira ali ne blokira.
- Če je potrebna večja obdelava, se lahko obdelava prenese v namensko področje procesov.
Določiti morate, katera je ustrezna arhitektura za vašo aplikacijo. Trenutno za nalaganje datotek po vrednosti v zagonsko možnost uporabite kodiranje base64 za datoteko (podatki o več delih/obrazcu še niso podprti).
Tukaj je Primer ki prikazuje, kako uporabiti kodiranje base64 za pošiljanje datoteke na oddaljeni izvajalec. Ne pozabite, da lahko datoteke vedno naložite s sklicevanjem (npr. s3 url) ali jih naložite kot podatke iz več delov/obrazca na namensko končno točko.
Vhodni in izhodni tipi so definirani na vseh zagonskih elementih. Do njih lahko dostopate prek lastnosti input_schema in output_schema. LangServe uporablja te vrste za preverjanje in dokumentacijo. Če želite preglasiti privzete ugotovljene vrste, lahko uporabite metodo with_types.
Tukaj je primer igrače za ponazoritev ideje:
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)
Podedujte iz CustomUserType, če želite, da se podatki deserializirajo v pidantični model in ne v enakovredno predstavitev dict. Ta vrsta trenutno deluje samo na strani strežnika in se uporablja za določanje želenega vedenja dekodiranja. Če deduje po tej vrsti, bo strežnik ohranil dekodirano vrsto kot pidantični model, namesto da bi jo pretvoril v diktat.
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")
Igrišče vam omogoča, da iz ozadja določite pripomočke po meri za svoj izvajalni program. Gradnik je določen na ravni polja in poslan kot del sheme JSON vrste vnosa. Gradnik mora vsebovati ključ, imenovan type, pri čemer je vrednost ena od znanih seznamov gradnikov. Drugi ključi gradnika bodo povezani z vrednostmi, ki opisujejo poti v objektu JSON.
Splošna shema:
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;
};
Omogoča ustvarjanje vnosa za nalaganje datotek na igrišču uporabniškega vmesnika za datoteke, ki so naložene kot nizi, kodirani base64. Tukaj je celoten primer.
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
Avtomatizirajte ročna opravila in poteke dela z našim graditeljem potekov dela, ki ga poganja AI, ki ga je Nanonets zasnoval za vas in vaše ekipe.
Uvod v LangSmith
LangChain olajša izdelavo prototipov LLM aplikacij in agentov. Vendar pa je lahko dobava LLM aplikacij v produkcijo varljivo težka. Verjetno boste morali močno prilagoditi in ponoviti svoje pozive, verige in druge komponente, da ustvarite visokokakovosten izdelek.
Za pomoč pri tem procesu je bil predstavljen LangSmith, enotna platforma za odpravljanje napak, testiranje in spremljanje vaših aplikacij za LLM.
Kdaj bi to lahko prišlo prav? Morda se vam bo zdelo uporabno, ko želite hitro odpraviti napake v novi verigi, agentu ali naboru orodij, vizualizirati, kako so komponente (verige, llms, retrieverji itd.) povezane in kako se uporabljajo, oceniti različne pozive in LLM-je za posamezno komponento, dano verigo večkrat preglejte nabor podatkov, da zagotovite, da dosledno izpolnjuje merilo kakovosti, ali zajemite sledi uporabe in uporabite LLM-je ali analitične cevovode za ustvarjanje vpogledov.
Pogoji:
- Ustvarite račun LangSmith in ustvarite ključ API (glejte spodnji levi kot).
- Seznanite se s platformo tako, da si ogledate dokumente.
Zdaj pa začnimo!
Najprej konfigurirajte spremenljivke svojega okolja, da bodo LangChainu sporočili, naj beleži sledi. To storite tako, da spremenljivko okolja LANGCHAIN_TRACING_V2 nastavite na true. LangChainu lahko poveste, v kateri projekt naj se prijavi, tako da nastavite spremenljivko okolja LANGCHAIN_PROJECT (če ta ni nastavljena, bodo zagoni zabeleženi v privzeti projekt). To bo samodejno ustvarilo projekt za vas, če ne obstaja. Nastaviti morate tudi spremenljivki okolja LANGCHAIN_ENDPOINT in LANGCHAIN_API_KEY.
OPOMBA: Upravljalnik konteksta v pythonu lahko uporabite tudi za beleženje sledi z uporabo:
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?")
Vendar bomo v tem primeru uporabili spremenljivke okolja.
%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>"
Ustvarite odjemalca LangSmith za interakcijo z API-jem:
from langsmith import Client client = Client()
Ustvarite komponento LangChain in zabeležite zagone na platformo. V tem primeru bomo ustvarili agenta v slogu ReAct z dostopom do splošnega iskalnega orodja (DuckDuckGo). Poziv agenta si lahko ogledate v središču tukaj:
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
)
Agent izvajamo hkrati na več vhodih, da zmanjšamo zakasnitev. Zagoni se prijavijo v LangSmith v ozadju, tako da zakasnitev izvajanja ni prizadeta:
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]
Ob predpostavki, da ste uspešno nastavili svoje okolje, bi se morale sledi vaših agentov prikazati v razdelku Projekti v aplikaciji. Čestitke!
Videti je, da posrednik orodij ne uporablja učinkovito. Ocenimo to, da bomo imeli izhodišče.
Poleg beleženja vam LangSmith omogoča tudi testiranje in ocenjevanje vaših LLM aplikacij.
V tem razdelku boste izkoristili LangSmith za ustvarjanje primerjalnega nabora podatkov in zagon ocenjevalcev s pomočjo umetne inteligence na agentu. To boste storili v nekaj korakih:
- Ustvarite nabor podatkov LangSmith:
Spodaj uporabljamo odjemalca LangSmith za ustvarjanje nabora podatkov iz vhodnih vprašanj od zgoraj in oznak seznama. Te boste uporabili pozneje za merjenje uspešnosti novega agenta. Nabor podatkov je zbirka primerov, ki niso nič drugega kot vhodno-izhodni pari, ki jih lahko uporabite kot testne primere za svojo aplikacijo:
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 )
- Inicializirajte novega agenta za primerjavo:
LangSmith vam omogoča ovrednotenje katere koli LLM, verige, agenta ali celo funkcije po meri. Pogovorni agenti so s stanjem (imajo spomin); da zagotovimo, da se to stanje ne deli med zagoni nabora podatkov, bomo posredovali chain_factory (
aka konstruktor) funkcijo za inicializacijo za vsak klic:
# 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)
- Konfiguriraj vrednotenje:
Ročna primerjava rezultatov verig v uporabniškem vmesniku je učinkovita, vendar je lahko zamudna. Uporabite lahko samodejne meritve in povratne informacije s pomočjo umetne inteligence, da ocenite delovanje vaše komponente:
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=[],
)
- Zaženite agenta in ocenjevalce:
Uporabite funkcijo run_on_dataset (ali asinhrono arun_on_dataset), da ocenite svoj model. To bo:
- Pridobite vzorčne vrstice iz navedenega niza podatkov.
- Zaženite agenta (ali katero koli funkcijo po meri) na vsakem primeru.
- Uporabite ocenjevalce za nastale sledi izvajanja in ustrezne referenčne primere za ustvarjanje samodejnih povratnih informacij.
Rezultati bodo vidni v aplikaciji LangSmith:
chain_results = run_on_dataset( dataset_name=dataset_name, llm_or_chain_factory=functools.partial(agent_factory, prompt=prompt), evaluation=evaluation_config, verbose=True, client=client, project_name=f"runnable-agent-test-5d466cbc-{unique_id}", tags=[ "testing-notebook", "prompt:5d466cbc", ],
)
Zdaj, ko imamo rezultate testnega delovanja, lahko spremenimo našega agenta in ga primerjamo. Poskusimo to znova z drugim pozivom in poglejmo rezultate:
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 vam omogoča izvoz podatkov v običajne formate, kot sta CSV ali JSONL, neposredno v spletni aplikaciji. Odjemalca lahko uporabite tudi za pridobivanje izvajanj za nadaljnjo analizo, shranjevanje v lastni bazi podatkov ali skupno rabo z drugimi. Pridobimo sledi izvajanja iz ocenjevalnega izvajanja:
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
To je bil hiter vodnik za začetek, vendar obstaja veliko več načinov za uporabo LangSmitha za pospešitev razvijalskega toka in doseganje boljših rezultatov.
Za več informacij o tem, kako lahko kar najbolje izkoristite LangSmith, si oglejte dokumentacijo za LangSmith.
Naprej na raven z Nanoneti
Čeprav je LangChain dragoceno orodje za integracijo jezikovnih modelov (LLM) z vašimi aplikacijami, se lahko sooči z omejitvami, ko gre za primere uporabe v podjetjih. Raziščimo, kako Nanonets presega LangChain za reševanje teh izzivov:
1. Celovita podatkovna povezljivost:
LangChain ponuja priključke, vendar morda ne pokriva vseh aplikacij delovnega prostora in formatov podatkov, na katere se zanašajo podjetja. Nanonets ponuja podatkovne konektorje za več kot 100 široko uporabljenih aplikacij za delovni prostor, vključno s Slack, Notion, Google Suite, Salesforce, Zendesk in mnogimi drugimi. Podpira tudi vse nestrukturirane podatkovne vrste, kot so PDF-ji, TXT-ji, slike, zvočne datoteke in video datoteke, ter strukturirane podatkovne vrste, kot so CSV-ji, preglednice, zbirke podatkov MongoDB in SQL.
2. Avtomatizacija opravil za aplikacije delovnega prostora:
Čeprav ustvarjanje besedila/odgovora deluje odlično, so zmožnosti LangChaina omejene, ko gre za uporabo naravnega jezika za izvajanje nalog v različnih aplikacijah. Nanonets ponuja sprožilne/dejavne agente za najbolj priljubljene aplikacije delovnega prostora, kar vam omogoča nastavitev delovnih tokov, ki poslušajo dogodke in izvajajo dejanja. Na primer, lahko avtomatizirate e-poštne odgovore, vnose CRM, poizvedbe SQL in drugo, vse z ukazi naravnega jezika.
3. Sinhronizacija podatkov v realnem času:
LangChain pridobi statične podatke s podatkovnimi konektorji, ki morda ne sledijo spremembam podatkov v izvorni bazi podatkov. Nasprotno pa Nanonets zagotavlja sinhronizacijo v realnem času z viri podatkov, kar zagotavlja, da vedno delate z najnovejšimi informacijami.
3. Poenostavljena konfiguracija:
Konfiguriranje elementov cevovoda LangChain, kot so retrieverji in sintetizatorji, je lahko zapleten in dolgotrajen postopek. Nanonets to poenostavi z zagotavljanjem optimiziranega vnosa in indeksiranja podatkov za vsako vrsto podatkov, vse pa v ozadju upravlja pomočnik AI. To zmanjša breme natančnega prilagajanja in olajša nastavitev in uporabo.
4. Enotna rešitev:
Za razliko od LangChaina, ki lahko zahteva edinstvene izvedbe za vsako nalogo, Nanonets služi kot rešitev na enem mestu za povezovanje vaših podatkov z LLM. Ne glede na to, ali morate ustvariti programe LLM ali poteke dela z umetno inteligenco, Nanonets ponuja enotno platformo za vaše raznolike potrebe.
Poteki dela Nanonets AI
Nanonets Workflows je varen, večnamenski AI Assistant, ki poenostavlja integracijo vašega znanja in podatkov z LLM-ji ter olajša ustvarjanje aplikacij in delovnih tokov brez kode. Ponuja uporabniški vmesnik, ki je enostaven za uporabo, zaradi česar je dostopen tako posameznikom kot organizacijam.
Za začetek lahko načrtujete klic z enim od naših strokovnjakov za umetno inteligenco, ki vam lahko zagotovi prilagojeno predstavitev in preizkus delovnih tokov Nanonets, prilagojenih vašemu posebnemu primeru uporabe.
Ko je nastavljen, lahko uporabite naravni jezik za načrtovanje in izvajanje zapletenih aplikacij in delovnih tokov, ki jih poganjajo LLM-ji, ki se brezhibno integrirajo z vašimi aplikacijami in podatki.
Napolnite svoje ekipe z Nanonets AI za ustvarjanje aplikacij in integracijo vaših podatkov z aplikacijami in poteki dela, ki jih poganja AI, kar vašim ekipam omogoča, da se osredotočijo na tisto, kar je resnično pomembno.
Avtomatizirajte ročna opravila in poteke dela z našim graditeljem potekov dela, ki ga poganja AI, ki ga je Nanonets zasnoval za vas in vaše ekipe.
- Distribucija vsebine in PR s pomočjo SEO. Okrepite se še danes.
- PlatoData.Network Vertical Generative Ai. Opolnomočite se. Dostopite tukaj.
- PlatoAiStream. Web3 Intelligence. Razširjeno znanje. Dostopite tukaj.
- PlatoESG. Ogljik, CleanTech, Energija, Okolje, sončna energija, Ravnanje z odpadki. Dostopite tukaj.
- PlatoHealth. Obveščanje o biotehnologiji in kliničnih preskušanjih. Dostopite tukaj.
- vir: https://nanonets.com/blog/langchain/
- :ima
- : je
- :ne
- :kje
- $GOR
- 1
- 10
- 100
- 114
- 13
- 15%
- 2000
- 2012
- 2023
- 25
- 30
- 32
- 36
- 40
- 400
- 408
- 50
- 500
- 7
- 8
- a
- ABC
- sposobnost
- Sposobna
- O meni
- o IT
- nad
- Sprejmi
- Sprejema
- dostop
- dostopen
- Dostop
- doseganje
- ustrezno
- Račun
- natančnost
- natančna
- natančno
- Doseči
- doseže
- Dosega
- čez
- Zakon
- Ukrep
- dejavnosti
- aktivna
- prilagajanje
- prilagodljivo
- dodajte
- dodano
- dodajanje
- Poleg tega
- Dodatne
- Poleg tega
- Naslov
- Dodaja
- priznati
- napredno
- Adventure
- po
- spet
- starost
- Agent
- agenti
- AI
- Pomočnik AI
- AI modeli
- Pomoč
- Usmerjanje
- algoritmi
- uskladiti
- Poravnava
- vsi
- omogočajo
- Dovoli
- omogoča
- sam
- skupaj
- skupaj
- že
- Prav tako
- Čeprav
- vedno
- an
- Analiza
- Analitično
- analitika
- in
- Angeles
- Objavi
- letno
- Še ena
- odgovor
- odgovori
- Himna
- Antropično
- kaj
- karkoli
- API
- API KLJUČI
- API-ji
- aplikacija
- primerno
- uporaba
- Razvoj aplikacij
- aplikacije
- uporabna
- velja
- pristop
- pristopi
- primerno
- ustrezno
- aplikacije
- Arhitektura
- SE
- Argument
- Argumenti
- Armstrong
- okoli
- Array
- Izvajalci
- AS
- vprašati
- vidik
- vidiki
- pomoč
- Pomočnik
- povezan
- At
- pripisujejo
- pozornosti
- audio
- Povečana
- Preverjanje pristnosti
- avtomatizirati
- Avtomatizirano
- avtomatizira
- samodejno
- Avtomatizacija
- Na voljo
- povprečno
- čakati
- zaveda
- AWS
- nazaj
- Hrbtenica
- Backend
- ozadje
- slabo
- Ravnovesje
- bar
- baza
- temeljijo
- Izhodišče
- bash
- Osnovni
- Osnove
- BCG
- BE
- Beach
- Medvedi
- ker
- bilo
- pred
- začetek
- vedenje
- zadaj
- v zakulisju
- počutje
- spodaj
- merilo
- koristno
- BEST
- Boljše
- med
- Poleg
- največji
- Bill
- Bill Gates
- vežejo
- bing
- Bit
- črna
- Črna luknja
- Block
- blokiranje
- Bloki
- Blog
- zrna
- Bootstrap
- rojen
- Bot
- tako
- Bottom
- Branch
- Break
- vetrič
- Na kratko
- širši
- rjav
- brskalnik
- varovalni
- izgradnjo
- builder
- Building
- zgrajena
- obremenitev
- podjetja
- vendar
- by
- izračun
- izračuna
- izračun
- izračun
- klic
- povratne klice
- se imenuje
- kliče
- poziva
- CAN
- Lahko dobiš
- Kanada
- Zmogljivosti
- lahko
- kapaciteta
- zajemanje
- Zajemanje
- primeru
- primeri
- CAT
- poskrbi
- gostinstvo
- poskrbi
- Mačke
- previdnost
- previden
- centrirano
- nekatere
- verige
- verige
- izzivi
- Spremembe
- značaja
- chatbot
- klepetalnice
- preveriti
- Pregledi
- Izberite
- izbran
- okoliščinah
- mesto
- razred
- razredi
- stranke
- Cloud
- Koda
- Kodiranje
- Kava
- KOHERENTNO
- kohezivni
- sodelovati
- Collapse
- zbirka
- barvita
- Stolpec
- Stolpci
- COM
- združujejo
- kombinirani
- združuje
- združevanje
- kako
- prihaja
- udobna
- Skupno
- Komunikacija
- podjetje
- primerjate
- primerjavo
- združljivost
- združljiv
- dokončanje
- popolnoma
- dokončanje
- kompleksna
- zapletenosti
- komponenta
- deli
- sestavljajo
- sestava
- celovito
- obsegajo
- Koncept
- zgoščeno
- sočasno
- stanje
- konfiguracija
- sotočje
- Connect
- Povezovanje
- Povezovanje
- Proti
- Razmislite
- dosledno
- vsebuje
- Konzole
- nenehno
- konstrukti
- vsebujejo
- Vsebuje
- vsebina
- ozadje
- kontekstih
- kontekstualno
- naprej
- stalno
- kontrast
- nadzor
- Nadzor
- Priročen
- Pogovor
- pogovorni
- pogovorni AI
- pogovorov
- Pretvorba
- pretvori
- pretvorbo
- Core
- Kotiček
- popravi
- Ustrezno
- bi
- štetje
- država
- par
- pokrov
- zajeti
- ustvarjajo
- ustvaril
- ustvari
- Ustvarjanje
- Oblikovanje
- Mandatno
- Merila
- Kritik
- CRM
- ključnega pomena
- Trenutna
- Trenutno
- po meri
- Stranke, ki so
- customization
- prilagodite
- meri
- vrhunsko
- datum
- Struktura podatkov
- Baze podatkov
- baze podatkov
- Datum
- Datum čas
- ponudba
- deliti
- december
- odloča
- Odločanje
- Odločanje
- dekodiranje
- namenjen
- globlje
- privzeto
- opredeliti
- opredeljen
- definiranje
- definicije
- dostavo
- daje
- potopite
- demo
- izkazati
- Dokazano
- dokazuje
- odvisna
- Odvisno
- odvisno
- razporedi
- razporejeni
- uvajanja
- uvajanje
- razpolaga
- opisati
- opis
- Oblikovanje
- imenovani
- zasnovan
- želeno
- Podatki
- podrobno
- Podrobnosti
- Ugotovite,
- določa
- Razvoj
- Razvojni
- Razvijalci
- razvoju
- Razvoj
- diagrami
- DICT
- DID
- se razlikujejo
- drugačen
- drugače
- težko
- Dimenzije
- dimenzije
- direktiv
- neposredno
- razpravlja
- razpravljali
- prikazovanje
- izrazit
- potop
- razne
- DM
- do
- dokument
- Dokumentacija
- Dokumenti
- ne
- ne
- tem
- don
- opravljeno
- podvojila
- navzdol
- prenesi
- prenosov
- Osnutek
- pogon
- 2
- med
- dinamično
- dinamično
- e
- vsak
- prej
- Zgodnje
- enostavnost
- Enostavnost uporabe
- lažje
- enostavno
- lahka
- enostaven za uporabo
- echo
- ekosistem
- Učinkovito
- učinkovito
- učinkovitosti
- učinkovite
- učinkovito
- truda
- bodisi
- element
- elementi
- Elon
- Elon Musk
- ostalo
- E-naslov
- Embed
- vgrajeni
- vdelava
- zaposleni
- Zaposleni
- zaposluje
- opolnomočiti
- omogočajo
- omogoča
- omogočanje
- inkapsulira
- srečanje
- konec koncev
- Končna točka
- angažiran
- Motor
- Motorji
- Anglija
- Angleščina
- Angleški Premier League
- okrepi
- okrepljeno
- izboljšanje
- zagotovitev
- zagotavlja
- zagotoviti
- Podjetje
- subjekti
- entiteta
- okolje
- okolja
- Enakovredna
- Era
- Napaka
- napake
- zlasti
- bistvena
- odtujena
- itd
- oceniti
- Ocena
- Tudi
- dogodki
- Tudi vsak
- Primer
- Primeri
- presega
- Razen
- izvršiti
- izvršeno
- Izvaja
- izvršitve
- izvedba
- ponazarja
- Vaja
- obstajajo
- pričakovati
- pričakovanja
- Pričakuje
- pričakuje
- izkušnje
- eksperimentalni
- Strokovnjaki
- razložiti
- Pojasni
- izrecno
- raziskovanje
- raziskuje
- Raziskano
- izvoz
- izraz
- razširiti
- razširitev
- obsežen
- zunanja
- dodatna
- ekstrakt
- pridobivanje
- Izvlečki
- Obraz
- olajšati
- olajša
- Tovarna
- dejstva
- daleč
- FAST
- Priljubljeni
- Feature
- Lastnosti
- povratne informacije
- Nekaj
- Polje
- Področja
- figma
- Slika
- file
- datoteke
- izpolnite
- napolnjena
- polnjenje
- filter
- filtriranje
- končna
- končno
- Najdi
- iskanje
- prva
- pet
- prilagodljivost
- prilagodljiv
- Pretok
- Osredotočite
- osredotočena
- Osredotoča
- osredotoča
- sledi
- po
- sledi
- hrana
- za
- obrazec
- format
- oblikovana
- Na srečo
- je pokazala,
- Okvirni
- okviri
- pogosto
- prijatelj
- prijatelji
- iz
- polno
- polnopravni
- funkcija
- funkcionalnosti
- funkcionalnost
- funkcije
- temeljna
- smešno
- nadalje
- Prihodnost
- Gain
- Games
- Gates
- splošno
- splošno
- ustvarjajo
- ustvarila
- ustvarja
- ustvarjajo
- generacija
- žanr
- Nemčija
- dobili
- pridobivanje
- gif
- GitHub
- dana
- GMT
- Go
- goes
- dogaja
- dobro
- zrnat
- graf
- veliko
- več
- Navodila
- vodi
- Smernice
- maraton hekanja
- ročaj
- Ročaji
- Ravnanje
- priročen
- Trdi
- škodovalo
- snopov
- Imajo
- ob
- močno
- Hero
- pomoč
- pomoč
- Pomaga
- jo
- tukaj
- hi
- visoka
- na visoki ravni
- visoka kvaliteta
- najvišja
- zelo
- zgodovinski
- zgodovina
- Luknja
- napa
- gostitelj
- Kako
- Kako
- Vendar
- HTML
- http
- HTTPS
- Hub
- človeškega
- Stotine
- i
- ID
- Ideja
- idealen
- ID-ji
- if
- ii
- iii
- ilustrirajte
- ponazarja
- slike
- Takojšen
- izvajati
- Izvajanje
- izvedbe
- izvajali
- uvoz
- Izboljšave
- izboljšanju
- in
- Poglobljena
- vključujejo
- vključeno
- vključuje
- Vključno
- vključi
- vključujoč
- neverjetno
- Indeks
- indekse
- Navedite
- označuje
- Posamezno
- posamezniki
- Podatki
- začetna
- sproži
- inovativne
- vhod
- vhodi
- vpogledi
- namestitev
- nameščen
- Namestitev
- primer
- instant
- Namesto
- Navodila
- integral
- integrirati
- integrirana
- Integrira
- Povezovanje
- integracija
- integracije
- Inteligentna
- namenjen
- interakcijo
- interakcije
- interakcije
- interaktivno
- interaktivni
- vmesnik
- vmesniki
- interno
- Internet
- v
- Uvedeno
- Predstavlja
- intuitivno
- vključujejo
- isn
- vprašanje
- Vprašanja
- IT
- Izdelkov
- ponovitve
- ITS
- sam
- Jackson
- JavaScript
- Job
- Jordan
- Potovanje
- json
- julij
- samo
- Justice
- Imejte
- ohranja
- Ključne
- tipke
- Otrok
- Vedite
- znanje
- Graf znanja
- znano
- label
- Oznake
- Država
- jezik
- jeziki
- velika
- večja
- Zadnja
- Latenca
- pozneje
- Zadnji
- Liga
- UČITE
- učenje
- levo
- Legacy
- dolžina
- manj
- Naj
- Lets
- pismo
- Stopnja
- ravni
- Vzvod
- Leverages
- vzvod
- knjižnice
- Knjižnica
- kot
- Verjeten
- LIMIT
- omejitve
- Limited
- omejujoč
- Meje
- Povezave
- Seznam
- poslušati
- seznami
- v živo
- ll
- LLM
- obremenitev
- nakladač
- nahaja
- kraj aktivnosti
- prijavi
- prijavljen
- sečnja
- Logika
- Long
- več
- Poglej
- si
- POGLEDI
- iskanje
- jih
- Los Angeles
- nizka
- stroj
- strojno učenje
- je
- vzdrževati
- Vzdrževalno
- vzdrževanje
- vzdržuje
- Znamka
- IZDELA
- Izdelava
- upravljanje
- upravljanje
- upravitelj
- upravljanje
- manchester
- Manchester United
- Manipulacija
- Način
- Navodilo
- Proizvajalec
- več
- veliko ljudi
- map
- kartiranje
- Zemljevidi
- Stave
- ujemanje
- math
- matematični
- Zadeve
- največja
- Maj ..
- me
- pomeni
- kar pomeni,
- pomeni
- merjenje
- mediji
- srečanja
- ustreza
- spomini
- Spomin
- omenjeno
- Spoji
- združitev
- Sporočilo
- sporočil
- sporočanje
- metapodatki
- Metoda
- Metode
- Meritve
- morda
- milijoni
- minimalna
- mladoletnika
- manjka
- napake
- Mešanje
- MLB
- Mobilni
- Model
- modeli
- zmernost
- Moduli
- Moduli
- Trenutek
- MongoDB
- monitor
- spremljanje
- Luna
- več
- Najbolj
- Najbolj popularni
- premikanje
- Film
- veliko
- več
- več verig
- Musk
- morajo
- my
- Ime
- Imenovan
- Imena
- nacionalni
- naravna
- Obdelava Natural Language
- Krmarjenje
- krmarjenje
- Blizu
- potrebno
- Nimate
- potrebna
- potrebe
- negativna
- Novo
- NY
- New York Times
- Naslednja
- št
- Noben
- nič
- Pojem
- zdaj
- Številka
- Obama
- predmet
- Cilj
- predmeti
- Opazovanje
- pridobi
- pridobitev
- OCR
- of
- ponudba
- ponujanje
- Ponudbe
- pogosto
- oh
- Ok
- Olimpijske igre
- on
- enkrat
- ONE
- samo
- open source
- OpenAI
- operacije
- operater
- optimizirana
- Optimizira
- Možnost
- or
- Da
- organsko
- organizacije
- izvirno
- OS
- Ostalo
- drugi
- drugače
- naši
- ven
- izhod
- izhodi
- več
- preglasijo
- pregled
- lastne
- paket
- pakete
- Stran
- strani
- parov
- pand
- Papir
- vzporedno
- parameter
- parametri
- parkirati
- del
- zlasti
- deli
- mimo
- opravil
- vozovnice
- Podaje
- preteklosti
- pot
- poti
- vzorci
- Plače
- ljudje
- za
- popolna
- popolnoma
- Izvedite
- performance
- izvajati
- opravlja
- Dovoljenja
- vztrajnost
- oseba
- Prilagojene
- perspektiva
- Fizika
- kos
- plinovod
- Pizza
- placeholder
- platforma
- platon
- Platonova podatkovna inteligenca
- PlatoData
- Predvajaj
- igrišče
- igra
- prosim
- plus
- Točka
- politike
- politika
- političnih
- bazen
- Popular
- naseljeno
- pozitiven
- mogoče
- Prispevek
- Prispevkov
- potencial
- moč
- poganja
- močan
- Praktično
- praksa
- raje
- premier
- predstaviti
- Predsednik
- preprečiti
- preprečevanje
- prejšnja
- v prvi vrsti
- primarni
- Predsednik
- zasebna
- problem
- Težave
- nadaljujte
- Postopek
- Predelano
- Procesi
- obravnavati
- proizvodnjo
- Izdelek
- proizvodnja
- Učitelj
- Programiranje
- programskih jezikov
- Projekt
- projekti
- Lastnosti
- nepremičnine
- PROS
- Prototip
- prototipov
- zagotavljajo
- če
- Ponudnik
- ponudniki
- zagotavlja
- zagotavljanje
- javnega
- Namen
- namene
- dal
- Python
- Vprašanja in odgovori
- kakovost
- poizvedbe
- vprašanje
- vprašanja
- Hitri
- hitro
- kotacije
- R
- dvigniti
- območje
- obsegu
- precej
- ocena
- Surovi
- RE
- dosežejo
- Reagirajo
- Preberi
- reading
- pripravljen
- pravo
- v realnem času
- podatki v realnem času
- kraljestvo
- Razlog
- Razlogi
- nedavno
- priporočeno
- Zabeležena
- evidence
- Obnovi
- zmanjša
- zmanjšuje
- zmanjšanje
- Zmanjšanje
- reference
- sklicevanje
- izboljšati
- rafiniranje
- regije
- Razmerja
- sprosti
- ustreznost
- pomembno
- zanesljivost
- zanesljiv
- zanašajo
- zanašanje
- ostanki
- ne pozabite
- opomnik
- daljinsko
- donos
- ponovite
- PONOVNO
- preoblikovanje
- zamenjajte
- poročilo
- Skladišče
- zastopanje
- predstavlja
- predstavlja
- zahteva
- zahteva
- zahteva
- obvezna
- Zahteve
- zahteva
- reševanje
- Raziskave
- reševanje
- vir
- Odzove
- odziva
- Odgovor
- odgovorov
- odgovorna
- odziven
- REST
- povzroči
- rezultat
- Rezultati
- ohranitev
- zadrževanje
- vrnitev
- vrnitev
- vrne
- za večkratno uporabo
- pregleda
- vrti
- Riž
- Rich
- roboti
- vloga
- vloge
- koren
- usmerjanje
- ROW
- Run
- tek
- deluje
- runtime
- s
- varovala
- prodaja
- prodajni center
- sam
- Enako
- Shrani
- pravijo,
- pravi
- razširljive
- Lestvica
- Scenarij
- scenariji
- prizori
- urnik
- rezultat
- praska
- brezšivne
- brez težav
- Iskalnik
- iskalnik
- iskanja
- iskanje
- Oddelek
- oddelki
- zavarovanje
- varnost
- glej
- izbran
- izbor
- Prodaja
- pošljite
- občutljiva
- sentiment
- čustva
- ločena
- september
- Zaporedje
- Serija
- služijo
- strežnik
- služi
- Storitve
- nastavite
- Kompleti
- nastavitev
- nastavitve
- nastavitev
- sedem
- več
- Delite s prijatelji, znanci, družino in partnerji :-)
- deli
- Shell
- sije
- pošiljajo
- shouldnt
- Prikaži
- predstavitev
- pokazale
- Razstave
- Sigma
- pomemben
- Podoben
- Enostavno
- poenostavljeno
- poenostavitev
- poenostavitev
- preprosto
- saj
- sam
- Velikosti
- Slack
- majhna
- manj
- pametna
- delček
- So
- doslej
- Soccer
- socialna
- družbeni mediji
- Objave v družabnih medijih
- Izključno
- trdna
- Rešitev
- SOLVE
- nekaj
- Nekaj
- Včasih
- prefinjeno
- zvoki
- vir
- Viri
- Vesolje
- španski
- specializirani
- specifična
- posebej
- posebnosti
- določeno
- hitrost
- porabljen
- po delih
- Razcepi
- Šport
- kvadrat
- stati
- samostojna
- standardna
- Začetek
- začel
- Začetek
- Država
- Izjave
- statična
- Korak
- Koraki
- Še vedno
- stop
- ustavljanje
- Postanki
- shranjevanje
- trgovina
- shranjeni
- trgovine
- shranjevanje
- Zgodba
- naravnost
- tok
- pretakanje
- racionalizirati
- racionaliziran
- prednosti
- Stavke
- String
- Struktura
- strukturirano
- strukture
- strukturiranje
- slog
- predmet
- kasneje
- Uspešno
- taka
- Suit
- primerna
- apartma
- Povzamemo
- POVZETEK
- Sončni zahod
- podpora
- Podprti
- Podpira
- Preverite
- Trajnostni razvoj
- Sinhronizacija
- sinopsis
- sintaksa
- sistem
- sistemi
- miza
- po meri
- prilagojene
- Bodite
- meni
- Cilji
- Naloga
- Naloge
- skupina
- Skupine
- povej
- Predloga
- predloge
- terminal
- terminologija
- Pogoji
- Test
- Testiranje
- besedilo
- kot
- Hvala
- da
- O
- Osnove
- pesto
- informacije
- The New York Times
- Projekti
- Vir
- svet
- njihove
- Njih
- POTEM
- Tukaj.
- te
- jih
- stvari
- ta
- tisti,
- čeprav?
- skozi
- vsej
- čas
- zamudno
- krat
- Naslov
- do
- skupaj
- žeton
- Tokenizacija
- Boni
- tudi
- orodje
- Orodje
- orodja
- vrh
- temo
- Teme
- Skupaj za plačilo
- mesto
- Sledenje
- sledenje
- tradicionalna
- usposabljanje
- Transform
- transformacije
- transformator
- transformatorji
- Prehod
- sojenje
- Res
- resnično
- poskusite
- tuning
- OBRAT
- Obračalni
- Navodila
- Dvakrat
- dva
- tip
- Vrste
- Tipkovnica
- tipično
- ui
- Konec koncev
- nedotaknjen
- pod
- osnovni
- razumeli
- razumevanje
- razume
- poenoteno
- edinstven
- Velika
- Universal
- za razliko od
- dokler
- Nadgradnja
- posodobitve
- naložili
- URL
- us
- uporabnost
- Uporaba
- uporaba
- primeru uporabe
- Rabljeni
- uporabnik
- Uporabniški vmesnik
- Uporabniki
- uporablja
- uporabo
- javne gospodarske službe
- uporabiti
- uporablja
- izkorišča
- Uporaben
- v1
- potrjevanje
- Validator
- dragocene
- vrednost
- Vrednote
- spremenljivka
- raznolikost
- različnih
- Ve
- vsestranski
- različica
- zelo
- preko
- Video
- Poglej
- Kršitve
- vidna
- vizualizirati
- ključnega pomena
- vs
- sprehod
- walkthrough
- želeli
- je
- Watch
- način..
- načini
- we
- Vreme
- web
- spletni brskalnik
- spletne storitve
- spletne strani
- Dobro
- dobro znana
- so bili
- Kaj
- Kaj je
- kaj
- kdaj
- ali
- ki
- medtem
- WHO
- celoti
- zakaj
- široka
- pogosto
- pripomoček
- Wikipedia
- bo
- okno
- Zmage
- z
- v
- brez
- beseda
- delo
- delal
- potek dela
- delovnih tokov
- deluje
- deluje
- svet
- bi
- pisati
- pisanje
- X
- še
- york
- Vi
- Vaša rutina za
- sami
- youtube
- Zendesk
- zefirnet
- Zip