langchain icon indicating copy to clipboard operation
langchain copied to clipboard

Add chain to get multiple inputs from the LLM

Open amosjyng opened this issue 2 years ago • 2 comments

Right now, it seems that if you want to get multiple inputs from the LLM, you have to write a custom regex parser like ZeroShotAgent does with its get_action_and_input. I would like to suggest that we add an optional generic way to retrieve such inputs.

Please feel free to suggest or make changes to this PR!

amosjyng avatar Jan 27 '23 13:01 amosjyng

im not sure i really understand what this will be used for, so having a tough time reviewing it. what's a concrete example of how you would use it?

sorry for not understanding!

hwchase17 avatar Jan 28 '23 16:01 hwchase17

Sorry, I should've been clearer :P

You can use it like this to quickly get multiple inputs, one at a time:

from langchain.chains.multiple_outputs import GetMultipleOutputsChain
from langchain.llms.openai import OpenAI


llm = OpenAI(temperature=0, model_name="text-davinci-002")
print(GetMultipleOutputsChain(
    llm=llm,
    prefix="Generate a fictional person for me. Make sure to put all attributes in quotes.\n\n",
    variables={
        "first_name": "First Name",
        "last_name": "Last Name",
        "dob": "Date of birth",
        "gender": "Gender",
        "address": "Address",
    }
)({}))

Output:

{'first_name': 'Lydia', 'last_name': 'Smith', 'dob': 'June 12, 1990', 'gender': 'Female', 'address': '123 Elm Street'}

Extra complexity results from allowing the user to specify their own per-variable prompting for different types of LLM output (e.g. code blocks). For example, to get multiple pieces of code all at once:

from langchain.chains.multiple_outputs import GetMultipleOutputsChain, VariableConfig
from langchain.llms.openai import OpenAI


PREFIX = """
This is a Python function that calculates the Fibonacci sequence in a slow, recursive way.

```python
def fib(n):
    if n == 0 or n == 1:
        return n
    return fib(n - 1) + fib(n - 2)
```

Now rewrite this function in C++, JS, and Rust, along with accompany tests for each. Make sure to surround each code block with ```. Begin:

"""


async def do():
    llm = OpenAI(temperature=0, model_name="code-davinci-002")
    print(GetMultipleOutputsChain(
        llm=llm,
        prefix=PREFIX,
        variable_configs=[
            VariableConfig.for_code("cpp", "C++ Code", language="cpp"),
            VariableConfig.for_code("cpp_tests", "C++ Test Code", language="cpp"),
            VariableConfig.for_code("js", "JS Code", language="js"),
            VariableConfig.for_code("js_tests", "JS Test Code", language="js"),
        ]
    )({}))

Fragment of result (colored text is LLM output - sorry I mentioned "Rust" in the prefix but forgot to add it in the list of outputs to get from the LLM):

example

Having this chain lets you ask for all that without needing special parsing logic every time you want multiple outputs out of the LLM.

If you've gotten it working but don't want to use so many LLM calls, you can also write a custom output parser and parse the generated outputs all at once. Here is me refactoring ZeroShotAgent to use get_action_and_input as the basis for an output parser, so that I can compare between asking it for one input at a time, versus asking it for many (and also to compare between returning "Final Answer" as a decision rather than as a special dialogue option):

https://github.com/amosjyng/langchain/commit/a4670feb#diff-a97b7d5316f498629288bf0ce84cb650892bc9eeb696c16cf51fafcb5cde789a

Results were mixed in that case, but I had wanted to experiment to see how it goes.

This is the general idea. Please let me know if that helps clear things up!

amosjyng avatar Jan 30 '23 01:01 amosjyng

Closing as stale

eyurtsev avatar Aug 08 '23 14:08 eyurtsev