forked from google/adk-python
-
Notifications
You must be signed in to change notification settings - Fork 1
Add Anthropic Extended Thinking and Streaming Support #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
damithsenanayake
wants to merge
321
commits into
main
Choose a base branch
from
claude-thoughts-stream
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 4 commits
Commits
Show all changes
321 commits
Select commit
Hold shift + click to select a range
0aede9f
docs: Update CHANGELOG with [847df16](https://github.com/google/adk-p…
Jacksunwei cc24d61
feat: Support ContentUnion as static instruction
seanzhougoogle 9939e0b
feat: Support resuming a parallel agent with multiple branches paused…
XinranTang ae139bb
feat: ADK cli allows developers to create an eval set and add an eval…
ankursharmas 731bb90
chore: Announce the first ADK Community Call in the README
hangfei 9e0b1fb
fix: Create context cache only when prefix matches with previous request
seanzhougoogle 81913c8
chore: Update README md with recent ADK features
hangfei 64646e0
chore: Remove deprecated static methods from TrajectoryEvaluator
ankursharmas 9a6b850
feat: Add `bypass_multi_tools_limit` option to GoogleSearchTool and V…
xuanyang15 998264a
fix: Only exclude scores that are None
ankursharmas 85ed500
fix: Add support for file URIs in LiteLLM content conversion to fix i…
GWeale bddc70b
fix: Better handling the A2A streaming tasks so calling Agent can tel…
google-genai-bot 59670d2
feat: Support resuming from a paused invocation starting from a sub-a…
XinranTang 16b030b
fix: Add a guideline to avoid content deletion
joefernandez b21d0a5
fix: Add more clear instruction to the doc updater agent about one PR…
xuanyang15 6da7274
feat: Set default for `bypass_multi_tools_limit` to False for GoogleS…
google-genai-bot e63180c
feat: Add the support for returning `struct_data.uri` in DiscoveryEng…
xuanyang15 e212ff5
feat: Add new methods in the artifact service interface
google-genai-bot 348e552
chore: Remove deprecated `run_evals` from `cli_eval.py`
ankursharmas 214986e
chore: Adjust the instruction about default model
seanzhougoogle bb1ea74
chore: Delegate the agent state reset logic to LoopAgent
DeanChensj fa84bcb
chore: Correct the callback signatures
seanzhougoogle e2072af
feat: migrate invocation_context to callback_context
GWeale 2158b3c
fix: correctly populate context_id in remote_a2a_agent library when c…
google-genai-bot df05ed6
feat: migrate invocation_context to callback_context
google-genai-bot d8548aa
feat: add structured JSON logging with Cloud Trace correlation Close …
GWeale 3c0b99a
fix: rollback of add structured JSON logging with Cloud Trace correla…
GWeale dfb8638
chore: fix the `cleanup_unused_files` tool in yaml agent to use the s…
GWeale 0ec2b88
Merge branch 'main' into claude-thoughts-stream
damithsenanayake d22b8bf
chore: Clarify how to use adk built-in tool in instruction
seanzhougoogle 89344da
chore: Update agent builder instructions and remove run command details
GWeale bae2102
chore: Disable the scheduled execution for issue triage workflow
xuanyang15 9fbed0b
fix: Overall eval status should be NOT_EVALUATED if no invocations we…
jcpagadora737 2c7a342
feat: Add create_time and mime_type to ArtifactVersion
DeanChensj cb6d583
chore: Add RSVP link to ADK Community Call
hangfei 85c95a8
feat: Add create_time and mime_type to ArtifactVersion
google-genai-bot 141318f
feat: Support returning all sessions when user_id is none in the request
DeanChensj f9c09ef
feat: Support returning all sessions when user_id is none in the request
google-genai-bot 05aa3fa
fix: Remove the PR triaging agent's dependence on "bot triaged" label
xuanyang15 bf02129
Merge branch 'main' into claude-thoughts-stream
damithsenanayake d82c492
chore: Remove deprecated `convert_session_to_eval_format` function
ankursharmas 78e74b5
feat: Add require_confirmation param for MCP tool/toolset
wukath b650181
feat: add support for ContetxtWindowCompressionConfig in RunConfig
ac-machache a985cc3
feat: Support return all sessions when user id is none
DeanChensj 36c96ec
fix: #2883 pickle data was truncated error in database session using …
Lin-Nikaido 2424d6a
feat: Reorder create_time and mime_type to ArtifactVersion
google-genai-bot 6ab1498
fix: Add usage_metadata and citation_metadata to DatabaseSessionService
DeanChensj a17f3b2
feat: Allow custom request and event converters in A2aAgentExecutor
google-genai-bot 86097af
feat: Update AgentEvaluator to handle async ADK agent definitions
google-genai-bot 3734cea
fix: Use the agent's model when creating Google search agent tool
xuanyang15 f51380f
feat: Extend `ReflectAndRetryToolPlugin` to support hallucinating fun…
xuanyang15 1e1d63f
fix: Internal change
kibergus 5a543c0
feat: implement new methods in in-memory artifact service
google-genai-bot 9dc0036
ci: Add `state` info for PR triaging agent
xuanyang15 e50f05a
feat(otel): env variable for disabling llm_request and llm_response i…
jawoszek e6e2767
chore: Update gemini_llm_connection.py - typo spelling correction
DHHHG ce46386
docs: Bump models in llms and llms-full to Gemini 2.5
ggalloro 37a153e
ci: Fix the `logs` importing for PR triaging agent
xuanyang15 2a8fdd9
chore: Add computer use sample agent
seanzhougoogle 6dcbb5a
feat: Support dynamic per-request headers in MCPToolset
wukath 5ec3ae5
Merge branch 'main' into claude-thoughts-stream
damithsenanayake 307896a
fix: Exclude `additionalProperties` from Gemini schemas
GWeale 9dce06f
feat: Add rewind_async to support rewinding the session to before a p…
DeanChensj cf34032
chore: Fix evaluation test cases to only use pytest features
ankursharmas 8b3ed05
chore: Refactor and fix state management in the session service
DeanChensj 0df6759
chore: Checks gemini version for `2 and above` for gemini-builtin tools
Jacksunwei a2d9f13
chore: Add span for context caching handling and new cache creation
seanzhougoogle dbd818b
feat: introduces a new AgentEngineSandboxCodeExecutor class that supp…
google-genai-bot af74eba
test: Skips test_langchain_tool.py temporarily after their new 1.0.0 …
Jacksunwei a5b742b
feat: introduces a new AgentEngineSandboxCodeExecutor class that supp…
google-genai-bot d327538
chore: Throw 409 already exist error when trying to create a session …
DeanChensj fd25c23
Merge branch 'main' into claude-thoughts-stream
damithsenanayake ee39a89
feat: introduces a new AgentEngineSandboxCodeExecutor class that supp…
google-genai-bot 0b73a69
fix: Handle App objects in eval and graph endpoints
ejfn 6a5eac0
feat: Allow passing extra kwargs to create_session of VertexAiSession…
DeanChensj 9de3b54
Merge branch 'main' into claude-thoughts-stream
damithsenanayake 0bdba30
docs: format README.md for samples
Jacksunwei 4a842c5
fix(cli): Improve error message when adk web is run in wrong directory
jpantsjoha aeaec85
feat: Adds Static User Simulator and User Simulator Provider
google-genai-bot dc4975d
fix: relax runner app-name enforcement
GWeale fe1fc75
chore: Improve hint message in agent loader
GWeale b83b608
Merge branch 'main' into claude-thoughts-stream
damithsenanayake ce3418a
fix: Fix BuiltInCodeExecutor so that it can support visualizations
wukath ed37e34
feat(tools): support additional headers for google api toolset #non-b…
Prhmma c850da3
fix: Fix the broken langchain importing caused their 1.0.0 release
xuanyang15 2a901d1
chore: Raise AlreadyExistsError when trying to create a resource with…
DeanChensj 409df13
feat: Granular Per Agent Speech Configuration
391628f
feat: Add a service registry to provide a generic way to register cus…
DeanChensj aab2504
chore: update adk web
wyf7107 7d5c6b9
fix: Fixes the identity prompt to be one line and add ending period a…
Jacksunwei d4dc645
chore: Fixes MCPToolset --> McpToolset in various places
Jacksunwei 4df9263
fix: Returns dict as result from McpTool
Jacksunwei 2f4f561
fix:Remove unnecessary Aclosing
kibergus 2724819
chore: update adk web, fixing cursor color, and thought bubble
wyf7107 c6cf11c
chore:Rename conformance `create` command to `record`
wuliang229 d8c66fe
fix: Update the saving artifact text for BuiltInCodeExecutor to be mo…
wukath 91cc03e
chore: Bump ADK version to 1 17 0
hangfei 3ee1cd2
chore:Update conformance `create` command to `record` in documentation
wuliang229 e28d3c5
chore: Add a pull request template
xuanyang15 c9647f3
docs: Update agent builder instructions to require explicit `agent_cl…
GWeale 392067e
Merge branch 'main' into claude-thoughts-stream
damithsenanayake f1e01ea
docs: Update ADK Agent Builder Assistant instructions and clarified b…
GWeale c426c48
No public description
google-genai-bot 4c58b76
docs: Update ADK Agent Builder Assistant instructions for workflow tools
GWeale 23092a2
feat: Consolidate external dependencies in a single place
ankursharmas 33fd712
chore: Remove community call announcement from README
hangfei 055e86a
chore: Update ADK README with new features
hangfei 9cf7ab1
docs: Update agent builder instructions for clarity and best practice…
GWeale 45a2168
chore: Adds a new sample agent that demonstrates how to integrate Pos…
Vrajesh-Babu 6d4d72a
chore: Update vertexai & rouge scorer dependencies in eval to use a p…
ankursharmas 955632c
feat:Allow agent evaluation from modules ending in ".agent"
ankursharmas ba63176
feat: Introduce custom_metadata field to `run_config` and propagate a…
google-genai-bot bb32a63
chore: Adding traceback logging to inference step of eval
ankursharmas 0dbfb43
fix: Update `_evaluate_single_inference_result` documentation
alDuncanson 0660779
docs: Update agent builder instructions to restrict fields on workflo…
GWeale 0d0fb4d
ci: Remove reviewer assignment in the PR triaging agent
xuanyang15 53209f1
docs: Clarify research tool instructions in YAML agent
GWeale d193c39
docs: Add root agent requirement to instructions so it does not creat…
GWeale d767fcc
chore: Add Community Events section to README
hangfei 64d9d69
chore: Remove rogue print statement from agent_evaluator.py
google-genai-bot 97a224f
chore: Clean up rag memory dependencies
DeanChensj 54c4ecc
feat: Adds LLM-Backed User Simulator
KPJoshi fb96d17
fix: Fix import for live bidi streaming single agent
wukath f8a9672
docs: Make sure `LlmAgent` as the immutable root agent in ADK configu…
GWeale 5d9a7e7
feat: enable persistent browser sessions in the computer use sample
google-genai-bot e6f7363
fix: set `execute_tool {tool.name}` span attributes even when excepti…
RKest 2c68a12
Merge branch 'main' into claude-thoughts-stream
damithsenanayake 16d4b9a
docs: Revise BaseAgent.after_agent_callback to be more clear
Jacksunwei e0e5384
chore: Limits fastapi to <0.119, so that swagger api can still render
Jacksunwei 48ddd07
chore:clarify the behavior of disallow_transfer_to_parent
wuliang229 f7e2a7a
chore: Make VertexAiSessionService fully asynchronous
DeanChensj 496f8cd
fix: output file uploading to artifact service should handle both bas…
google-genai-bot 36ca4f1
feat: Add `on_tool_error_callback` in `LlmAgent`
xuanyang15 1a4261a
fix: Fix issue with MCP tools throwing an error
google-genai-bot e194ebb
feat: Implement artifact_version related methods in GcsArtifactService
DeanChensj ab00c41
fix: nullable types with gen ai bump
MarlzRana 1ca8206
docs: Automatically create `__init__.py` files when writing Python files
GWeale 19f5246
docs: Update ADK agent builder instructions for model callback signat…
GWeale 0a87e02
fix: Rename agent config files to match the agent name
GWeale b7dbfed
feat: Add BigQueryLoggingPlugin for event logging to BigQuery
google-genai-bot 00d147d
fix: check if eval config file exists
ankursharmas 87dcb3f
feat: Add ApigeeLlm as a model that let's ADK Agent developers to con…
google-genai-bot 6c3882f
fix: Creates evalset directory on evalset create
hoonji 86f0155
docs: Fixes null check for reflect_retry plugin sample
Jacksunwei 9ab17f2
fix: Yield the long running tool response before pausing execution
DeanChensj b17c8f1
chore: Marked expected_invocation as optional field on evaluator inte…
ankursharmas 240ef5b
feat: Added support for enums as arguments for function tools (#3088)
SOORAJTS2001 74d8361
fix: Add a fallback user message to LiteLLM requests if the last user…
GWeale 9851340
feat: Add Bigquery detect_anomalies tool
google-genai-bot 971eafa
feat: Add `crewai[tools]` to `pyproject.toml` test section
wuliang229 61adfcd
refactor: Adds a util method to check the enablement of any env variable
Jacksunwei 1aa9bb1
chore: Update vertex ai in example store and rag retrieval to use proxy
ankursharmas edfe553
feat: Add sample agent for VertexAiCodeExecutor
enisher 8eeff35
feat: Demonstrate CodeExecutor customization for environment setup
enisher 2f72ceb
chore: Do not treat `FinishReason.STOP` as error case for LLM respons…
speedstorm1 420de9c
test: Add a test case for resuming any invocation
XinranTang ee8acc5
chore: Allow tenacity 9.0.0
speedstorm1 15afbcd
feat: Add `ADK_DISABLE_LOAD_DOTENV` environment variable that disable…
speedstorm1 74a3500
fix: #3036 parameter filtering for CrewAI functions with **kwargs
omarcevi 6bdac02
fix: do not consider events with state delta and no content as final …
kevinkassimo 1ee93c8
fix: do not consider events with state delta and no content as final …
google-genai-bot c8e5340
fix: Propagate MCP tools output schema to FunctionDeclaration
vishwa180 746dbff
Merge branch 'main' into claude-thoughts-stream
damithsenanayake 0ce2d56
chore: Update agent triaging rules and owners
GWeale 2216fe7
docs: Update AGENTS.md with latest development guidelines and make it…
Jacksunwei e7f7705
ADK changes
google-genai-bot 87f415a
feat: Add util to run ADK LLM Agent with simulation environment
google-genai-bot c0c67c8
feat: Add ADK-based agent factory for Tau-bench
google-genai-bot 592c5d8
feat: Add initial colab to run GEPA on Tau-bench with ADK
google-genai-bot 04dbc42
feat: Improve Tau-bench ADK colab stability
google-genai-bot d45b31f
chore: Ignore AI coding tool project-specific configs in .gitignore
Jacksunwei 9014a84
feat: Add api key argument to Vertex Session and Memory services for …
google-genai-bot 7a41d97
Merge branch 'main' into claude-thoughts-stream
damithsenanayake b23eed6
feat: Remove `@experimental` from `App` class
hangfei 72a8d8d
fix: Session input file are required for creating an eval case
ankursharmas 6429457
feat: Add get_job_info tool to BigQuery toolset
dongyuj1 71aa564
fix: Propagate LiteLLM finish_reason to LlmResponse for use in callbacks
lizzij 01b48c0
feat: Add example demonstrating JSON passing between agents
lizzij f9569bb
fix: Enable usage metadata in LiteLLM streaming
lizzij fc15c9a
fix: Update DynamicPickleType to support MySQL dialect
hung12ct 3814d8b
docs: Update agent builder assistant to query knowledge base through …
xuanyang15 ce8f674
fix: Allow LLM request to override the model used in the generate con…
ayam04 c0892c7
chore: remove legacy validation that forbids co-exist of agent transf…
ec86608
docs: Add sample agent to test support of output_schema, tools and su…
9704d27
ci: Add a github action to automatically close the PR imported and co…
Jacksunwei d3796f9
feat: Add example for using ADK with Fast MCP sampling
lizzij 1e6a9da
fix: Change instruction insertion to respect tool call/response pairs
GWeale b0017ae
chore: Revise README for clarity and consistency
Shubhamsaboo 5eca72f
fix: Correct message part ordering in A2A history
speedstorm1 34d9b53
feat: Enhance error messages for tool and agent not found errors
jpantsjoha 610e219
ci: Fixes the copybara-pr-handler.yml file location, it should be und…
Jacksunwei 2274c4f
feat: Add "final_session_state" to the EvalCase data model
google-genai-bot b8a2b6c
fix: include delimiter when matching events from parent nodes in cont…
kevinkassimo 5cb35db
chore: Avoid rendering empty columns as part of detailed results rend…
ankursharmas dea7668
chore: Allow google-cloud-storage >=3.0.0
speedstorm1 546c2a6
feat: Remove custom polling logic for Vertex AI Session Service since…
google-genai-bot a2c6a8a
feat: Expose the Python code run by the code interpreter in the logs
lizzij 338c3c8
fix: Add example and fix for loading and upgrading old ADK session da…
dongyuj1 156d235
feat: Allow injecting a custom Runner into `agent_to_a2a`
dongyuj1 0b56f22
refactor(bigquery): Remove dataset_id from logging schema
google-genai-bot 0487eea
feat: add run_debug() helper method for quick agent experimentation
lavinigam-gcp a0df75b
chore: Add support for reversed proxy in adk web, users can use an op…
wyf7107 e8526f7
fix: Fix credential manager so that it supports the ServiceAccountCre…
wukath b1ff85f
chore: Add support for specifying logging level for adk eval cli command
ankursharmas c4c127d
fix: fix typo in local_eval_service.py
FingerLiu 4124f54
refactor: Remove unnecessary branching in run_cli
ftnext 44aa821
docs: fix spelling error in `response_for_auth_required` parameter do…
dunnkers 71b01ef
Merge branch 'main' into claude-thoughts-stream
damithsenanayake 2c6d6e1
fix: fix typo for --save_session option in `adk run --resume` help
ftnext 308da62
docs: updates CONTRIBUTING.md
ghchinoy a02f321
chore(otel): Change default of trace_to_cloud to None for Agent Engin…
jawoszek 92a7d19
fix: Undo adding MCP tools output schema to FunctionDeclaration
xuanyang15 8dff850
fix: Support models slash prefix in model name extraction
google-genai-bot aa12336
chore: Fix spelling
jsoref c33a680
docs: Add instructions to prevent tool hallucination
GWeale f81ebdb
fix: Bug when callback_context_invocation_context is missing in Globa…
UlookEE 8b6ee57
chore: remove working_in_progress for agent builder endpoints
wyf7107 6a94af2
chore: Disable SetModelResponseTool workaround for Vertex AI Gemini 2…
xuanyang15 d2888a3
fix: Fix typo in several files
UlookEE 38ea749
feat: Extend Bigquery detect_anomalies tool to support future data an…
google-genai-bot 489c39d
fix: Remove redundant `format` field from LiteLLM content objects
GWeale e25beb4
docs: Refine ADK triaging agent labeling guidelines and response format
GWeale d4c63fc
chore: Add model tracking to LiteLlm and introduce a LiteLLM with fal…
csvenja ce91a8e
fix: Pass drop_params to LiteLLM completion API
GWeale abdc2bb
chore: update adk web for adk web builder: https://github.com/google/…
wyf7107 4f85e86
feat: Add support for extracting cache-related token counts from Lite…
lizzij 2435dcc
Merge branch 'main' into claude-thoughts-stream
damithsenanayake 6e5c0eb
feat: Add token usage to live events for bidi streaming
wukath 54db3d4
fix: update the contribution analysis tool to use original write mode
google-genai-bot 432d30a
chore: Add Community Repo section to README
hangfei 11571c3
fix: Reduce logging spam for MCP tools without authentication
wukath 88032cf
feat: Support MCP prompts
wukath 033f5a5
feat: Add configuration options to BigQuery logging plugin
google-genai-bot d4b2a8b
feat: Add support for Vertex AI Express Mode when deploying to Agent …
yeesian 0c49aef
chore: correct typo in pyproject.toml (swtich → switch)
marsboy02 4284c61
fix: agent evaluations detailed output rows wrapping issue
nimanthadilz 63353b2
feat: Refactor gepa sample code and clean-up user demo colab
google-genai-bot e01e54e
chore: Bumps version to v1.18.0 and updates CHANGELOG.md
xuanyang15 0b1784e
fix: Update dependency version constraints to be based on PyPI versions
yeesian aa77834
chore: Update Gemini Live model names in live bidi streaming sample
hangfei 0826755
chore: Stop logging the full content of LLM blobs
hangfei d8d7774
chore: Update v1.18.0 wheel and CHANGELOG.md
xuanyang15 744f94f
fix: Add None check for `event` in `remote_a2a_agent.py`
google-genai-bot d6b928b
chore: Returns agent state regardless if ctx.is_resumable
DeanChensj 9ec38c0
feat: Add on_model_error_callback in LlmAgent
xuanyang15 e02f177
feat: Improve gepa tau-bench colab for external use
google-genai-bot 2b31bd9
chore: Fix spelling: provide
jsoref d9ec07d
docs: Improve Agent Builder Assistant schema reference for prompts
GWeale 99ca6aa
feat: add file-backed artifact service
GWeale 9a92aa5
Merge branch 'main' into claude-thoughts-stream
damithsenanayake File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,6 +30,7 @@ | |
| from typing import Union | ||
|
|
||
| from anthropic import AnthropicVertex | ||
| from anthropic import AsyncAnthropicVertex | ||
| from anthropic import NOT_GIVEN | ||
| from anthropic import types as anthropic_types | ||
| from google.genai import types | ||
|
|
@@ -166,7 +167,82 @@ def content_block_to_part( | |
| ) | ||
| part.function_call.id = content_block.id | ||
| return part | ||
| raise NotImplementedError("Not supported yet.") | ||
|
|
||
| # Handle thinking blocks from Anthropic extended thinking feature | ||
| # Thinking blocks have a 'thinking' attribute containing the reasoning text | ||
| if hasattr(content_block, "thinking"): | ||
| thinking_text = content_block.thinking | ||
| logger.info(f"Received thinking block ({len(thinking_text)} chars)") | ||
| # Return as Part with thought=True (standard GenAI format) | ||
| return types.Part(text=thinking_text, thought=True) | ||
|
|
||
| # Alternative check: some versions may use type attribute | ||
| if ( | ||
| hasattr(content_block, "type") | ||
| and getattr(content_block, "type", None) == "thinking" | ||
| ): | ||
| thinking_text = str(content_block) | ||
| logger.info( | ||
| f"Received thinking block via type check ({len(thinking_text)} chars)" | ||
| ) | ||
| # Return as Part with thought=True (standard GenAI format) | ||
| return types.Part(text=thinking_text, thought=True) | ||
|
|
||
| raise NotImplementedError( | ||
| f"Not supported yet: {type(content_block).__name__}" | ||
| ) | ||
|
|
||
|
|
||
| def streaming_event_to_llm_response( | ||
| event: anthropic_types.MessageStreamEvent, | ||
| ) -> Optional[LlmResponse]: | ||
| """Convert Anthropic streaming events to ADK LlmResponse format. | ||
|
|
||
| Args: | ||
| event: Anthropic streaming event | ||
|
|
||
| Returns: | ||
| LlmResponse or None if event should be skipped | ||
| """ | ||
| # Handle content block deltas | ||
| if event.type == "content_block_delta": | ||
| delta = event.delta | ||
|
|
||
| # Text delta | ||
| if delta.type == "text_delta": | ||
| return LlmResponse( | ||
| content=types.Content( | ||
| role="model", | ||
| parts=[types.Part.from_text(text=delta.text)], | ||
| ), | ||
| partial=True, | ||
| ) | ||
|
|
||
| # Thinking delta | ||
| elif delta.type == "thinking_delta": | ||
| return LlmResponse( | ||
| content=types.Content( | ||
| role="model", | ||
| parts=[types.Part(text=delta.thinking, thought=True)], | ||
| ), | ||
| partial=True, | ||
| ) | ||
|
|
||
| # Handle message deltas (usage updates) | ||
| elif event.type == "message_delta": | ||
| if hasattr(event, "usage"): | ||
| input_tokens = getattr(event.usage, "input_tokens", 0) | ||
| output_tokens = getattr(event.usage, "output_tokens", 0) | ||
| return LlmResponse( | ||
| usage_metadata=types.GenerateContentResponseUsageMetadata( | ||
| prompt_token_count=input_tokens, | ||
| candidates_token_count=output_tokens, | ||
| total_token_count=input_tokens + output_tokens, | ||
| ), | ||
| ) | ||
|
|
||
| # Ignore start/stop events | ||
| return None | ||
|
|
||
|
|
||
| def message_to_generate_content_response( | ||
|
|
@@ -283,19 +359,127 @@ async def generate_content_async( | |
| if llm_request.tools_dict | ||
| else NOT_GIVEN | ||
| ) | ||
| # TODO(b/421255973): Enable streaming for anthropic models. | ||
| message = self._anthropic_client.messages.create( | ||
| model=llm_request.model, | ||
| system=llm_request.config.system_instruction, | ||
| messages=messages, | ||
| tools=tools, | ||
| tool_choice=tool_choice, | ||
| max_tokens=self.max_tokens, | ||
|
|
||
| # Extract and convert thinking config from ADK to Anthropic format | ||
| thinking = NOT_GIVEN | ||
| if llm_request.config and llm_request.config.thinking_config: | ||
| budget = llm_request.config.thinking_config.thinking_budget | ||
| if budget: | ||
| if budget == -1: | ||
| # Automatic thinking budget - use recommended default of 10000 tokens | ||
| thinking = {"type": "enabled", "budget_tokens": 10000} | ||
| logger.info( | ||
| "Extended thinking enabled (automatic budget: 10000 tokens)" | ||
| ) | ||
| elif budget > 0: | ||
| # Specific budget - enforce minimum 1024 tokens | ||
| actual_budget = max(budget, 1024) | ||
| thinking = {"type": "enabled", "budget_tokens": actual_budget} | ||
| logger.info( | ||
| f"Extended thinking enabled (budget: {actual_budget} tokens)" | ||
| ) | ||
|
|
||
| # Determine if streaming should be used | ||
| use_streaming = ( | ||
| stream # From runtime context (streaming_mode == SSE) | ||
| or thinking | ||
| != NOT_GIVEN # Extended thinking requires streaming (Anthropic-specific) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Anthropic only supports extended thinking if streaming?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nope... only for larger thinking budgets. now revised. |
||
| or self.max_tokens | ||
| >= 8192 # Large max_tokens may exceed 10min timeout (Anthropic SDK requirement) | ||
| ) | ||
| yield message_to_generate_content_response(message) | ||
|
|
||
| if use_streaming: | ||
| # Use streaming mode | ||
| logger.info( | ||
| f"Using streaming mode (stream={stream}, " | ||
| f"has_thinking={thinking != NOT_GIVEN}, " | ||
| f"large_max_tokens={self.max_tokens >= 8192})" | ||
| ) | ||
|
|
||
| # Accumulators for text and thinking | ||
| accumulated_text = "" | ||
| accumulated_thinking = "" | ||
|
|
||
| async with self._anthropic_client.messages.stream( | ||
| model=llm_request.model, | ||
| system=llm_request.config.system_instruction, | ||
| messages=messages, | ||
| tools=tools, | ||
| tool_choice=tool_choice, | ||
| max_tokens=self.max_tokens, | ||
| thinking=thinking, | ||
| ) as anthropic_stream: | ||
| # Process streaming events | ||
| async for event in anthropic_stream: | ||
| # Convert Anthropic event to LlmResponse | ||
| if llm_response := streaming_event_to_llm_response(event): | ||
| # Track accumulated content | ||
| is_thought = False | ||
| if llm_response.content and llm_response.content.parts: | ||
| for part in llm_response.content.parts: | ||
| if part.text: | ||
| if hasattr(part, "thought") and part.thought: | ||
| accumulated_thinking += part.text | ||
| is_thought = True | ||
| else: | ||
| accumulated_text += part.text | ||
|
|
||
| # If we have accumulated thinking and now getting text, | ||
| # yield the accumulated thinking first | ||
| if accumulated_thinking and accumulated_text and not is_thought: | ||
| yield LlmResponse( | ||
| content=types.Content( | ||
| role="model", | ||
| parts=[ | ||
| types.Part(text=accumulated_thinking, thought=True) | ||
| ], | ||
| ), | ||
| partial=True, | ||
| ) | ||
| accumulated_thinking = "" # Reset after yielding | ||
|
|
||
| # Yield partial response (but skip individual thought deltas) | ||
| if not is_thought: | ||
| yield llm_response | ||
|
|
||
| # Get final message to extract usage metadata | ||
| final_message = await anthropic_stream.get_final_message() | ||
|
|
||
| # Build final aggregated response with complete content | ||
| parts = [] | ||
| if accumulated_thinking: | ||
| parts.append(types.Part(text=accumulated_thinking, thought=True)) | ||
| if accumulated_text: | ||
| parts.append(types.Part.from_text(text=accumulated_text)) | ||
|
|
||
| # Only yield final aggregated response if we have content | ||
| if parts: | ||
| input_tokens = final_message.usage.input_tokens | ||
| output_tokens = final_message.usage.output_tokens | ||
| yield LlmResponse( | ||
| content=types.Content(role="model", parts=parts), | ||
| usage_metadata=types.GenerateContentResponseUsageMetadata( | ||
| prompt_token_count=input_tokens, | ||
| candidates_token_count=output_tokens, | ||
| total_token_count=input_tokens + output_tokens, | ||
| ), | ||
| ) | ||
|
|
||
| else: | ||
| # Non-streaming mode (simple requests without thinking) | ||
| logger.info("Using non-streaming mode") | ||
| message = await self._anthropic_client.messages.create( | ||
| model=llm_request.model, | ||
| system=llm_request.config.system_instruction, | ||
| messages=messages, | ||
| tools=tools, | ||
| tool_choice=tool_choice, | ||
| max_tokens=self.max_tokens, | ||
| ) | ||
| yield message_to_generate_content_response(message) | ||
|
|
||
| @cached_property | ||
| def _anthropic_client(self) -> AnthropicVertex: | ||
| def _anthropic_client(self) -> AsyncAnthropicVertex: | ||
| if ( | ||
| "GOOGLE_CLOUD_PROJECT" not in os.environ | ||
| or "GOOGLE_CLOUD_LOCATION" not in os.environ | ||
|
|
@@ -305,7 +489,7 @@ def _anthropic_client(self) -> AnthropicVertex: | |
| " Anthropic on Vertex." | ||
| ) | ||
|
|
||
| return AnthropicVertex( | ||
| return AsyncAnthropicVertex( | ||
| project_id=os.environ["GOOGLE_CLOUD_PROJECT"], | ||
| region=os.environ["GOOGLE_CLOUD_LOCATION"], | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If Anthropic doesn't support automatic thinking budget we shouldn't fake it here. Throw an error instead as its important that the end user considers thinking budget for their use case as per https://docs.claude.com/en/docs/build-with-claude/extended-thinking#working-with-thinking-budgets
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done...