Skip to content

Commit 22cdf4c

Browse files
committed
undo
1 parent d7552f1 commit 22cdf4c

File tree

2 files changed

+71
-28
lines changed

2 files changed

+71
-28
lines changed

weave/integrations/anthropic/anthropic_sdk.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,18 @@ def get_anthropic_patcher(
237237
"kind": base.kind or "llm",
238238
}
239239
)
240+
beta_messages_parse_settings = base.model_copy(
241+
update={
242+
"name": base.name or "anthropic.beta.Messages.parse",
243+
"kind": base.kind or "llm",
244+
}
245+
)
246+
beta_async_messages_parse_settings = base.model_copy(
247+
update={
248+
"name": base.name or "anthropic.beta.AsyncMessages.parse",
249+
"kind": base.kind or "llm",
250+
}
251+
)
240252
beta_stream_settings = base.model_copy(
241253
update={
242254
"name": base.name or "anthropic.beta.Messages.stream",
@@ -283,6 +295,16 @@ def get_anthropic_patcher(
283295
"AsyncMessages.create",
284296
create_wrapper_async(beta_async_messages_create_settings),
285297
),
298+
SymbolPatcher(
299+
lambda: importlib.import_module("anthropic.resources.beta.messages"),
300+
"Messages.parse",
301+
create_wrapper_sync(beta_messages_parse_settings),
302+
),
303+
SymbolPatcher(
304+
lambda: importlib.import_module("anthropic.resources.beta.messages"),
305+
"AsyncMessages.parse",
306+
create_wrapper_async(beta_async_messages_parse_settings),
307+
),
286308
SymbolPatcher(
287309
lambda: importlib.import_module("anthropic.resources.beta.messages"),
288310
"Messages.stream",

weave/integrations/google_genai/gemini_utils.py

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
from __future__ import annotations
2+
13
from collections.abc import Callable
24
from functools import wraps
3-
from typing import TYPE_CHECKING, Any, Optional
5+
from typing import TYPE_CHECKING, Any
46

57
import weave
68
from weave.trace.autopatch import OpSettings
@@ -74,44 +76,63 @@ def google_genai_gemini_on_finish(
7476

7577

7678
def google_genai_gemini_accumulator(
77-
acc: Optional["GenerateContentResponse"], value: "GenerateContentResponse"
78-
) -> "GenerateContentResponse":
79+
acc: GenerateContentResponse | None, value: GenerateContentResponse
80+
) -> GenerateContentResponse:
7981
if acc is None:
8082
return value
8183

82-
for i, value_candidate in enumerate(value.candidates):
83-
if i >= len(acc.candidates):
84+
value_candidates = value.candidates or []
85+
acc_candidates = acc.candidates or []
86+
for i, value_candidate in enumerate(value_candidates):
87+
if i >= len(acc_candidates):
8488
break
85-
for j, value_part in enumerate(value_candidate.content.parts):
86-
if j >= len(acc.candidates[i].content.parts):
87-
break
88-
if value_part.text is not None:
89-
acc.candidates[i].content.parts[j].text += value_part.text
90-
91-
if acc.usage_metadata.prompt_token_count is None:
92-
acc.usage_metadata.prompt_token_count = 0
93-
elif value.usage_metadata.prompt_token_count is not None:
94-
acc.usage_metadata.prompt_token_count += value.usage_metadata.prompt_token_count
95-
96-
if acc.usage_metadata.candidates_token_count is None:
97-
acc.usage_metadata.candidates_token_count = 0
98-
elif value.usage_metadata.candidates_token_count is not None:
99-
acc.usage_metadata.candidates_token_count += (
89+
90+
value_parts = value_candidate.content.parts or []
91+
for value_part in value_parts:
92+
if value_part.text is None:
93+
continue
94+
95+
# Check if this part is thinking content (thought=True)
96+
value_part_is_thought = getattr(value_part, "thought", False)
97+
98+
# Find matching part by type (thought vs non-thought), not by index
99+
matched = False
100+
for acc_part in acc.candidates[i].content.parts:
101+
acc_part_is_thought = getattr(acc_part, "thought", False)
102+
if acc_part_is_thought == value_part_is_thought:
103+
acc_part.text += value_part.text
104+
matched = True
105+
break
106+
107+
# If no matching part found, append as new part
108+
if not matched:
109+
acc.candidates[i].content.parts.append(value_part)
110+
111+
# Replace token counts with latest non-None values (Gemini returns cumulative counts)
112+
# Per Google docs: "When streaming output, the usageMetadata attribute only appears
113+
# on the last chunk of the stream."
114+
if value.usage_metadata.prompt_token_count is not None:
115+
acc.usage_metadata.prompt_token_count = value.usage_metadata.prompt_token_count
116+
117+
if value.usage_metadata.candidates_token_count is not None:
118+
acc.usage_metadata.candidates_token_count = (
100119
value.usage_metadata.candidates_token_count
101120
)
102121

103-
if acc.usage_metadata.total_token_count is None:
104-
acc.usage_metadata.total_token_count = 0
105-
elif value.usage_metadata.total_token_count is not None:
106-
acc.usage_metadata.total_token_count += value.usage_metadata.total_token_count
122+
if value.usage_metadata.total_token_count is not None:
123+
acc.usage_metadata.total_token_count = value.usage_metadata.total_token_count
107124

108-
if acc.usage_metadata.cached_content_token_count is None:
109-
acc.usage_metadata.cached_content_token_count = 0
110-
elif value.usage_metadata.cached_content_token_count is not None:
111-
acc.usage_metadata.cached_content_token_count += (
125+
if value.usage_metadata.cached_content_token_count is not None:
126+
acc.usage_metadata.cached_content_token_count = (
112127
value.usage_metadata.cached_content_token_count
113128
)
114129

130+
# Also handle thoughts_token_count for thinking models
131+
if getattr(value.usage_metadata, "thoughts_token_count", None) is not None:
132+
acc.usage_metadata.thoughts_token_count = (
133+
value.usage_metadata.thoughts_token_count
134+
)
135+
115136
return acc
116137

117138

0 commit comments

Comments
 (0)