Repository: truera/trulens
Issue: Issues with Multi-output Chain
Root cause: Interface Contract Mismatch

HI,
 i try to use trulens_eval with a chain that returns multi outputs, and it fails with following stack:
version of trulens:eval: 0.20.0

```sh
Traceback (most recent call last)
...
  File "../python3.10/site-packages/trulens_eval/tru_chain.py", line 310, in main_output
    if self.app.output_keys[0] in ret:
AttributeError: 'RunnableParallel' object has no attribute 'output_keys'
```

The reproducible code is:
```python
from trulens_eval import TruChain, Tru
tru = Tru()

from langchain_core.runnables.base import RunnableSerializable
from trulens_eval.instruments import instrument


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()
)

chain2_input = {"person": "obama", "language": "spanish"}

chain2.invoke(chain2_input)

tru_recorder = TruChain(
    chain2,
    app_id='Chain2'
)

with tru_recorder as recs:
    llm_response = chain2.invoke({"person": "obama", "language": "spanish"})

## MODIFICATION HERE:
## chain2 works, but the following chain3 does not
## chain3 return a multioutput in a dict with keys result and inputs.

from langchain_core.runnables import RunnableParallel, RunnablePassthrough
chain3 = (
    RunnableParallel(
        {"result":
            {"city": chain1, "language": itemgetter("language")}
            | prompt2
            | model
            | StrOutputParser(),
        "inputs": RunnablePassthrough()}
    )
)
## the chain works without tru_recorder
print(chain3.invoke(chain2_input))

tru_recorder = TruChain(
    chain3,
    app_id='Chain3'
)

# this fails
with tru_recorder as recs:
    llm_response = chain3.invoke({"person": "obama", "language": "spanish"})
```

Is it something that currently trulens can not do? or should i miss something?
Thanks

Investigating a bit, it looks that is is related to the fact that trulens is expecting a legacy chain object in this part of the code, instead of a RunnableSequence which looks like the new ways langchain is going to.
Maybe some issues related: https://github.com/truera/trulens/issues/641


Hi @anotine10 , looks like this was fixed in some recent changes in how main app input is determined. I'm seeing the context work with chain3.invoke . Please let us know if it works for you.

<!-- Answer -->
Hi, @anotine10,

I'm helping the trulens team manage their backlog and am marking this issue as stale. The issue was raised regarding an AttributeError when using trulens_eval with a chain that returns multiple outputs. User "piotrm0" commented that the issue seems to have been fixed in recent changes and suggested trying the context work with chain3.invoke.

Could you please confirm if this issue is still relevant to the latest version of the trulens repository? If it is, please let the trulens team know by commenting on the issue. Otherwise, feel free to close the issue yourself, or the issue will be automatically closed in 7 days.

Thank you!