Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
ContentBlockStopEvent,
CitationsSearchResultLocation,
InputJSONDelta,
RawContentBlockDeltaEvent,
RawContentBlockStartEvent,
RawContentBlockStopEvent,
TextBlock,
TextDelta,
ThinkingBlock,
Expand Down Expand Up @@ -443,7 +446,8 @@ def stream_chat(
)

def gen() -> Generator[AnthropicChatResponse, None, None]:
content = [LITextBlock(text="")]
content = []
cur_block = None
content_delta = ""
thinking = None
cur_tool_calls: List[ToolUseBlock] = []
Expand All @@ -453,13 +457,13 @@ def gen() -> Generator[AnthropicChatResponse, None, None]:
tracked_citations: Set[str] = set()
role = MessageRole.ASSISTANT
for r in response:
if isinstance(r, ContentBlockDeltaEvent):
if isinstance(r, (ContentBlockDeltaEvent, RawContentBlockDeltaEvent)):
if isinstance(r.delta, TextDelta):
content_delta = r.delta.text or ""
if not isinstance(content[-1], LITextBlock):
content.append(LITextBlock(text=content_delta))
if not isinstance(cur_block, LITextBlock):
cur_block = LITextBlock(text=content_delta)
else:
content[-1].text += content_delta
cur_block.text += content_delta

elif isinstance(r.delta, CitationsDelta) and isinstance(
r.delta.citation, CitationsSearchResultLocation
Expand All @@ -480,23 +484,23 @@ def gen() -> Generator[AnthropicChatResponse, None, None]:
)
)
elif isinstance(r.delta, SignatureDelta):
if thinking is None:
thinking = ThinkingBlock(
signature=r.delta.signature,
thinking="",
type="thinking",
if not isinstance(cur_block, LIThinkingBlock):
cur_block = LIThinkingBlock(
content="",
additional_information={"signature": r.delta.signature},
)
else:
thinking.signature += r.delta.signature
cur_block.additional_information["signature"] += (
r.delta.signature
)
elif isinstance(r.delta, ThinkingDelta):
if thinking is None:
thinking = ThinkingBlock(
signature="",
thinking=r.delta.thinking,
type="thinking",
if cur_block is None:
cur_block = LIThinkingBlock(
content=r.delta.thinking or "",
additional_information={"signature": ""},
)
else:
thinking.thinking += r.delta.thinking
cur_block.content += r.delta.thinking
elif isinstance(r.delta, CitationsDelta):
# TODO: handle citation deltas
cur_citations.append(r.delta.citation.model_dump())
Expand All @@ -523,29 +527,44 @@ def gen() -> Generator[AnthropicChatResponse, None, None]:
tool_calls_to_send = [*cur_tool_calls, cur_tool_call]
else:
tool_calls_to_send = cur_tool_calls

yield AnthropicChatResponse(
message=ChatMessage(
role=role,
blocks=content,
additional_kwargs={
"tool_calls": [
t.model_dump() for t in tool_calls_to_send
],
"thinking": thinking.model_dump() if thinking else None,
"tool_calls": [t.dict() for t in tool_calls_to_send]
},
),
citations=cur_citations,
delta=content_delta,
raw=dict(r),
)
elif isinstance(r, ContentBlockStartEvent):
elif isinstance(r, (ContentBlockStartEvent, RawContentBlockStartEvent)):
if isinstance(r.content_block, ToolUseBlock):
cur_tool_call = r.content_block
cur_tool_json = ""
elif isinstance(r, ContentBlockStopEvent):
elif isinstance(r, (ContentBlockStopEvent, RawContentBlockStopEvent)):
if isinstance(cur_tool_call, ToolUseBlock):
cur_tool_calls.append(cur_tool_call)

if cur_block is not None:
content.append(cur_block)
cur_block = None

yield AnthropicChatResponse(
message=ChatMessage(
role=role,
blocks=content,
additional_kwargs={
"tool_calls": [t.dict() for t in tool_calls_to_send]
},
),
citations=cur_citations,
delta=content_delta,
raw=dict(r),
)

return gen()

@llm_completion_callback()
Expand Down Expand Up @@ -615,7 +634,8 @@ async def astream_chat(
)

async def gen() -> ChatResponseAsyncGen:
content = [LITextBlock(text="")]
content = []
cur_block = None
content_delta = ""
thinking = None
cur_tool_calls: List[ToolUseBlock] = []
Expand All @@ -625,13 +645,13 @@ async def gen() -> ChatResponseAsyncGen:
tracked_citations: Set[str] = set()
role = MessageRole.ASSISTANT
async for r in response:
if isinstance(r, ContentBlockDeltaEvent):
if isinstance(r, (ContentBlockDeltaEvent, RawContentBlockDeltaEvent)):
if isinstance(r.delta, TextDelta):
content_delta = r.delta.text or ""
if not isinstance(content[-1], LITextBlock):
content.append(LITextBlock(text=content_delta))
if not isinstance(cur_block, LITextBlock):
cur_block = LITextBlock(text=content_delta)
else:
content[-1].text += content_delta
cur_block.text += content_delta

elif isinstance(r.delta, CitationsDelta) and isinstance(
r.delta.citation, CitationsSearchResultLocation
Expand All @@ -652,23 +672,23 @@ async def gen() -> ChatResponseAsyncGen:
)
)
elif isinstance(r.delta, SignatureDelta):
if thinking is None:
thinking = ThinkingBlock(
signature=r.delta.signature,
thinking="",
type="thinking",
if not isinstance(cur_block, LIThinkingBlock):
cur_block = LIThinkingBlock(
content="",
additional_information={"signature": r.delta.signature},
)
else:
thinking.signature += r.delta.signature
cur_block.additional_information["signature"] += (
r.delta.signature
)
elif isinstance(r.delta, ThinkingDelta):
if thinking is None:
thinking = ThinkingBlock(
signature="",
thinking=r.delta.thinking,
type="thinking",
if cur_block is None:
cur_block = LIThinkingBlock(
content=r.delta.thinking or "",
additional_information={"signature": ""},
)
else:
thinking.thinking += r.delta.thinking
cur_block.content += r.delta.thinking
elif isinstance(r.delta, CitationsDelta):
# TODO: handle citation deltas
cur_citations.append(r.delta.citation.model_dump())
Expand All @@ -695,27 +715,44 @@ async def gen() -> ChatResponseAsyncGen:
tool_calls_to_send = [*cur_tool_calls, cur_tool_call]
else:
tool_calls_to_send = cur_tool_calls

yield AnthropicChatResponse(
message=ChatMessage(
role=role,
blocks=content,
additional_kwargs={
"tool_calls": [t.dict() for t in tool_calls_to_send],
"thinking": thinking.model_dump() if thinking else None,
"tool_calls": [t.dict() for t in tool_calls_to_send]
},
),
citations=cur_citations,
delta=content_delta,
raw=dict(r),
)
elif isinstance(r, ContentBlockStartEvent):
elif isinstance(r, (ContentBlockStartEvent, RawContentBlockStartEvent)):
if isinstance(r.content_block, ToolUseBlock):
cur_tool_call = r.content_block
cur_tool_json = ""
elif isinstance(r, ContentBlockStopEvent):
elif isinstance(r, (ContentBlockStopEvent, RawContentBlockStopEvent)):
if isinstance(cur_tool_call, ToolUseBlock):
cur_tool_calls.append(cur_tool_call)

if cur_block is not None:
content.append(cur_block)
cur_block = None

yield AnthropicChatResponse(
message=ChatMessage(
role=role,
blocks=content,
additional_kwargs={
"tool_calls": [t.dict() for t in tool_calls_to_send]
},
),
citations=cur_citations,
delta=content_delta,
raw=dict(r),
)

return gen()

@llm_completion_callback()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ dev = [

[project]
name = "llama-index-llms-anthropic"
version = "0.9.3"
version = "0.9.4"
description = "llama-index llms anthropic integration"
authors = [{name = "Your Name", email = "[email protected]"}]
requires-python = ">=3.9,<4.0"
Expand Down
Loading