mirror of
https://github.com/hwchase17/langchain.git
synced 2026-07-15 07:00:38 +00:00
fix(core): (v1) trace PDFs in v0 standard format (#33009)
This commit is contained in:
@@ -48,7 +48,6 @@ from langchain_core.messages import (
|
||||
message_chunk_to_message,
|
||||
)
|
||||
from langchain_core.messages.block_translators.openai import (
|
||||
convert_to_openai_data_block,
|
||||
convert_to_openai_image_block,
|
||||
)
|
||||
from langchain_core.output_parsers.openai_tools import (
|
||||
@@ -149,16 +148,18 @@ def _format_for_tracing(messages: list[BaseMessage]) -> list[BaseMessage]:
|
||||
block.get("type") == "file"
|
||||
and is_data_content_block(block) # v0 (image/audio/file) or v1
|
||||
and "base64" in block
|
||||
# Narrows to old Base64ContentBlock or new FileContentBlock
|
||||
# Backward compat: convert v1 base64 blocks to v0
|
||||
):
|
||||
if message_to_trace is message:
|
||||
# Shallow copy
|
||||
message_to_trace = message.model_copy()
|
||||
message_to_trace.content = list(message_to_trace.content)
|
||||
|
||||
message_to_trace.content[idx] = convert_to_openai_data_block( # type: ignore[index]
|
||||
block
|
||||
)
|
||||
message_to_trace.content[idx] = { # type: ignore[index]
|
||||
**{k: v for k, v in block.items() if k != "base64"},
|
||||
"data": block["base64"],
|
||||
"source_type": "base64",
|
||||
}
|
||||
elif len(block) == 1 and "type" not in block:
|
||||
# Tracing assumes all content blocks have a "type" key. Here
|
||||
# we add this key if it is missing, and there's an obvious
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""Test base chat model."""
|
||||
|
||||
import uuid
|
||||
import warnings
|
||||
from collections.abc import AsyncIterator, Iterator
|
||||
from typing import TYPE_CHECKING, Any, Literal, Optional, Union
|
||||
|
||||
@@ -505,6 +506,45 @@ def test_trace_images_in_openai_format() -> None:
|
||||
]
|
||||
|
||||
|
||||
def test_trace_pdfs() -> None:
|
||||
# For backward compat
|
||||
llm = ParrotFakeChatModel()
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "file",
|
||||
"mime_type": "application/pdf",
|
||||
"base64": "<base64 string>",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
tracer = FakeChatModelStartTracer()
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error")
|
||||
llm.invoke(messages, config={"callbacks": [tracer]})
|
||||
|
||||
assert tracer.messages == [
|
||||
[
|
||||
[
|
||||
HumanMessage(
|
||||
content=[
|
||||
{
|
||||
"type": "file",
|
||||
"mime_type": "application/pdf",
|
||||
"source_type": "base64",
|
||||
"data": "<base64 string>",
|
||||
}
|
||||
]
|
||||
)
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
def test_content_block_transformation_v0_to_v1_image() -> None:
|
||||
"""Test that v0 format image content blocks are transformed to v1 format."""
|
||||
# Create a message with v0 format image content
|
||||
|
||||
@@ -789,6 +789,22 @@ def test_format_message_content() -> None:
|
||||
for content in contents:
|
||||
assert expected == _format_message_content([content])
|
||||
|
||||
# Test warn if PDF is missing a filename
|
||||
pdf_block = {
|
||||
"type": "file",
|
||||
"base64": "<base64 data>",
|
||||
"mime_type": "application/pdf",
|
||||
}
|
||||
expected = [
|
||||
# N.B. this format is invalid for OpenAI
|
||||
{
|
||||
"type": "file",
|
||||
"file": {"file_data": "data:application/pdf;base64,<base64 data>"},
|
||||
}
|
||||
]
|
||||
with pytest.warns(match="filename"):
|
||||
assert expected == _format_message_content([pdf_block])
|
||||
|
||||
contents = [
|
||||
{"type": "file", "source_type": "id", "id": "file-abc123"},
|
||||
{"type": "file", "file_id": "file-abc123"},
|
||||
|
||||
Reference in New Issue
Block a user