core[minor]: Add message chunks to AnyMessage (#26057)

Adds the chunk variant of each Message to AnyMessage.

Required for this PR:
https://github.com/langchain-ai/langchain/pull/26050/files
This commit is contained in:
Eugene Yurtsev
2024-09-04 15:36:22 -04:00
committed by GitHub
parent 0a6c67ce6a
commit efa10c8ef8
4 changed files with 6722 additions and 57 deletions

View File

@@ -52,6 +52,12 @@ AnyMessage = Union[
SystemMessage,
FunctionMessage,
ToolMessage,
AIMessageChunk,
HumanMessageChunk,
ChatMessageChunk,
SystemMessageChunk,
FunctionMessageChunk,
ToolMessageChunk,
]

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,31 @@
# serializer version: 1
# name: test_double_nested_subgraph_mermaid[mermaid]
'''
%%{init: {'flowchart': {'curve': 'linear'}}}%%
graph TD;
__start__([__start__]):::first
parent_1(parent_1)
child_child_1_grandchild_1(grandchild_1)
child_child_1_grandchild_2(grandchild_2<hr/><small><em>__interrupt = before</em></small>)
child_child_2(child_2)
parent_2(parent_2)
__end__([__end__]):::last
__start__ --> parent_1;
child_child_2 --> parent_2;
parent_1 --> child_child_1_grandchild_1;
parent_2 --> __end__;
subgraph child
child_child_1_grandchild_2 --> child_child_2;
subgraph child_1
child_child_1_grandchild_1 --> child_child_1_grandchild_2;
end
end
classDef default fill:#f2f0ff,line-height:1.2
classDef first fill-opacity:0
classDef last fill:#bfb6fc
'''
# ---
# name: test_graph_sequence[ascii]
'''
+-------------+
@@ -450,6 +477,122 @@
'title': 'AIMessage',
'type': 'object',
}),
'AIMessageChunk': dict({
'additionalProperties': True,
'description': 'Message chunk from an AI.',
'properties': dict({
'additional_kwargs': dict({
'title': 'Additional Kwargs',
'type': 'object',
}),
'content': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'items': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'object',
}),
]),
}),
'type': 'array',
}),
]),
'title': 'Content',
}),
'example': dict({
'default': False,
'title': 'Example',
'type': 'boolean',
}),
'id': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'null',
}),
]),
'default': None,
'title': 'Id',
}),
'invalid_tool_calls': dict({
'default': list([
]),
'items': dict({
'$ref': '#/$defs/InvalidToolCall',
}),
'title': 'Invalid Tool Calls',
'type': 'array',
}),
'name': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'null',
}),
]),
'default': None,
'title': 'Name',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',
}),
'tool_call_chunks': dict({
'default': list([
]),
'items': dict({
'$ref': '#/$defs/ToolCallChunk',
}),
'title': 'Tool Call Chunks',
'type': 'array',
}),
'tool_calls': dict({
'default': list([
]),
'items': dict({
'$ref': '#/$defs/ToolCall',
}),
'title': 'Tool Calls',
'type': 'array',
}),
'type': dict({
'const': 'AIMessageChunk',
'default': 'AIMessageChunk',
'enum': list([
'AIMessageChunk',
]),
'title': 'Type',
'type': 'string',
}),
'usage_metadata': dict({
'anyOf': list([
dict({
'$ref': '#/$defs/UsageMetadata',
}),
dict({
'type': 'null',
}),
]),
'default': None,
}),
}),
'required': list([
'content',
]),
'title': 'AIMessageChunk',
'type': 'object',
}),
'ChatMessage': dict({
'additionalProperties': True,
'description': 'Message that can be assigned an arbitrary speaker (i.e. role).',
@@ -528,6 +671,84 @@
'title': 'ChatMessage',
'type': 'object',
}),
'ChatMessageChunk': dict({
'additionalProperties': True,
'description': 'Chat Message chunk.',
'properties': dict({
'additional_kwargs': dict({
'title': 'Additional Kwargs',
'type': 'object',
}),
'content': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'items': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'object',
}),
]),
}),
'type': 'array',
}),
]),
'title': 'Content',
}),
'id': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'null',
}),
]),
'default': None,
'title': 'Id',
}),
'name': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'null',
}),
]),
'default': None,
'title': 'Name',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',
}),
'role': dict({
'title': 'Role',
'type': 'string',
}),
'type': dict({
'const': 'ChatMessageChunk',
'default': 'ChatMessageChunk',
'enum': list([
'ChatMessageChunk',
]),
'title': 'Type',
'type': 'string',
}),
}),
'required': list([
'content',
'role',
]),
'title': 'ChatMessageChunk',
'type': 'object',
}),
'FunctionMessage': dict({
'additionalProperties': True,
'description': '''
@@ -603,6 +824,72 @@
'title': 'FunctionMessage',
'type': 'object',
}),
'FunctionMessageChunk': dict({
'additionalProperties': True,
'description': 'Function Message chunk.',
'properties': dict({
'additional_kwargs': dict({
'title': 'Additional Kwargs',
'type': 'object',
}),
'content': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'items': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'object',
}),
]),
}),
'type': 'array',
}),
]),
'title': 'Content',
}),
'id': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'null',
}),
]),
'default': None,
'title': 'Id',
}),
'name': dict({
'title': 'Name',
'type': 'string',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',
}),
'type': dict({
'const': 'FunctionMessageChunk',
'default': 'FunctionMessageChunk',
'enum': list([
'FunctionMessageChunk',
]),
'title': 'Type',
'type': 'string',
}),
}),
'required': list([
'content',
'name',
]),
'title': 'FunctionMessageChunk',
'type': 'object',
}),
'HumanMessage': dict({
'additionalProperties': True,
'description': '''
@@ -704,6 +991,84 @@
'title': 'HumanMessage',
'type': 'object',
}),
'HumanMessageChunk': dict({
'additionalProperties': True,
'description': 'Human Message chunk.',
'properties': dict({
'additional_kwargs': dict({
'title': 'Additional Kwargs',
'type': 'object',
}),
'content': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'items': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'object',
}),
]),
}),
'type': 'array',
}),
]),
'title': 'Content',
}),
'example': dict({
'default': False,
'title': 'Example',
'type': 'boolean',
}),
'id': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'null',
}),
]),
'default': None,
'title': 'Id',
}),
'name': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'null',
}),
]),
'default': None,
'title': 'Name',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',
}),
'type': dict({
'const': 'HumanMessageChunk',
'default': 'HumanMessageChunk',
'enum': list([
'HumanMessageChunk',
]),
'title': 'Type',
'type': 'string',
}),
}),
'required': list([
'content',
]),
'title': 'HumanMessageChunk',
'type': 'object',
}),
'InvalidToolCall': dict({
'description': '''
Allowance for errors made by LLM.
@@ -870,6 +1235,79 @@
'title': 'SystemMessage',
'type': 'object',
}),
'SystemMessageChunk': dict({
'additionalProperties': True,
'description': 'System Message chunk.',
'properties': dict({
'additional_kwargs': dict({
'title': 'Additional Kwargs',
'type': 'object',
}),
'content': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'items': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'object',
}),
]),
}),
'type': 'array',
}),
]),
'title': 'Content',
}),
'id': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'null',
}),
]),
'default': None,
'title': 'Id',
}),
'name': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'null',
}),
]),
'default': None,
'title': 'Name',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',
}),
'type': dict({
'const': 'SystemMessageChunk',
'default': 'SystemMessageChunk',
'enum': list([
'SystemMessageChunk',
]),
'title': 'Type',
'type': 'string',
}),
}),
'required': list([
'content',
]),
'title': 'SystemMessageChunk',
'type': 'object',
}),
'ToolCall': dict({
'description': '''
Represents a request to call a tool.
@@ -924,6 +1362,89 @@
'title': 'ToolCall',
'type': 'object',
}),
'ToolCallChunk': dict({
'description': '''
A chunk of a tool call (e.g., as part of a stream).
When merging ToolCallChunks (e.g., via AIMessageChunk.__add__),
all string attributes are concatenated. Chunks are only merged if their
values of `index` are equal and not None.
Example:
.. code-block:: python
left_chunks = [ToolCallChunk(name="foo", args='{"a":', index=0)]
right_chunks = [ToolCallChunk(name=None, args='1}', index=0)]
(
AIMessageChunk(content="", tool_call_chunks=left_chunks)
+ AIMessageChunk(content="", tool_call_chunks=right_chunks)
).tool_call_chunks == [ToolCallChunk(name='foo', args='{"a":1}', index=0)]
''',
'properties': dict({
'args': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'null',
}),
]),
'title': 'Args',
}),
'id': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'null',
}),
]),
'title': 'Id',
}),
'index': dict({
'anyOf': list([
dict({
'type': 'integer',
}),
dict({
'type': 'null',
}),
]),
'title': 'Index',
}),
'name': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'null',
}),
]),
'title': 'Name',
}),
'type': dict({
'const': 'tool_call_chunk',
'enum': list([
'tool_call_chunk',
]),
'title': 'Type',
'type': 'string',
}),
}),
'required': list([
'name',
'args',
'id',
'index',
]),
'title': 'ToolCallChunk',
'type': 'object',
}),
'ToolMessage': dict({
'additionalProperties': True,
'description': '''
@@ -1054,6 +1575,97 @@
'title': 'ToolMessage',
'type': 'object',
}),
'ToolMessageChunk': dict({
'additionalProperties': True,
'description': 'Tool Message chunk.',
'properties': dict({
'additional_kwargs': dict({
'title': 'Additional Kwargs',
'type': 'object',
}),
'artifact': dict({
'default': None,
'title': 'Artifact',
}),
'content': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'items': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'object',
}),
]),
}),
'type': 'array',
}),
]),
'title': 'Content',
}),
'id': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'null',
}),
]),
'default': None,
'title': 'Id',
}),
'name': dict({
'anyOf': list([
dict({
'type': 'string',
}),
dict({
'type': 'null',
}),
]),
'default': None,
'title': 'Name',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',
}),
'status': dict({
'default': 'success',
'enum': list([
'success',
'error',
]),
'title': 'Status',
'type': 'string',
}),
'tool_call_id': dict({
'title': 'Tool Call Id',
'type': 'string',
}),
'type': dict({
'const': 'ToolMessageChunk',
'default': 'ToolMessageChunk',
'enum': list([
'ToolMessageChunk',
]),
'title': 'Type',
'type': 'string',
}),
}),
'required': list([
'content',
'tool_call_id',
]),
'title': 'ToolMessageChunk',
'type': 'object',
}),
'UsageMetadata': dict({
'description': '''
Usage metadata for a message, such as token counts.
@@ -1115,6 +1727,24 @@
dict({
'$ref': '#/$defs/ToolMessage',
}),
dict({
'$ref': '#/$defs/AIMessageChunk',
}),
dict({
'$ref': '#/$defs/HumanMessageChunk',
}),
dict({
'$ref': '#/$defs/ChatMessageChunk',
}),
dict({
'$ref': '#/$defs/SystemMessageChunk',
}),
dict({
'$ref': '#/$defs/FunctionMessageChunk',
}),
dict({
'$ref': '#/$defs/ToolMessageChunk',
}),
]),
'title': 'RunnableParallel<as_list,as_str>Input',
}),
@@ -1250,63 +1880,6 @@
'''
# ---
# name: test_parallel_subgraph_mermaid[mermaid]
'''
%%{init: {'flowchart': {'curve': 'linear'}}}%%
graph TD;
__start__([__start__]):::first
outer_1(outer_1)
inner_1_inner_1(inner_1)
inner_1_inner_2(inner_2<hr/><small><em>__interrupt = before</em></small>)
inner_2_inner_1(inner_1)
inner_2_inner_2(inner_2)
outer_2(outer_2)
__end__([__end__]):::last
__start__ --> outer_1;
inner_1_inner_2 --> outer_2;
inner_2_inner_2 --> outer_2;
outer_1 --> inner_1_inner_1;
outer_1 --> inner_2_inner_1;
outer_2 --> __end__;
subgraph inner_1
inner_1_inner_1 --> inner_1_inner_2;
end
subgraph inner_2
inner_2_inner_1 --> inner_2_inner_2;
end
classDef default fill:#f2f0ff,line-height:1.2
classDef first fill-opacity:0
classDef last fill:#bfb6fc
'''
# ---
# name: test_double_nested_subgraph_mermaid[mermaid]
'''
%%{init: {'flowchart': {'curve': 'linear'}}}%%
graph TD;
__start__([__start__]):::first
parent_1(parent_1)
child_child_1_grandchild_1(grandchild_1)
child_child_1_grandchild_2(grandchild_2<hr/><small><em>__interrupt = before</em></small>)
child_child_2(child_2)
parent_2(parent_2)
__end__([__end__]):::last
__start__ --> parent_1;
child_child_2 --> parent_2;
parent_1 --> child_child_1_grandchild_1;
parent_2 --> __end__;
subgraph child
child_child_1_grandchild_2 --> child_child_2;
subgraph child_1
child_child_1_grandchild_1 --> child_child_1_grandchild_2;
end
end
classDef default fill:#f2f0ff,line-height:1.2
classDef first fill-opacity:0
classDef last fill:#bfb6fc
'''
# ---
# name: test_graph_single_runnable[ascii]
'''
+----------------------+
@@ -1341,6 +1914,36 @@
'''
# ---
# name: test_parallel_subgraph_mermaid[mermaid]
'''
%%{init: {'flowchart': {'curve': 'linear'}}}%%
graph TD;
__start__([__start__]):::first
outer_1(outer_1)
inner_1_inner_1(inner_1)
inner_1_inner_2(inner_2<hr/><small><em>__interrupt = before</em></small>)
inner_2_inner_1(inner_1)
inner_2_inner_2(inner_2)
outer_2(outer_2)
__end__([__end__]):::last
__start__ --> outer_1;
inner_1_inner_2 --> outer_2;
inner_2_inner_2 --> outer_2;
outer_1 --> inner_1_inner_1;
outer_1 --> inner_2_inner_1;
outer_2 --> __end__;
subgraph inner_1
inner_1_inner_1 --> inner_1_inner_2;
end
subgraph inner_2
inner_2_inner_1 --> inner_2_inner_2;
end
classDef default fill:#f2f0ff,line-height:1.2
classDef first fill-opacity:0
classDef last fill:#bfb6fc
'''
# ---
# name: test_trim
dict({
'edges': list([