Skip to content

Commit 09b4699

Browse files
fix(langchain): use correct keyword argument name for chat messages [backport 1.17] (#6505)
Backport 19155cf from #6466 to 1.17. Resolves #6464. We were not using the correct keyword argument name for chat model messages, as well as for embeddings (we use the same method to trace `embed_query(text)` and `embed_documents(texts)`, and we previously only looked for `text`). This PR fixes this issue and adds test coverage for keyword argument usage into our existing test cases. For reference, below is the current code coverage for the langchain integration test suite. It is not the ideal 100% we would like it to be, but currently sitting at 93% is acceptable at this moment, especially considering the complexity/ambiguity of the integration and different model providers having different internal parameters. ``` Name Stmts Miss Cover ddtrace/contrib/langchain/patch.py 440 32 93% Missing coverage for lines: 36, 181, 280, 301-304, 309-312, 355-356, 446-447, 467-470, 475-478, 630-633, 638-643, 677 ``` ## Checklist - [x] Change(s) are motivated and described in the PR description. - [x] Testing strategy is described if automated tests are not included in the PR. - [x] Risk is outlined (performance impact, potential for breakage, maintainability, etc). - [x] Change is maintainable (easy to change, telemetry, documentation). - [x] [Library release note guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html) are followed. If no release note is required, add label `changelog/no-changelog`. - [x] Documentation is included (in-code, generated user docs, [public corp docs](https://github.com/DataDog/documentation/)). - [x] Backport labels are set (if [applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)) ## Reviewer Checklist - [x] Title is accurate. - [x] No unnecessary changes are introduced. - [x] Description motivates each change. - [x] Avoids breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes unless absolutely necessary. - [x] Testing strategy adequately addresses listed risk(s). - [x] Change is maintainable (easy to change, telemetry, documentation). - [x] Release note makes sense to a user of the library. - [x] Reviewer has explicitly acknowledged and discussed the performance implications of this PR as reported in the benchmarks PR comment. - [x] Backport labels are set in a manner that is consistent with the [release branch maintenance policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting) Co-authored-by: Yun Kim <[email protected]>
1 parent 2d1949d commit 09b4699

File tree

3 files changed

+23
-9
lines changed

3 files changed

+23
-9
lines changed

ddtrace/contrib/langchain/patch.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from ddtrace.contrib.trace_utils import wrap
2626
from ddtrace.internal.agent import get_stats_url
2727
from ddtrace.internal.logger import get_logger
28+
from ddtrace.internal.utils import ArgumentError
2829
from ddtrace.internal.utils import get_argument_value
2930
from ddtrace.internal.utils.formats import asbool
3031
from ddtrace.internal.utils.formats import deep_getattr
@@ -326,7 +327,7 @@ async def traced_llm_agenerate(langchain, pin, func, instance, args, kwargs):
326327
@with_traced_module
327328
def traced_chat_model_generate(langchain, pin, func, instance, args, kwargs):
328329
llm_provider = instance._llm_type.split("-")[0]
329-
chat_messages = get_argument_value(args, kwargs, 0, "chat_messages")
330+
chat_messages = get_argument_value(args, kwargs, 0, "messages")
330331
integration = langchain._datadog_integration
331332
span = integration.trace(
332333
pin,
@@ -417,7 +418,7 @@ def traced_chat_model_generate(langchain, pin, func, instance, args, kwargs):
417418
@with_traced_module
418419
async def traced_chat_model_agenerate(langchain, pin, func, instance, args, kwargs):
419420
llm_provider = instance._llm_type.split("-")[0]
420-
chat_messages = get_argument_value(args, kwargs, 0, "chat_messages")
421+
chat_messages = get_argument_value(args, kwargs, 0, "messages")
421422
integration = langchain._datadog_integration
422423
span = integration.trace(
423424
pin,
@@ -507,7 +508,15 @@ async def traced_chat_model_agenerate(langchain, pin, func, instance, args, kwar
507508

508509
@with_traced_module
509510
def traced_embedding(langchain, pin, func, instance, args, kwargs):
510-
input_texts = get_argument_value(args, kwargs, 0, "text")
511+
"""
512+
This traces both embed_query(text) and embed_documents(texts), so we need to make sure
513+
we get the right arg/kwarg.
514+
"""
515+
try:
516+
input_texts = get_argument_value(args, kwargs, 0, "texts")
517+
except ArgumentError:
518+
input_texts = get_argument_value(args, kwargs, 0, "text")
519+
511520
provider = instance.__class__.__name__.split("Embeddings")[0].lower()
512521
integration = langchain._datadog_integration
513522
span = integration.trace(
@@ -559,7 +568,7 @@ def traced_chain_call(langchain, pin, func, instance, args, kwargs):
559568
span = integration.trace(pin, "%s.%s" % (instance.__module__, instance.__class__.__name__), interface_type="chain")
560569
final_outputs = {}
561570
try:
562-
inputs = args[0]
571+
inputs = get_argument_value(args, kwargs, 0, "inputs")
563572
if not isinstance(inputs, dict):
564573
inputs = {instance.input_keys[0]: inputs}
565574
if integration.is_pc_sampled_span(span):
@@ -605,7 +614,7 @@ async def traced_chain_acall(langchain, pin, func, instance, args, kwargs):
605614
span = integration.trace(pin, "%s.%s" % (instance.__module__, instance.__class__.__name__), interface_type="chain")
606615
final_outputs = {}
607616
try:
608-
inputs = args[0]
617+
inputs = get_argument_value(args, kwargs, 0, "inputs")
609618
if not isinstance(inputs, dict):
610619
inputs = {instance.input_keys[0]: inputs}
611620
if integration.is_pc_sampled_span(span):
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
fixes:
3+
- |
4+
langchain: This fix resolves an issue where chat messages and embedding arguments
5+
passed in as keyword arguments were not parsed correctly and resulted in an ``ArgumentError``.

tests/contrib/langchain/test_langchain.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def test_openai_llm_sync_multiple_prompts(langchain, request_vcr):
181181
llm = langchain.llms.OpenAI()
182182
with request_vcr.use_cassette("openai_completion_sync_multi_prompt.yaml"):
183183
llm.generate(
184-
[
184+
prompts=[
185185
"What is the best way to teach a baby multiple languages?",
186186
"How many times has Spongebob failed his road test?",
187187
]
@@ -376,7 +376,7 @@ def test_llm_logs(langchain, ddtrace_config_langchain, request_vcr, mock_logs, m
376376
def test_openai_chat_model_sync_call(langchain, request_vcr):
377377
chat = langchain.chat_models.ChatOpenAI(temperature=0, max_tokens=256)
378378
with request_vcr.use_cassette("openai_chat_completion_sync_call.yaml"):
379-
chat([langchain.schema.HumanMessage(content="When do you use 'whom' instead of 'who'?")])
379+
chat(messages=[langchain.schema.HumanMessage(content="When do you use 'whom' instead of 'who'?")])
380380

381381

382382
@pytest.mark.skipif(sys.version_info >= (3, 10, 0), reason="Python 3.9 specific test")
@@ -622,13 +622,13 @@ def test_openai_embedding_document(langchain, request_vcr):
622622
@pytest.mark.snapshot
623623
def test_fake_embedding_query(langchain):
624624
embeddings = langchain.embeddings.FakeEmbeddings(size=99)
625-
embeddings.embed_query("foo")
625+
embeddings.embed_query(text="foo")
626626

627627

628628
@pytest.mark.snapshot
629629
def test_fake_embedding_document(langchain):
630630
embeddings = langchain.embeddings.FakeEmbeddings(size=99)
631-
embeddings.embed_documents(["foo", "bar"])
631+
embeddings.embed_documents(texts=["foo", "bar"])
632632

633633

634634
def test_openai_embedding_metrics(langchain, request_vcr, mock_metrics, mock_logs, snapshot_tracer):

0 commit comments

Comments
 (0)