Home Machine Learning Callbacks and Pipeline constructions in LangChain | by Roshan Santhosh | Apr, 2024

Callbacks and Pipeline constructions in LangChain | by Roshan Santhosh | Apr, 2024

0
Callbacks and Pipeline constructions in LangChain | by Roshan Santhosh | Apr, 2024

[ad_1]

We begin with a easy dummy chain that has 3 parts : 2 prompts and a customized perform to hitch them. I seek advice from this as a dummy instance as a result of its not possible that you’d want two separate prompts to work together with one another, nevertheless it makes for a neater instance to begin with for understanding callbacks and LangChain pipelines.

Instance 1 : Primary construction of LangChain pipeline

Implementing this in code would seem like :

Pipeline implementation for Instance 1

The above code is fairly textbook stuff. The one probably complicated piece is the retrieve_text and RunnableLambda perform thats getting used right here. The rationale that is vital is as a result of the format of the output from qa_prompt1 isn’t appropriate with the format of the output required by qa_prompt2.

Defining the customized Callback

For our customized callback, we outline a brand new subclass of BaseCallbackHandler referred to as CustomCallback1 which defines the on_chain_start technique. The tactic definition is easy because it merely takes the enter values handed to it and saves it in 2 particular variables : chain_input and serialized_input

Invoking the customized callback

Instance 1 : Invoking with pipeline with the customized callback

The above code reveals one of many doable methods to move your customized callback to your pipeline : As an inventory of callback objects as the worth to a corresponding key of ‘callbacks’. This additionally makes it straightforward to guess that you’ll be able to move a number of callbacks to your LangChain pipeline.

Decoding the Callback/Pipeline Construction

Now comes the fascinating half. After now we have outlined the callbacks and handed it on to our pipeline, we now carry out a deep dive into the callback outputs

We first have a look at the values saved in chain_input

Instance 1 : Contents of chain_input variable of callback handler

Observations :

  1. Although there are 3 parts in our chain, there are 4 values in chain_input. Which corresponds to the on_chain_start technique being triggered 4 occasions as a substitute of three.
  2. For the primary two chain_input values/ on_chain_start triggers, the enter is identical because the consumer supplied enter.

We subsequent have a look at the outputs of serialized_input

Observations :

  1. The primary element is a RunnableSequence which is a element that wasnt added by the consumer however was mechanically added by LangChain. The remainder of the parts correspond on to the user-defined parts within the pipeline.
  2. The complete contents of serialized_input is in depth! Whereas there’s a particular construction to that content material, its positively out of scope for this publish and probably doesnt have a lot sensible implications for an finish consumer.

How can we interpret these outcomes

For probably the most half, the outputs seen within the chain_input and serialized_input make sense. Whether or not its the enter values or the names/IDs of the parts. The one largely unknown half is the RunnableSequence element, so we take a more in-depth have a look at this.

As I discussed beforehand, the total contents of serialized_input is in depth and never straightforward to digest. So to make issues simpler, we have a look at solely the excessive stage attributes described in serialized_input and attempt to intrepret the outcomes by means of these attributes. For this, we make use of a customized debugging perform referred to as getChainBreakdown (code in pocket book).

We name getChainBreakdown on all values of serialized_input and observe the output. Particularly for the primary RunnableSequence component, we have a look at the keys of the kwargs dict : first, midde, final, title.

On nearer inspection of the kwargs argument and their values, we see that they’ve the identical construction as our earlier pipeline parts. In reality, the primary, center and final parts correspond precisely to the user-defined parts of the pipeline.

Nearer inspection of RunnableSequence kwargs values

The above particulars type the premise of the ultimate conclusion that we make right here. That the construction of the pipeline is like proven beneath :

Instance 1 : Construction of LangChain pipeline

We do make a little bit of a leap right here because the above flowchart was confirmed after going by means of a bunch of examples and observing the format by which these parts are created internally by LangChain. So bear with me as we undergo these different examples which is able to solidify the conclusion that we make right here.

With the above outlined construction, the opposite items of the puzzle match collectively fairly properly. Specializing in the chain_input values, lets map them to the parts (with their ordering) outlined above.

Instance 1 : Mapping chain_input values to pipeline parts

Observations :

  1. For RunnableSequence, because it acts like a wrapper for the entire pipeline, the enter from the consumer acts because the enter for the RunnableSequence element as properly.
  2. For the primary ChatPromptTemplate (qa_prompt1), as the primary ‘true’ element of the pipeline, it receives the direct enter from the consumer
  3. For RunnableLambda (retrieve_text), it receives as enter the output from qa_prompt1, which is a Message object
  4. For the final ChatPromptTemplate (qa_prompt2), it receives as enter the output from retrieve_text, which is a dict with ‘immediate’ as its single key

The above breakdown reveals how the construction of the pipeline described above matches completely with the information seen in serialized_input and chain_input

[ad_2]