Repository: mlflow/mlflow

Issue:
[BUG] Autologging using langchain failing with warning
### Issues Policy acknowledgement

- [X] I have read and agree to submit bug reports in accordance with the [issues policy](https://www.github.com/mlflow/mlflow/blob/master/ISSUE_POLICY.md)

### Where did you encounter this bug?

Local machine

### Willingness to contribute

No. I cannot contribute a bug fix at this time.

### MLflow version

- Client: 2.11.3
- Tracking server: 2.11.3

### System information

- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: Running in docker container python:3.10-slim-bookworm
- **Python version**: 3.10.14
- **yarn version, if running the dev UI**: N/A


### Describe the problem

When using autologging for langchain the run will encounter a warning in mlflow and not generate the artifact. The odd part is that I have other chains that mlflow works for but just not in the chain I am posting about.

This is the warning:

024/04/05 18:35:57 WARNING mlflow.utils.autologging_utils: Encountered unexpected error during langchain autologging: 'AsyncCallbackManager' object has no attribute 'append'

The run will complete without error but mlflow does not log anything. 

### Tracking information

<!-- PLEASE KEEP BACKTICKS AND CHECK PREVIEW -->
```shell
System information: Linux #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022
Python version: 3.10.14
MLflow version: 2.11.3
MLflow module location: /usr/local/lib/python3.10/site-packages/mlflow/__init__.py
Tracking URI: file:///app/mlruns
Registry URI: file:///app/mlruns
MLflow dependencies: 
  Flask: 3.0.2
  Jinja2: 3.1.3
  aiohttp: 3.9.3
  alembic: 1.13.1
  click: 8.1.7
  cloudpickle: 3.0.0
  docker: 7.0.0
  entrypoints: 0.4
  fastapi: 0.109.1
  gitpython: 3.1.43
  google-cloud-storage: 2.16.0
  graphene: 3.3
  gunicorn: 21.2.0
  importlib-metadata: 7.1.0
  markdown: 3.6
  matplotlib: 3.8.4
  numpy: 1.23.5
  packaging: 23.2
  pandas: 2.2.1
  protobuf: 4.25.3
  pyarrow: 15.0.2
  pydantic: 1.10.14
  pytz: 2024.1
  pyyaml: 6.0.1
  querystring-parser: 1.2.4
  requests: 2.31.0
  scikit-learn: 1.4.1.post1
  scipy: 1.10.0
  sqlalchemy: 2.0.25
  sqlparse: 0.4.4
  tiktoken: 0.5.2
  uvicorn: 0.15.0
```


### Code to reproduce issue

<!-- PLEASE KEEP BACKTICKS AND CHECK PREVIEW -->
```python
import mlflow

from typing import List, Tuple, Dict, Any

from langchain.prompts import ChatPromptTemplate
from langchain.prompts.prompt import PromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnableMap, RunnablePassthrough, RunnableLambda
from langchain_community.chat_models import ChatVertexAI
from langchain_community.llms import VertexAI
from langchain_core.runnables import Runnable

from langserve.pydantic_v1 import BaseModel
from langserve import add_routes
from fastapi import FastAPI


_TEMPLATE = """Given the following conversation and a follow up question, rephrase the 
follow up question to be a standalone question.

Chat History:
{chat_history}
Follow Up Input: {question}
Standalone question:"""
CONDENSE_QUESTION_PROMPT = PromptTemplate.from_template(_TEMPLATE)

_ANSWER_TEMPLATE = """Respond to the following question preceed the anwser with the pharse "This information was derived from public sources":

Question: {question}
Answer:
"""
ANSWER_PROMPT = ChatPromptTemplate.from_template(_ANSWER_TEMPLATE)

DEFAULT_DOCUMENT_PROMPT = PromptTemplate.from_template(template="{page_content}")

class ChatHistory(BaseModel):
    """Chat history with the bot."""

    chat_history: List[Tuple[str, str]] = []
    question: str
    embedding_model: str = "textembedding-gecko"
    model_name: str = "chat-bison@002"
    temperature: float = 0.7
    max_output_tokens: int = 1024
    custom_prompt: str = ""
    chat: bool = True
    llm_name: str = "VERTEXAI"
    user: str
    translation_language_code: str | None = None

class SearchResponse(BaseModel):
    question: str
    "The question that was asked"

    translated_answer: str | None = None
    "The translated answer to the question"

    context: Dict[Any, Any] = {}
    "The context of the answer"

    sources: str = ""
    "The sources of the answer"

    response: str = ""
    "The response to the question"

    followup_questions: List[str] = []
    "The follow-up questions to the answer"

    answer_with_citations: str
    "The answer with citations"

    matched_sources_list: List[str] = []
    "The matched sources list"

    link_list: List[str] = []
    "The list of links for the sources"

    filename_list: List[str] = []
    "The list of filenames for the sources"

    source_list: List[str] = []
    "The list of sources"

class PublicChain:
    def create_chain(self) -> Runnable[Dict[str, Any], str]:
        inputs = RunnableMap(
            standalone_question=RunnablePassthrough.assign(
                chat_history=lambda x: self._format_chat_history(x["chat_history"])
            )
            | CONDENSE_QUESTION_PROMPT
            | VertexAI(
                model_name="text-bison@002",
                temperature=0.7,
                max_output_tokens=1024,
            )
            | StrOutputParser(),
            user=lambda x: x["user"],
            translation_language_code=lambda x: x["translation_language_code"],
        )

        vertex_chat = ChatVertexAI(
            model_name="chat-bison@002",
            temperature=0.7,
            max_output_tokens=1024,
        )

        answer = {
            "answer": {"question": lambda x: x["standalone_question"]}
            | ANSWER_PROMPT
            | vertex_chat
            | StrOutputParser(),
            "user": lambda x: x["user"],
            "question": lambda x: x["standalone_question"],
            "translation_language_code": lambda x: x["translation_language_code"],
        }

        parser = RunnableLambda(self._parse_response)

        conversational_qa_chain = inputs | answer | parser
        return conversational_qa_chain.with_types(input_type=ChatHistory, output_type=SearchResponse)

    def _format_chat_history(self, chat_history: List[Tuple]) -> str:
        """Format chat history into a string."""
        buffer = ""
        for dialogue_turn in chat_history:
            human = "Human: " + dialogue_turn[0]
            ai = "Assistant: " + dialogue_turn[1]
            buffer += "\n" + "\n".join([human, ai])
        return buffer

    def _parse_response(self, params: Dict[str, Any]) -> SearchResponse:
        temp = SearchResponse(
            answer_with_citations=params["answer"],
            question=params["question"],
            response=params["answer"],
            translated_answer=params["translated_answer"] if params.get("translated_answer", None) else None,
        )
        return temp

app = FastAPI(
    title="LangChain Server",
    version="0.0.1",
)

mlflow.set_tracking_uri(uri="http://mlflow:80")
mlflow.langchain.autolog()

add_routes(app, PublicChain().create_chain(), path="/public")
```

Please note that I am using Langserve to create an API for the chain and then using the API to invoke the chain. The data is sent to another container where the artifacts are saved. This works with several other chains that I have created but it does not work for the one posted above.

### Stack trace

<!-- PLEASE KEEP BACKTICKS AND CHECK PREVIEW -->
```
WARNING mlflow.utils.autologging_utils: Encountered unexpected error during langchain autologging: 'AsyncCallbackManager' object has no attribute 'append'
```
Nothing else from mlflow is logged about this warning even when setting log level to DEBUG.

### Other info / logs

<!-- PLEASE KEEP BACKTICKS AND CHECK PREVIEW -->
This is everything that is printed prior to seeing the warning (nothing is printed after the warning).

```
LANGSERVE: Playground for chain "/public/" is live at:
LANGSERVE:  │
LANGSERVE:  └──> /public/playground/
LANGSERVE:
LANGSERVE: See all available routes at /docs/

INFO:     172.19.0.1:57812 - "GET /public/playground/ HTTP/1.1" 200 OK
INFO:     172.19.0.1:57810 - "GET /public/playground/assets/index-52e8ab2f.css HTTP/1.1" 200 OK
INFO:     172.19.0.1:57812 - "GET /public/playground/assets/index-dbc96538.js HTTP/1.1" 200 OK
INFO:     172.19.0.1:57812 - "GET /public/playground/favicon.ico HTTP/1.1" 200 OK
INFO:     172.19.0.1:58268 - "POST /public/stream_log HTTP/1.1" 200 OK
2024/04/05 19:10:57 WARNING mlflow.utils.git_utils: Failed to import Git (the Git executable is probably not on your PATH), so Git SHA is not available. Error: Failed to initialize: Bad git executable.
The git executable must be specified in one of the following ways:
    - be included in your $PATH
    - be set via $GIT_PYTHON_GIT_EXECUTABLE
    - explicitly set via git.refresh(<full-path-to-git-executable>)

All git commands will error until this is rectified.

This initial message can be silenced or aggravated in the future by setting the
$GIT_PYTHON_REFRESH environment variable. Use one of the following values:
    - quiet|q|silence|s|silent|none|n|0: for no message or exception
    - warn|w|warning|log|l|1: for a warning message (logging level CRITICAL, displayed by default)
    - error|e|exception|raise|r|2: for a raised exception

Example:
    export GIT_PYTHON_REFRESH=quiet

Run `python -m spacy download en_core_web_sm` to download en_core_web_sm model for text visualization.
```


### What component(s) does this bug affect?

- [X] `area/artifacts`: Artifact stores and artifact logging
- [ ] `area/build`: Build and test infrastructure for MLflow
- [ ] `area/deployments`: MLflow Deployments client APIs, server, and third-party Deployments integrations
- [ ] `area/docs`: MLflow documentation pages
- [ ] `area/examples`: Example code
- [ ] `area/model-registry`: Model Registry service, APIs, and the fluent client calls for Model Registry
- [ ] `area/models`: MLmodel format, model serialization/deserialization, flavors
- [ ] `area/recipes`: Recipes, Recipe APIs, Recipe configs, Recipe Templates
- [ ] `area/projects`: MLproject format, project running backends
- [ ] `area/scoring`: MLflow Model server, model deployment tools, Spark UDFs
- [ ] `area/server-infra`: MLflow Tracking server backend
- [X] `area/tracking`: Tracking Service, tracking client APIs, autologging

### What interface(s) does this bug affect?

- [ ] `area/uiux`: Front-end, user experience, plotting, JavaScript, JavaScript dev server
- [ ] `area/docker`: Docker use across MLflow's components, such as MLflow Projects and MLflow Models
- [ ] `area/sqlalchemy`: Use of SQLAlchemy in the Tracking Service or Model Registry
- [ ] `area/windows`: Windows support

### What language(s) does this bug affect?

- [ ] `language/r`: R APIs and clients
- [ ] `language/java`: Java APIs and clients
- [ ] `language/new`: Proposals for new client languages

### What integration(s) does this bug affect?

- [ ] `integrations/azure`: Azure and Azure ML integrations
- [ ] `integrations/sagemaker`: SageMaker integrations
- [ ] `integrations/databricks`: Databricks integrations


Discussion:
@cleretm-work Can you set `export MLFLOW_AUTOLOGGING_TESTING=true` and rerun your code? This should tell us where the error occurs.
Here is the stack trace after setting the flag to true:

File "/usr/local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 164, in __call__
  await self.app(scope, receive, _send)
File "/usr/local/lib/python3.10/site-packages/starlette/middleware/cors.py", line 83, in __call__
  await self.app(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
  await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
  raise exc
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
  await app(scope, receive, sender)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 762, in __call__
  await self.middleware_stack(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 782, in app
  await route.handle(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 297, in handle
  await self.app(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 77, in app
  await wrap_app_handling_exceptions(app, request)(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
  raise exc
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
  await app(scope, receive, sender)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 72, in app
  response = await func(request)
File "/usr/local/lib/python3.10/site-packages/fastapi/routing.py", line 299, in app
  raise e
File "/usr/local/lib/python3.10/site-packages/fastapi/routing.py", line 294, in app
  raw_response = await run_endpoint_function(
File "/usr/local/lib/python3.10/site-packages/fastapi/routing.py", line 191, in run_endpoint_function
  return await dependant.call(**values)
File "/usr/local/lib/python3.10/site-packages/langserve/server.py", line 481, in invoke
  return await api_handler.invoke(request)
File "/usr/local/lib/python3.10/site-packages/langserve/api_handler.py", line 729, in invoke
  output = await self._runnable.ainvoke(input_, config=config)
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 4076, in ainvoke
  return await self.bound.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2087, in ainvoke
  input = await step.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 3527, in ainvoke
  return await self._acall_with_config(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 1297, in _acall_with_config
  output = await coro
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 3484, in _ainvoke
  output = await output.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 4076, in ainvoke
  return await self.bound.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2087, in ainvoke
  input = await step.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2719, in ainvoke
  results = await asyncio.gather(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2087, in ainvoke
  input = await step.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 498, in ainvoke
  return await run_in_executor(config, self.invoke, input, config, **kwargs)
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/config.py", line 493, in run_in_executor
  return await asyncio.get_running_loop().run_in_executor(
File "/usr/local/lib/python3.10/concurrent/futures/thread.py", line 58, in run
  result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/site-packages/mlflow/utils/autologging_utils/safety.py", line 578, in safe_patch_function
  patch_function(call_original, *args, **kwargs)
File "/usr/local/lib/python3.10/site-packages/mlflow/langchain/_langchain_autolog.py", line 244, in patched_inference
  args, kwargs = _inject_mlflow_callback(func_name, mlflow_callback, args, kwargs)
File "/usr/local/lib/python3.10/site-packages/mlflow/langchain/_langchain_autolog.py", line 124, in _inject_mlflow_callback
  callbacks.append(mlflow_callback)
  | AttributeError: 'AsyncCallbackManager' object has no attribute 'append'
  | 
  | Request:  <starlette.requests.Request object at 0x40c0b63670>
  | INFO:     172.19.0.6:59676 - "POST /api/v1/langserve/invoke HTTP/1.1" 500 Internal Server Error
  | ERROR:    Exception in ASGI application
  | Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/uvicorn/protocols/http/h11_impl.py", line 373, in run_asgi
  result = await app(self.scope, self.receive, self.send)
File "/usr/local/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 75, in __call__
  return await self.app(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/fastapi/applications.py", line 1054, in __call__
  await super().__call__(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/applications.py", line 123, in __call__
  await self.middleware_stack(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 186, in __call__
  raise exc
File "/usr/local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 164, in __call__
  await self.app(scope, receive, _send)
File "/usr/local/lib/python3.10/site-packages/starlette/middleware/cors.py", line 83, in __call__
  await self.app(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
  await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
  raise exc
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
  await app(scope, receive, sender)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 762, in __call__
  await self.middleware_stack(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 782, in app
  await route.handle(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 297, in handle
  await self.app(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 77, in app
  await wrap_app_handling_exceptions(app, request)(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
  raise exc
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
  await app(scope, receive, sender)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 72, in app
  response = await func(request)
File "/usr/local/lib/python3.10/site-packages/fastapi/routing.py", line 299, in app
  raise e
File "/usr/local/lib/python3.10/site-packages/fastapi/routing.py", line 294, in app
  raw_response = await run_endpoint_function(
File "/usr/local/lib/python3.10/site-packages/fastapi/routing.py", line 191, in run_endpoint_function
  return await dependant.call(**values)
File "/usr/local/lib/python3.10/site-packages/langserve/server.py", line 481, in invoke
  return await api_handler.invoke(request)
File "/usr/local/lib/python3.10/site-packages/langserve/api_handler.py", line 729, in invoke
  output = await self._runnable.ainvoke(input_, config=config)
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 4076, in ainvoke
  return await self.bound.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2087, in ainvoke
  input = await step.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 3527, in ainvoke
  return await self._acall_with_config(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 1297, in _acall_with_config
  output = await coro
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 3484, in _ainvoke
  output = await output.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 4076, in ainvoke
  return await self.bound.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2087, in ainvoke
  input = await step.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2719, in ainvoke
  results = await asyncio.gather(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2087, in ainvoke
  input = await step.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 498, in ainvoke
  return await run_in_executor(config, self.invoke, input, config, **kwargs)
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/config.py", line 493, in run_in_executor
  return await asyncio.get_running_loop().run_in_executor(
File "/usr/local/lib/python3.10/concurrent/futures/thread.py", line 58, in run
  result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/site-packages/mlflow/utils/autologging_utils/safety.py", line 578, in safe_patch_function
  patch_function(call_original, *args, **kwargs)
File "/usr/local/lib/python3.10/site-packages/mlflow/langchain/_langchain_autolog.py", line 244, in patched_inference
  args, kwargs = _inject_mlflow_callback(func_name, mlflow_callback, args, kwargs)
File "/usr/local/lib/python3.10/site-packages/mlflow/langchain/_langchain_autolog.py", line 124, in _inject_mlflow_callback
  callbacks.append(mlflow_callback)
  | AttributeError: 'AsyncCallbackManager' object has no attribute 'append'
  | ERROR:uvicorn.error:Exception in ASGI application
  | Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/uvicorn/protocols/http/h11_impl.py", line 373, in run_asgi
  result = await app(self.scope, self.receive, self.send)
File "/usr/local/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 75, in __call__
  return await self.app(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/fastapi/applications.py", line 1054, in __call__
  await super().__call__(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/applications.py", line 123, in __call__
  await self.middleware_stack(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 186, in __call__
  raise exc
File "/usr/local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 164, in __call__
  await self.app(scope, receive, _send)
File "/usr/local/lib/python3.10/site-packages/starlette/middleware/cors.py", line 83, in __call__
  await self.app(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
  await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
  raise exc
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
  await app(scope, receive, sender)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 762, in __call__
  await self.middleware_stack(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 782, in app
  await route.handle(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 297, in handle
  await self.app(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 77, in app
  await wrap_app_handling_exceptions(app, request)(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
  raise exc
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
  await app(scope, receive, sender)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 72, in app
  response = await func(request)
File "/usr/local/lib/python3.10/site-packages/fastapi/routing.py", line 299, in app
  raise e
File "/usr/local/lib/python3.10/site-packages/fastapi/routing.py", line 294, in app
  raw_response = await run_endpoint_function(
File "/usr/local/lib/python3.10/site-packages/fastapi/routing.py", line 191, in run_endpoint_function
  return await dependant.call(**values)
File "/usr/local/lib/python3.10/site-packages/langserve/server.py", line 481, in invoke
  return await api_handler.invoke(request)
File "/usr/local/lib/python3.10/site-packages/langserve/api_handler.py", line 729, in invoke
  output = await self._runnable.ainvoke(input_, config=config)
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 4076, in ainvoke
  return await self.bound.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2087, in ainvoke
  input = await step.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 3527, in ainvoke
  return await self._acall_with_config(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 1297, in _acall_with_config
  output = await coro
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 3484, in _ainvoke
  output = await output.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 4076, in ainvoke
  return await self.bound.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2087, in ainvoke
  input = await step.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2719, in ainvoke
  results = await asyncio.gather(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2087, in ainvoke
  input = await step.ainvoke(
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 498, in ainvoke
  return await run_in_executor(config, self.invoke, input, config, **kwargs)
File "/usr/local/lib/python3.10/site-packages/langchain_core/runnables/config.py", line 493, in run_in_executor
  return await asyncio.get_running_loop().run_in_executor(
File "/usr/local/lib/python3.10/concurrent/futures/thread.py", line 58, in run
  result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/site-packages/mlflow/utils/autologging_utils/safety.py", line 578, in safe_patch_function
  patch_function(call_original, *args, **kwargs)
File "/usr/local/lib/python3.10/site-packages/mlflow/langchain/_langchain_autolog.py", line 244, in patched_inference
  args, kwargs = _inject_mlflow_callback(func_name, mlflow_callback, args, kwargs)
File "/usr/local/lib/python3.10/site-packages/mlflow/langchain/_langchain_autolog.py", line 124, in _inject_mlflow_callback
  callbacks.append(mlflow_callback)
  | AttributeError: 'AsyncCallbackManager' object has no attribute 'append'

Resolving patch:
diff --git a/mlflow/langchain/_langchain_autolog.py b/mlflow/langchain/_langchain_autolog.py
--- a/mlflow/langchain/_langchain_autolog.py
+++ b/mlflow/langchain/_langchain_autolog.py
@@ -121,8 +121,9 @@ def _inject_mlflow_callback(func_name, mlflow_callback, args, kwargs):
             config = RunnableConfig(callbacks=callbacks)
         else:
             callbacks = config.get("callbacks") or []
-            callbacks.append(mlflow_callback)
-            config["callbacks"] = callbacks
+            if not isinstance(callbacks, list):
+                callbacks = [callbacks]
+            config["callbacks"] = [*callbacks, mlflow_callback]
         if in_args:
             args = (args[0], config) + args[2:]
         else:
@@ -134,19 +135,22 @@ def _inject_mlflow_callback(func_name, mlflow_callback, args, kwargs):
         # https://github.com/langchain-ai/langchain/blob/7d444724d7582386de347fb928619c2243bd0e55/libs/langchain/langchain/chains/base.py#L320
         if len(args) >= 3:
             callbacks = args[2] or []
-            callbacks.append(mlflow_callback)
-            args = args[:2] + (callbacks,) + args[3:]
+            if not isinstance(callbacks, list):
+                callbacks = [callbacks]
+            args = args[:2] + ([*callbacks, mlflow_callback],) + args[3:]
         else:
             callbacks = kwargs.get("callbacks") or []
-            callbacks.append(mlflow_callback)
-            kwargs["callbacks"] = callbacks
+            if not isinstance(callbacks, list):
+                callbacks = [callbacks]
+            kwargs["callbacks"] = [*callbacks, mlflow_callback]
         return args, kwargs
 
     # https://github.com/langchain-ai/langchain/blob/7d444724d7582386de347fb928619c2243bd0e55/libs/core/langchain_core/retrievers.py#L173
     if func_name == "get_relevant_documents":
         callbacks = kwargs.get("callbacks") or []
-        callbacks.append(mlflow_callback)
-        kwargs["callbacks"] = callbacks
+        if not isinstance(callbacks, list):
+            callbacks = [callbacks]
+        kwargs["callbacks"] = [*callbacks, mlflow_callback]
         return args, kwargs
 
 
@@ -230,7 +234,6 @@ def __init__(self, *args, **kwargs):
             )
     else:
         tags = None
-    # TODO: test adding callbacks works
     # Use session_id-inference_id as artifact directory where mlflow
     # callback logs artifacts into, to avoid overriding artifacts
     session_id = getattr(self, "session_id", uuid.uuid4().hex)


Test patch:
diff --git a/tests/langchain/test_langchain_autolog.py b/tests/langchain/test_langchain_autolog.py
--- a/tests/langchain/test_langchain_autolog.py
+++ b/tests/langchain/test_langchain_autolog.py
@@ -11,6 +11,7 @@
 from langchain.llms import OpenAI
 from langchain.prompts import PromptTemplate
 from langchain.text_splitter import CharacterTextSplitter
+from langchain_core.callbacks import StdOutCallbackHandler
 from test_langchain_model_export import FAISS, DeterministicDummyEmbeddings
 
 import mlflow
@@ -221,15 +222,13 @@ def extract_history(input):
 
 def test_autolog_manage_run():
     mlflow.langchain.autolog(log_models=True, extra_tags={"test_tag": "test"})
-    run = mlflow.start_run()
-    with _mock_request(return_value=_mock_chat_completion_response()):
+    with mlflow.start_run() as run, _mock_request(return_value=_mock_chat_completion_response()):
         model = create_openai_llmchain()
         model.invoke("MLflow")
-    assert mlflow.active_run() is not None
+        assert mlflow.active_run() is not None
     assert MlflowClient().get_run(run.info.run_id).data.metrics != {}
     assert MlflowClient().get_run(run.info.run_id).data.tags["test_tag"] == "test"
     assert MlflowClient().get_run(run.info.run_id).data.tags["mlflow.autologging"] == "langchain"
-    mlflow.end_run()
 
 
 def test_autolog_manage_run_no_active_run():
@@ -685,3 +684,21 @@ def test_combine_input_and_output(input, output, expected):
     loaded_table = mlflow.load_table(INFERENCE_FILE_NAME, run_ids=[run.info.run_id])
     pdf = pd.DataFrame(expected)
     pd.testing.assert_frame_equal(loaded_table, pdf)
+
+
+@pytest.mark.parametrize("callbacks", [StdOutCallbackHandler(), [StdOutCallbackHandler()]])
+def test_langchain_autolog_callback_injection(callbacks):
+    mlflow.langchain.autolog(log_models=True, extra_tags={"test_tag": "test"})
+    with mlflow.start_run() as run, _mock_request(return_value=_mock_chat_completion_response()):
+        model = create_openai_llmchain()
+        model.invoke("MLflow", callbacks=callbacks)
+        assert mlflow.active_run() is not None
+    assert MlflowClient().get_run(run.info.run_id).data.metrics != {}
+    assert MlflowClient().get_run(run.info.run_id).data.tags["test_tag"] == "test"
+    assert MlflowClient().get_run(run.info.run_id).data.tags["mlflow.autologging"] == "langchain"
+    artifacts = get_artifacts(run.info.run_id)
+    for artifact_name in get_mlflow_callback_artifacts():
+        if isinstance(artifact_name, str):
+            assert artifact_name in artifacts
+        else:
+            assert any(artifact_name.match(artifact) for artifact in artifacts)