
What is a Chain ?
Chains are like a series of steps or actions. These steps could involve using an AI model, a tool, or processing some data. The main method for creating these chains is called LCEL. LCEL is awesome for making your own chains of steps, but sometimes you just want to use ready-made chains. LangChain supports two kinds of ready-made chains:
- Chains made with LCEL: These chains use LCEL to put the steps together, and LangChain has an easy way to make them.
- [Old-fashioned] Chains: These chains are made using an older method that doesn’t use LCEL. They are standalone and not built with the new
system. The chains constructed in the « ChatGPT and LangChain: The Complete Developer’s Masterclass » training are considered outdated.
We’re not going to work on them.
Example of chain in the first Jupyter notebook.
from langchain_openai import AzureChatOpenAIfrom langchain.prompts import ChatPromptTemplatefrom langchain_core.output_parsers import StrOutputParserimport os# SECURE THIS KEY!os.environ["AZURE_OPENAI_API_KEY"] = ""os.environ["AZURE_OPENAI_ENDPOINT"] = "https://azqoreai.openai.azure.com/"os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT_NAME"] = "gpt-35-turbo-16k_azqore_ai"os.environ["AZURE_OPENAI_API_VERSION"] = "2024-02-01"model = AzureChatOpenAI(openai_api_version=os.environ["AZURE_OPENAI_API_VERSION"],azure_deployment=os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT_NAME"],)code_prompt_template = ChatPromptTemplate.from_messages([("system", "Your are a software developer specialized in {language} "),("human", "Write a very short function that will {task}. Make sure the code compiles !")])output_parser= StrOutputParser()chain = code_prompt_template | model |output_parserchain.invoke({"language": "python","task": "return a fibonacci sequence using recursion",})--------------------------------'Here is a short function that returns a Fibonacci sequence using recursion in Python:\n\n```python\ndeffibonacci(n):\nif n <= 1:\nreturn n\nelse:\nreturn fibonacci(n-1) + fibonacci(n-2)\n```\n\nIn this code, the base case is when `n` is less than or equal to 1, where we simply return `n`. Forany other value of `n`, we recursively call the `fibonacci` function with `n-1` and `n-2`, and return the sumof the two recursive calls.\n\nTo use this function, simply call it with the desired index of the Fibonaccisequence:\n\n```python\nprint(fibonacci(5)) # Output: 5\nprint(fibonacci(10)) # Output: 55\nprint(fibonacci(15)) # Output: 610\n```\n\nNote that since this implementation uses recursion, it may become inefficient forlarge values of `n` due to repeated calculations. To optimize it, you can use memoization or dynamicprogramming techniques.'
Imagine a chain like a series of steps you follow to get a job done. Each step in this chain talks to the next one. It could be asking a computer program to do something, using a tool, or dealing with some data.The most important part of this chain is the model. The model takes what the previous step gave it, does its job, and then passes its result on to the next step. A chain uses a PromptTemplate, which is like a guide or template to help each step know what to do. Sometimes, this guide even comes with a default setting, like in the SQL chain. Good to know: Langchain lets you run different component in parallel. We are not going to discuss it here, but you can find examples in their documentation
You can try running the example in the training folder on your own. There are many interesting points to discuss.
- First, we’re using AzureChatOpenAI and ChatPromptTemplate. As we learned before, this means the way we send and receive messages will follow a specific format (system, human, and AI). This is visible line 18 & 19.
- We’re using the LCEL format to build a series of steps, one after another. You can see this on line 25 where the | (pipe) operator is used. This operator takes the result from one step and sends it to the next step in the chain
- If you look carefully line 18 & 19, you’ll see that the chain requires specific information – the language and the task. If you forget to provide these when you invoke the chain (line 26), you’ll get an error message.
- Each component of the chain needs a certain type of input and gives back a different type of output. We’ll talk more about this in the next section
Input and Output
LangChain provides an easy-to-understand diagram that shows what each part does. For example in the following table, you can see that a « Prompt » creates something called a « PromptValue. » Then you can also see that a « ChatModel » needs a « PromptValue » to work. The ChatModel produce a ChatMessage, that OutputParser requires as an input. This makes everything flow smoothly.
All components show what kind of data they need to start (input_schema) and what kind of data they give back when done (output_schema):
- input_schema: It’s like a template created automatically based on what information the program needs to work.
- output_schema: It’s like a template created automatically based on what information the program gives you after it’s done.
If you run the code below, you will see the template for the PromptInput:
schema_representation = code_prompt_template.input_schema.schema()print(schema_representation){"title": "PromptInput","type": "object","properties": {"language": {"title": "Language","type": "string"},"task": {"title": "Task","type": "string"}}}
Predefined Chains
LCEL is super flexible, but LangChain has some handy built-in chains you can use. Here’s a quick table that explains all LCEL chain creators:
- Chain Constructor: This is the name of the function that creates the chain. These are methods that give you LCEL Runnables. There are also links to more details in the API docs.
- Function Calling: This tells you if you need to use OpenAI’s function calling for this chain (more on this later).
- Other Tools: Any additional tools you might need for the chain are listed here (more on this later).
- When to Use: Langchain’s advice on the best times to use each chain
Combining predefined chains
You can link different chains together. Let’s look at an example in the second Jupyter notebook. First, Langchain will gather information from Wikipedia using a « retriever » . Then, it will send the info returned by the retriever to another chain that uses a language model (llm). Don’t worry if you don’t know what a retriever is yet – we’ll explain it in another lesson.
The key thing to understand is that when you check out the create_retrieval_chain instructions (or the table above), you’ll see it needs a retriever to work. This retriever will pull data from Wikipedia and return it as a list of Documents. These documents will then go to the second chain, created with create_stuff_documents_chain. This chain uses the LLM. You can see in the table above that this type of chain takes a list of documents, turns them into a prompt, and sends the prompt to the llm. Finally, the StrOutputParser changes the LLM’s output, which is usually in complex formats like JSON, into simple strings
This explains how linking things together can create a final result. Usually, the last step involves calling the llm, which tends to be slower than the other steps
model = AzureChatOpenAI(openai_api_version=os.environ["AZURE_OPENAI_API_VERSION"],azure_deployment=os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT_NAME"],)output_parser= StrOutputParser()#this retriever (more on this later) let us access Wikipediaretriever = WikipediaRetriever()prompt_template = ChatPromptTemplate.from_messages([("system", "You are a highly efficient assistant that excels at creating concise and comprehensivesummaries."),("human", "Create a summary in 10 lines about this topic {input} using only the data provided here :{context}")])#this chain will invoke the llm passing the documents retrieved from from wikipedia as input in the "context"variablellm_chain = create_stuff_documents_chain(model, prompt_template)#this chain will invoke the wikipedia retriever then pass the result to llm_chainchain = create_retrieval_chain(retriever, llm_chain)output = chain.invoke({"input": "euro 2024",})output_parser.invoke(output['answer'])----------------------------------------------------'The 2024 UEFA European Football Championship, also known as Euro 2024, is the 17th edition of the tournamentand is being held in Germany from 14 June to 14 July 2024. The tournament features 24 teams, including Georgiamaking their debut in the European Championship finals. This is the third time matches are played on Germanterritory, with Leipzig hosting for the first time in what was formerly East Germany. Germany is the solo hostnation for the first time since the 2006 FIFA World Cup. The tournament returned to its regular four-year cycleafter being postponed in 2020 due to the COVID-19 pandemic. Italy, the defending champions, were eliminated inthe round of 16 by Switzerland. The tournament follows a knockout format, with extra time and penalty shootoutsused to determine winners in case of a tie. The final will be held at Olympiastadion in Berlin. The qualifyingtournament for Euro 2024 took place from March 2023 to March 2024, with the top two teams from each group andthe four best third-placed teams joining host nation Germany in the final tournament.'
If you run the following code you will print the list of documents that is passed down through the chain by the retriever. Here’s something to keep in mind about documents that will be helpful later when we talk about RAG: they have two important parts. One part is called metadata, and it’s like a little library of extra details about the document, such as the page number, the book it’s from, or who’s allowed to see it. The other part is the content of the document, which is basically what’s written in it (here it’s called page_content)
prompt_template = ChatPromptTemplate.from_messages([("system", "You are a highly efficient assistant that excels at creating concise and comprehensivesummaries."),("human", "Create a summary in 10 lines about this topic {input} using only the data provided here :{context}")])#this chain will invoke the llm passing the documents retrieved from from wikipedia as input in the "context"variablechain = create_retrieval_chain(retriever, prompt_template)output = chain.invoke({"input": "euro 2024",})output["context"]------------------------------------------[Document(metadata={'title': 'UEFA Euro 2024', 'summary': "The 2024 UEFA European Football Championship,commonly referred to as UEFA Euro 2024 (stylised as UEFA EURO 2024), or simply Euro 2024, is the ongoing 17thedition of the UEFA European Championship, the quadrennial international football championship organised byUEFA for the European men's national teams of its member associations. Germany is hosting the tournament, whichis taking place from 14 June to 14 July 2024. The tournament comprises 24 teams, with Georgia being the onlyteam making their European Championship finals debut. \nIt is the third time that European Championship matchesare played on German territory and the second time in reunified Germany, as West Germany hosted thetournament's 1988 edition, and four matches of the multi-national Euro 2020 were played in Munich. It is thefirst time the competition is held in what was formerly East Germany, with Leipzig as a host city, as well asthe first major tournament since the 2006 FIFA World Cup that Germany serves as a solo host nation. Thetournament returned to its usual four-year cycle after the 2020 edition was postponed to 2021 due to the COVID-19 pandemic.\nItaly were the defending champions, having won the 2020 final against England on penalties, butwere eliminated in the round of 16 by Switzerland.", 'source': 'https://en.wikipedia.org/wiki/UEFA_Euro_2024'},page_content='The 2024 UEFA European Football Championship, commonly referred to as UEFA Euro 2024 (stylised asUEFA EURO 2024), or simply Euro 2024, is the ongoing 17th edition of the UEFA European Championship, thequadrennial international football championship organised by UEFA for the European men\'s national teams ofits member associations. Germany is hosting the tournament, which is taking place from 14 June to 14 July 2024.The tournament comprises 24 teams, with Georgia being the only team making their European Championship finalsdebut. \nIt is the third time that European Championship matches are played on German territory and the secondtime in reunified Germany, as West Germany hosted the tournament\'s 1988 edition, and four matches of the multi-national Euro 2020 were played in Munich. It is the first time the competition is held in what was formerlyEast Germany, with Leipzig as a host city, as well as the first major tournament since the 2006 FIFA World Cupthat Germany serves as a solo host nation. The tournament returned to its usual four-year cycle after the 2020edition was postponed to 2021 due to the COVID-19 pandemic.\nItaly were the defending champions, having won the2020 final against England on penalties, but were eliminated in the round of 16 by Switzerland.\n\n\n== Hostselection ==\n\nOn 8 March 2017, UEFA announced that two countries, Germany and Turkey, had announced theirintentions to host the tournament before the deadline of 3 March 2017.\nThe host was chosen by the UEFAExecutive Committee in a confidential ballot, needing only a simple majority of votes to win. If the votes wereequal, the final decision rested with UEFA president Aleksander eferin. Out of the 20 members on the UEFAExecutive Committee, Reinhard Grindel (Germany) and Servet Yardmc (Turkey) could not vote because they wereineligible. Lars-Christer Olsson (Sweden) was also absent due to illness. In total, 17 members were able tovote.\nThe host was selected on 27 September 2018 in Nyon, Switzerland. Germany initially planned to fully hostEuro 2020, although had not announced any firm interest by May 2012.\n\n\n== Venues ==\nGermany had a widechoice of stadiums that satisfied UEFA\'s minimum capacity requirement of 30,000 seats for EuropeanChampionship matches.\nOf the ten venues selected for Euro 2024, nine were used for the 2006 FIFA World Cup:Berlin, Dortmund, Munich, Cologne, Stuttgart, Hamburg, Leipzig, Frankfurt, and Gelsenkirchen. Düsseldorf, whichwas not used in 2006 but had previously been used for the 1974 FIFA World Cup and UEFA Euro 1988, will serve asthe tenth venue; conversely, Hanover, Nuremberg and Kaiserslautern, host cities in 2006 (in addition to 1974and 1988 in Hanover\'s case), will not be used for this championship. Munich, the site of the first game ofUEFA Euro 2024, was also a host city at the multi-national UEFA Euro 2020 tournament, hosting four matches(three involving Germany) in front of a greatly reduced number of spectators due to COVID-19 restrictions.\nVarious other stadiums, such as those in Bremen and Mönchengladbach, were not selected. The area with thehighest number of venues at UEFA Euro 2024 is the Rhine-Ruhr metropolitan region in the state of North Rhine-Westphalia, with four of the ten host cities (Dortmund, Düsseldorf, Gelsenkirchen and Cologne).\n\n\n=== Teambase camps ===\nEach team chose a "team base camp" for its stay between the matches. The teams will train andreside in these locations throughout the tournament, travelling to games staged away from their bases. The"team base camp" needs to be in Germany.\n\n\n=== Ticketing ===\nTickets for the venues were sold directly byUEFA via its website, or distributed by the football associations of the 24 finalists. Ticket sales started on3 October 2023. More than 80% of 2.7 million tickets for the 51 tournament matches were available for the fansof the participating teams and the general public. Fans of each participating team allocated 10,000 ticketsfor'),Document(metadata={'title': 'UEFA Euro 2024 knockout stage', 'summary': 'The knockout stage of UEFA Euro 2024began on 29 June 2024 with the round of 16 and will end on 14 July 2024 with the final at Olympiastadion inBerlin, Germany.\nAll times listed are Central European Summer Time (UTC+2)\n\n', 'source': 'https://en.wikipedia.org/wiki/UEFA_Euro_2024_knockout_stage'}, page_content='The knockout stage of UEFA Euro 2024 began on29 June 2024 with the round of 16 and will end on 14 July 2024 with the final at Olympiastadion in Berlin,Germany.\nAll times listed are Central European Summer Time (UTC+2)\n\n\n== Format ==\nIn the knockout stage,if a match is level at the end of normal playing time, extra time is played (two periods of 15 minutes each).If still tied after extra time, the match is decided by a penalty shoot-out.\nUEFA set out the followingschedule for the round of 16:\n\nMatch 1: Winner Group B vs 3rd Group A/D/E/F\nMatch 2: Winner Group A vsRunner-up Group C\nMatch 3: Winner Group F vs 3rd Group A/B/C\nMatch 4: Runner-up Group D vs Runner-up GroupE\nMatch 5: Winner Group E vs 3rd Group A/B/C/D\nMatch 6: Winner Group D vs Runner-up Group F\nMatch 7: WinnerGroup C vs 3rd Group D/E/F\nMatch 8: Runner-up Group A vs Runner-up Group B\nAs with every tournament sinceUEFA Euro 1984, there will be no third place play-off.\n\n\n=== Combinations of matches in the round of 16===\nThe specific match-ups involving the third-placed teams depended on which four third-placed teamsqualified for the round of 16:\n\n\n== Qualified teams ==\nThe top two placed teams from each of the sixgroups, along with the four best-placed third teams, qualified for the knockout stage.\n\n\n== Bracket==\n\n\n== Round of 16 ==\n\n\n=== Switzerland vs Italy ===\n\n\n=== Germany vs Denmark ===\nThis was a rematchof the UEFA Euro 1992 final, which Denmark won 2–0.\nIn the 35th minute, the match was suspended due to adverseweather conditions (thunderstorms and heavy rain) in the vicinity of the stadium. Play was suspended for about25 minutes before resuming at 21:59.\n\n\n=== England vs Slovakia ===\n\n\n=== Spain vs Georgia ===\n\n\n===France vs Belgium ===\n\n\n=== Portugal vs Slovenia ===\n\n\n=== Romania vs Netherlands ===\n\n\n=== Austria vsTurkey ===\n\n\n== Quarter-finals ==\n\n\n=== Spain vs Germany ===\nThe sides previously met in the UEFA Euro2008 final, which Spain won 1–0.\n\n\n=== Portugal vs France ===\nThe sides previously met in the UEFA Euro2016 final, where Portugal prevailed against the hosts 1–0 on extra time.\n\n\n=== England vs Switzerland===\n\n\n=== Netherlands vs Turkey ===\n\n\n== Semi-finals ==\n\n\n=== Winner Match 45 vs Winner Match 46===\n\n\n=== Winner Match 47 vs Winner Match 48 ===\n\n\n== Final ==\n\n\n== References ==\n\n\n== Externallinks ==\nOfficial website'),Document(metadata={'title': 'UEFA Euro 2024 qualifying', 'summary': "The UEFA Euro 2024 qualifying tournamentwas a football competition that was played from March 2023 to March 2024 to determine the 23 UEFA member men'snational teams that would join the automatically qualified host team Germany in the UEFA Euro 2024 finaltournament. The competition was linked with the 2022–23 UEFA Nations League, which gave countries a secondaryroute to qualify for the final tournament.\nA total of 53 UEFA member associations entered the qualifyingprocess. The draw for the qualifying group stage took place at the Festhalle in Frankfurt on 9 October 2022.",'source': 'https://en.wikipedia.org/wiki/UEFA_Euro_2024_qualifying'}, page_content="The UEFA Euro 2024qualifying tournament was a football competition that was played from March 2023 to March 2024 to determine the23 UEFA member men's national teams that would join the automatically qualified host team Germany in the UEFAEuro 2024 final tournament. The competition was linked with the 2022–23 UEFA Nations League, which gavecountries a secondary route to qualify for the final tournament.\nA total of 53 UEFA member associationsentered the qualifying process. The draw for the qualifying group stage took place at the Festhalle inFrankfurt on 9 October 2022.\n\n\n== Qualified teams ==\n\n\n== Format ==\nThe format was similar to the UEFAEuro 2020 qualifying competition: the group stage decided 20 of the 23 teams that would advance to the finaltournament to join host Germany. The 53 UEFA member associations were divided into ten groups, with sevengroups containing five teams and three containing six teams. The draw for the qualifying group stage took placeon 9 October 2022, after conclusion of the league phase of the 2022–23 UEFA Nations League. The four UEFANations League Finals participants were drawn into groups of five teams (so they were able to compete in theNations League Finals in June 2023). The qualifying group stage was played in a home-and-away, round-robinformat on double matchdays in March, June, September, October, and November 2023. The winners and runners-upfrom the ten groups qualified directly to the final tournament.\nFollowing the qualifying group stage, theremaining three teams were decided through the play-offs, held in March 2024. Twelve teams were selected basedentirely on their performance in the 2022–23 UEFA Nations League. These teams were divided into three paths,each containing four teams, with one team from each path qualifying for the final tournament. The group winnersof Nations Leagues A, B, and C automatically qualified for the play-off path of their league, unless theyqualified for the final tournament via the qualifying group stage. If a group winner had already qualifiedthrough the qualifying group stage, they would be replaced by the next best-ranked team in the same league.However, if there were not enough non-qualified teams in the same league, then the spot would go first to thebest-ranked group winner of League D, unless that team had already qualified for the final tournament. Theremaining slots were then allocated to the next best team in the Nations League overall ranking. However, groupwinners of Leagues B and C could not face teams from a higher league.\nThe three play-off paths each featuredtwo single-leg semi-finals, and one single-leg final. In the semi-finals, the best-ranked team hosted thelowest-ranked team, and the second-ranked team hosted the third-ranked team. The host of the final was drawnbetween the winners of the semi-final pairings. The three play-off path winners joined the twenty teams thatalready qualified for the final tournament through the group stage.\n\n\n=== Tiebreakers for group ranking===\nIf two or more teams were equal on points on completion of the group matches, the following tie-breakingcriteria were applied:\n\nHigher number of points obtained in the matches played among the teams in question;\nSuperior goal difference in matches played among the teams in question;\nHigher number of goals scored in thematches played among the teams in question;\nIf, after having applied criteria 1 to 3, teams still had an equalranking, criteria 1 to 3 were reapplied exclusively to the matches between the teams in question to determinetheir final rankings. If this procedure did not lead to a decision, criteria 5 to 11 applied;\nSuperior goaldifference in all group matches;\nHigher number of goals scored in all group matches;\nHigher number of awaygoals scored in all group matches;\nHigher number of wins in all group matches;\nHigher number of away wins inall group matches;\nFair play conduct in all group matches (1 point for a single yellow card")]
Combining components using LCEL
The same result can be obtained using LCEL instead of predefined chains :
prompt_template = ChatPromptTemplate.from_messages([("system", "You are a highly efficient assistant that excels at creating concise and comprehensivesummaries."),("human", "Create a summary in 10 lines about this topic {input} using only the data provided here :{context}")])chain = ({"context": retriever, "input": RunnablePassthrough()}| prompt_template| model| output_parser)chain.invoke("euro 2024")-------------------------------------------'UEFA Euro 2024 is the 17th edition of the UEFA European Championship, hosted by Germany from 14 June to 14July 2024. The tournament features 24 teams, with Georgia making their European Championship finals debut. Thisis the third time European Championship matches are played in Germany and the first time in what was formerlyEast Germany. Leipzig is one of the host cities. It is the first major tournament since the 2006 FIFA World Cupthat Germany serves as a solo host nation. Italy, the defending champions, were eliminated in the round of 16by Switzerland. The knockout stage of Euro 2024 began on 29 June 2024 and will end with the final atOlympiastadion in Berlin on 14 July 2024. The qualifying tournament for Euro 2024 was played from March 2023 toMarch 2024, with 23 teams joining host Germany in the final tournament. The competition was linked with the2022–23 UEFA Nations League.'
The RunnablePassthrough() method makes sure that any info you provide when invoking the chain gets passed along correctly to the PromptTemplate and then to the model. Think of it like this: when you run the chain, the input (like « euro 2024 ») gets stored in a special map with a key called « input, » which all other parts of the process can use. In the next section, we’ll talk about how Lanchain keeps track of these variables
Variable management in LangChain
Each component takes in data as input (input_data), and gives out data output_data). The data is saved in a map as a key/value pair, like a word and its definition in a dictionary. When a component starts working, it first looks in the map to find the info it needs by its name. If the map doesn’t have the info (key), an error pops up, and everything stops. Once the needed info is found, the part does its job and then saves the new info in the map with a specific key for its output.
In our example, the prompt template has a variable called input_variable that contains the key to the data expected. The associated schema displays the
types.
print("Input variables :\t{}\n".format(prompt_template.input_variables))print("Input schema :\t{}\n".format(prompt_template.input_schema.schema_json()))-----------------------------------Input variables : ['context', 'input']Input schema : {"title": "PromptInput", "type": "object", "properties": {"context": {"title": "Context","type": "string"}, "input": {"title": "Input", "type": "string"}}}
The same idea applies to what comes out of this. The output we’re looking for is called AzureChatOpenAIOutput, and it can be any type of message under ‘AIMessage’, ‘HumanMessage’, or ‘ChatMessage’. We talked about this in the last lesson, and it’s because we’re using AzureChatOpenAI and ChatPromptTemplate
model.output_schema.schema_json()----------------------------------------'{"title": "AzureChatOpenAIOutput", "anyOf": [{"$ref": "#/definitions/AIMessage"}, {"$ref": "#/definitions/HumanMessage"}, {"$ref": "#/definitions/ChatMessage"}, {"$ref": "#/definitions/SystemMessage"}, {"$ref": "#/definitions/FunctionMessage"}, {"$ref": "#/definitions/ToolMessage"}], ....
Exercices
- Adapt the example to connect to OpenAI API instead of Azure.
- Try to combine two chains to create a unit test for the function that produces a Fibonacci sequence, as shown in the first example
- Try to implement the ChatPerplexity
- Tweak the input variables names and see how it reacts
Code
Laisser un commentaireAnnuler la réponse.