langchain: on_llm_start callback doesn't change the prompts sent to LLM

System Info

Python 3.10.12 langchain 0.0.233

Who can help?

@agola11

Information

  • The official example notebooks/scripts
  • My own modified scripts

Related Components

  • LLMs/Chat Models
  • Embedding Models
  • Prompts / Prompt Templates / Prompt Selectors
  • Output Parsers
  • Document Loaders
  • Vector Stores / Retrievers
  • Memory
  • Agents / Agent Executors
  • Tools / Toolkits
  • Chains
  • Callbacks/Tracing
  • Async

Reproduction

from typing import Dict, Union, Any, List

from langchain.callbacks.base import BaseCallbackHandler
from langchain.schema import AgentAction
from langchain.agents import AgentType, initialize_agent, load_tools
from langchain.callbacks import tracing_enabled
from langchain.llms import OpenAI
from langchain.schema.agent import AgentAction
from langchain.schema.output import LLMResult
from uuid import UUID

class MyCustomHandlerOne(BaseCallbackHandler):
    def on_llm_start(
        self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any
    ) -> Any:
        print(f"on_llm_start {prompts}")
        prompts[0] = "Tell me a joke?"
        print(f"on_llm_start {prompts}")

import langchain
langchain.verbose = True
langchain.debug = True

handler1 = MyCustomHandlerOne()
llm = OpenAI(temperature=0, streaming=True, callbacks=[handler1], verbose=True)
print(llm.__call__("""Context : Mr. Carl Smith is a 31-year-old man who has been experiencing homelessness 
                   on and off for all his adult life.
                   Questioin: How old is Mr. Carl Smith?"""))

The output is

on_llm_start ['Context : Mr. Carl Smith is a 31-year-old man who has been experiencing homelessness \n                   on and off for all his adult life.\n                   Questioin: How old is Mr. Carl Smith?']
on_llm_start ['Tell me a joke?']
[llm/start] [1:llm:OpenAI] Entering LLM run with input:
{
  "prompts": [
    "Tell me a joke?"
  ]
}
[llm/end] [1:llm:OpenAI] [699.067ms] Exiting LLM run with output:
{
  "generations": [
    [
      {
        "text": "\n\nAnswer: Mr. Carl Smith is 31 years old.",
        "generation_info": {
          "finish_reason": "stop",
          "logprobs": null
        }
      }
    ]
  ],
  "llm_output": {
    "token_usage": {},
    "model_name": "text-davinci-003"
  },
  "run": null
}


Answer: Mr. Carl Smith is 31 years old.

Expected behavior

LLM will respond to the new prompt set by the callback

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 3
  • Comments: 16 (8 by maintainers)

Most upvoted comments

Answer generated by a 🤖

Answer

Hello,

Thank you for reaching out with your question. The on_llm_start callback is not designed to modify the prompts. It is invoked before the LLM starts generating responses for the prompts and is used to perform any setup or initialization tasks that need to be done before the LLM starts. The return value of on_llm_start is stored in run_manager, but the original input_list is not modified.

Here is the relevant code from the generate method of the LLMChain class:

run_manager = callback_manager.on_chain_start(
    dumpd(self),
    {"input_list": input_list},
)

If you want to modify the prompts within a callback, you would need to implement this functionality yourself. However, this would likely involve significant changes to the LangChain framework, as the current design does not support modifying prompts within callbacks.

You can find more details about the on_llm_start callback and how it works in the LangChain framework in the source code:

I hope this helps clarify the issue. If you have any other questions, feel free to ask.

Best, Dosu

Sources


This response is meant to be useful, save you time, and share context. It is not meant to be a precise solution, but rather a starting point for your own research.

Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant.

I would like to modify the prompt in the on_llm_start as well, because I want to create a safeguard to prevent users from experiencing errors with the LLM API by exceeding the prompt’s token limit due to large observation of tool.

The errors occur occasionally as the tool is called multiple times… 😥

From

It seems like a far simpler approach to modify the prompt before you send it to the model in the first place 🤔

I’m assuming the solution you are suggesting is

# user app
prompts = ...
transformed_prompts = ...
Run chain(transformed_prompts)

What I’m trying to achieve

# some lib function
class CallBackHandler(...)
  def on_llm_start(...)
        transformed_prompts = ...
       return transformed_prompts
# user app
Run chain(prompts, callbacks=[CallBackHandler()])

which will make the user’s life easier.

What do you think?

@agola11 @hwchase17 is this true that callback is not designed to modify the prompts?