agent-starter-pack 0.18.2__py3-none-any.whl → 0.21.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. agent_starter_pack/agents/{langgraph_base_react → adk_a2a_base}/.template/templateconfig.yaml +5 -12
  2. agent_starter_pack/agents/adk_a2a_base/README.md +37 -0
  3. agent_starter_pack/{frontends/streamlit/frontend/style/app_markdown.py → agents/adk_a2a_base/app/__init__.py} +3 -23
  4. agent_starter_pack/agents/adk_a2a_base/app/agent.py +70 -0
  5. agent_starter_pack/agents/adk_a2a_base/notebooks/adk_a2a_app_testing.ipynb +583 -0
  6. agent_starter_pack/agents/{crewai_coding_crew/notebooks/evaluating_crewai_agent.ipynb → adk_a2a_base/notebooks/evaluating_adk_agent.ipynb} +163 -199
  7. agent_starter_pack/agents/adk_a2a_base/tests/integration/test_agent.py +58 -0
  8. agent_starter_pack/agents/adk_base/app/__init__.py +2 -2
  9. agent_starter_pack/agents/adk_base/app/agent.py +3 -0
  10. agent_starter_pack/agents/adk_base/notebooks/adk_app_testing.ipynb +13 -28
  11. agent_starter_pack/agents/adk_live/app/__init__.py +17 -0
  12. agent_starter_pack/agents/adk_live/app/agent.py +3 -0
  13. agent_starter_pack/agents/agentic_rag/app/__init__.py +2 -2
  14. agent_starter_pack/agents/agentic_rag/app/agent.py +3 -0
  15. agent_starter_pack/agents/agentic_rag/notebooks/adk_app_testing.ipynb +13 -28
  16. agent_starter_pack/agents/{crewai_coding_crew → langgraph_base}/.template/templateconfig.yaml +12 -9
  17. agent_starter_pack/agents/langgraph_base/README.md +30 -0
  18. agent_starter_pack/agents/langgraph_base/app/__init__.py +17 -0
  19. agent_starter_pack/agents/{langgraph_base_react → langgraph_base}/app/agent.py +4 -4
  20. agent_starter_pack/agents/{langgraph_base_react → langgraph_base}/tests/integration/test_agent.py +1 -1
  21. agent_starter_pack/base_template/.gitignore +4 -2
  22. agent_starter_pack/base_template/Makefile +110 -16
  23. agent_starter_pack/base_template/README.md +97 -12
  24. agent_starter_pack/base_template/deployment/terraform/dev/apis.tf +4 -6
  25. agent_starter_pack/base_template/deployment/terraform/dev/providers.tf +5 -1
  26. agent_starter_pack/base_template/deployment/terraform/dev/variables.tf +5 -3
  27. agent_starter_pack/base_template/deployment/terraform/dev/{% if cookiecutter.is_adk %}telemetry.tf{% else %}unused_telemetry.tf{% endif %} +193 -0
  28. agent_starter_pack/base_template/deployment/terraform/github.tf +16 -9
  29. agent_starter_pack/base_template/deployment/terraform/locals.tf +7 -7
  30. agent_starter_pack/base_template/deployment/terraform/providers.tf +5 -1
  31. agent_starter_pack/base_template/deployment/terraform/sql/completions.sql +138 -0
  32. agent_starter_pack/base_template/deployment/terraform/storage.tf +0 -9
  33. agent_starter_pack/base_template/deployment/terraform/variables.tf +15 -19
  34. agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}build_triggers.tf{% else %}unused_build_triggers.tf{% endif %} +20 -22
  35. agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.is_adk %}telemetry.tf{% else %}unused_telemetry.tf{% endif %} +206 -0
  36. agent_starter_pack/base_template/pyproject.toml +5 -17
  37. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/deploy-to-prod.yaml +19 -4
  38. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/staging.yaml +36 -11
  39. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/deploy-to-prod.yaml +24 -5
  40. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/staging.yaml +44 -9
  41. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/telemetry.py +96 -0
  42. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/{utils → app_utils}/typing.py +4 -6
  43. agent_starter_pack/{agents/crewai_coding_crew/app/crew/config/agents.yaml → base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}converters{% else %}unused_converters{% endif %}/__init__.py } +9 -23
  44. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}converters{% else %}unused_converters{% endif %}/part_converter.py +138 -0
  45. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/__init__.py +13 -0
  46. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/a2a_agent_executor.py +265 -0
  47. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/task_result_aggregator.py +152 -0
  48. agent_starter_pack/cli/commands/create.py +40 -4
  49. agent_starter_pack/cli/commands/enhance.py +1 -1
  50. agent_starter_pack/cli/commands/register_gemini_enterprise.py +1070 -0
  51. agent_starter_pack/cli/main.py +2 -0
  52. agent_starter_pack/cli/utils/cicd.py +20 -4
  53. agent_starter_pack/cli/utils/template.py +257 -25
  54. agent_starter_pack/deployment_targets/agent_engine/tests/integration/test_agent_engine_app.py +113 -16
  55. agent_starter_pack/deployment_targets/agent_engine/tests/load_test/README.md +2 -2
  56. agent_starter_pack/deployment_targets/agent_engine/tests/load_test/load_test.py +178 -9
  57. agent_starter_pack/deployment_targets/agent_engine/tests/{% if cookiecutter.is_a2a %}helpers.py{% else %}unused_helpers.py{% endif %} +138 -0
  58. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/agent_engine_app.py +193 -307
  59. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/app_utils/deploy.py +414 -0
  60. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/{utils → app_utils}/{% if cookiecutter.is_adk_live %}expose_app.py{% else %}unused_expose_app.py{% endif %} +13 -14
  61. agent_starter_pack/deployment_targets/cloud_run/Dockerfile +4 -1
  62. agent_starter_pack/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +85 -86
  63. agent_starter_pack/deployment_targets/cloud_run/deployment/terraform/service.tf +139 -107
  64. agent_starter_pack/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +228 -12
  65. agent_starter_pack/deployment_targets/cloud_run/tests/load_test/README.md +4 -4
  66. agent_starter_pack/deployment_targets/cloud_run/tests/load_test/load_test.py +92 -12
  67. agent_starter_pack/deployment_targets/cloud_run/{{cookiecutter.agent_directory}}/{server.py → fast_api_app.py} +194 -121
  68. agent_starter_pack/frontends/adk_live_react/frontend/package-lock.json +18 -18
  69. agent_starter_pack/frontends/adk_live_react/frontend/src/multimodal-live-types.ts +5 -3
  70. agent_starter_pack/resources/docs/adk-cheatsheet.md +198 -41
  71. agent_starter_pack/resources/locks/uv-adk_a2a_base-agent_engine.lock +4966 -0
  72. agent_starter_pack/resources/locks/uv-adk_a2a_base-cloud_run.lock +5011 -0
  73. agent_starter_pack/resources/locks/uv-adk_base-agent_engine.lock +1443 -709
  74. agent_starter_pack/resources/locks/uv-adk_base-cloud_run.lock +1058 -874
  75. agent_starter_pack/resources/locks/uv-adk_live-agent_engine.lock +1443 -709
  76. agent_starter_pack/resources/locks/uv-adk_live-cloud_run.lock +1058 -874
  77. agent_starter_pack/resources/locks/uv-agentic_rag-agent_engine.lock +1568 -749
  78. agent_starter_pack/resources/locks/uv-agentic_rag-cloud_run.lock +1123 -929
  79. agent_starter_pack/resources/locks/{uv-langgraph_base_react-agent_engine.lock → uv-langgraph_base-agent_engine.lock} +1714 -1689
  80. agent_starter_pack/resources/locks/{uv-langgraph_base_react-cloud_run.lock → uv-langgraph_base-cloud_run.lock} +1285 -2374
  81. agent_starter_pack/utils/watch_and_rebuild.py +1 -1
  82. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/METADATA +3 -6
  83. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/RECORD +89 -93
  84. agent_starter_pack-0.21.0.dist-info/entry_points.txt +2 -0
  85. llm.txt +4 -5
  86. agent_starter_pack/agents/crewai_coding_crew/README.md +0 -34
  87. agent_starter_pack/agents/crewai_coding_crew/app/agent.py +0 -47
  88. agent_starter_pack/agents/crewai_coding_crew/app/crew/config/tasks.yaml +0 -37
  89. agent_starter_pack/agents/crewai_coding_crew/app/crew/crew.py +0 -71
  90. agent_starter_pack/agents/crewai_coding_crew/tests/integration/test_agent.py +0 -47
  91. agent_starter_pack/agents/langgraph_base_react/README.md +0 -9
  92. agent_starter_pack/agents/langgraph_base_react/notebooks/evaluating_langgraph_agent.ipynb +0 -1574
  93. agent_starter_pack/base_template/deployment/terraform/dev/log_sinks.tf +0 -69
  94. agent_starter_pack/base_template/deployment/terraform/log_sinks.tf +0 -79
  95. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/utils/tracing.py +0 -155
  96. agent_starter_pack/cli/utils/register_gemini_enterprise.py +0 -406
  97. agent_starter_pack/deployment_targets/agent_engine/deployment/terraform/{% if not cookiecutter.is_adk_live %}service.tf{% else %}unused_service.tf{% endif %} +0 -82
  98. agent_starter_pack/deployment_targets/agent_engine/notebooks/intro_agent_engine.ipynb +0 -1025
  99. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/utils/deployment.py +0 -99
  100. agent_starter_pack/frontends/streamlit/frontend/side_bar.py +0 -214
  101. agent_starter_pack/frontends/streamlit/frontend/streamlit_app.py +0 -265
  102. agent_starter_pack/frontends/streamlit/frontend/utils/chat_utils.py +0 -67
  103. agent_starter_pack/frontends/streamlit/frontend/utils/local_chat_history.py +0 -127
  104. agent_starter_pack/frontends/streamlit/frontend/utils/message_editing.py +0 -59
  105. agent_starter_pack/frontends/streamlit/frontend/utils/multimodal_utils.py +0 -217
  106. agent_starter_pack/frontends/streamlit/frontend/utils/stream_handler.py +0 -310
  107. agent_starter_pack/frontends/streamlit/frontend/utils/title_summary.py +0 -94
  108. agent_starter_pack/resources/locks/uv-crewai_coding_crew-agent_engine.lock +0 -6650
  109. agent_starter_pack/resources/locks/uv-crewai_coding_crew-cloud_run.lock +0 -7825
  110. agent_starter_pack-0.18.2.dist-info/entry_points.txt +0 -3
  111. /agent_starter_pack/agents/{crewai_coding_crew → langgraph_base}/notebooks/evaluating_langgraph_agent.ipynb +0 -0
  112. /agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/{utils → app_utils}/gcs.py +0 -0
  113. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/WHEEL +0 -0
  114. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,310 +0,0 @@
1
- # Copyright 2025 Google LLC
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- # mypy: disable-error-code="unreachable"
16
- import importlib
17
- import json
18
- import uuid
19
- from collections.abc import Generator
20
- from typing import Any
21
- from urllib.parse import urljoin
22
-
23
- import google.auth
24
- import google.auth.transport.requests
25
- import google.oauth2.id_token
26
- import requests
27
- import streamlit as st
28
- import vertexai
29
- from google.auth.exceptions import DefaultCredentialsError
30
- from langchain_core.messages import AIMessage, ToolMessage
31
- from vertexai import agent_engines
32
-
33
- from frontend.utils.multimodal_utils import format_content
34
-
35
- st.cache_resource.clear()
36
-
37
-
38
- @st.cache_resource
39
- def get_remote_agent(remote_agent_engine_id: str) -> Any:
40
- """Get cached remote agent instance."""
41
- # Extract location and engine ID from the full resource ID.
42
- parts = remote_agent_engine_id.split("/")
43
- project_id = parts[1]
44
- location = parts[3]
45
- vertexai.init(project=project_id, location=location)
46
- return agent_engines.AgentEngine(remote_agent_engine_id)
47
-
48
-
49
- @st.cache_resource
50
- def get_remote_url_config(url: str, authenticate_request: bool) -> dict[str, Any]:
51
- """Get cached remote URL agent configuration."""
52
- stream_url = urljoin(url, "stream_messages")
53
- creds, _ = google.auth.default()
54
- id_token = None
55
- if authenticate_request:
56
- auth_req = google.auth.transport.requests.Request()
57
- try:
58
- id_token = google.oauth2.id_token.fetch_id_token(auth_req, stream_url)
59
- except DefaultCredentialsError:
60
- creds.refresh(auth_req)
61
- id_token = creds.id_token
62
- return {
63
- "url": stream_url,
64
- "authenticate_request": authenticate_request,
65
- "creds": creds,
66
- "id_token": id_token,
67
- }
68
-
69
-
70
- @st.cache_resource()
71
- def get_local_agent(agent_callable_path: str) -> Any:
72
- """Get cached local agent instance."""
73
- module_path, class_name = agent_callable_path.rsplit(".", 1)
74
- module = importlib.import_module(module_path)
75
- agent = getattr(module, class_name)()
76
- agent.set_up()
77
- return agent
78
-
79
-
80
- class Client:
81
- """A client for streaming events from a server."""
82
-
83
- def __init__(
84
- self,
85
- agent_callable_path: str | None = None,
86
- remote_agent_engine_id: str | None = None,
87
- url: str | None = None,
88
- authenticate_request: bool = False,
89
- ) -> None:
90
- """Initialize the Client with appropriate configuration.
91
-
92
- Args:
93
- agent_callable_path: Path to local agent class
94
- remote_agent_engine_id: ID of remote Agent engine
95
- url: URL for remote service
96
- authenticate_request: Whether to authenticate requests to remote URL
97
- """
98
- if url:
99
- remote_config = get_remote_url_config(url, authenticate_request)
100
- self.url = remote_config["url"]
101
- self.authenticate_request = remote_config["authenticate_request"]
102
- self.creds = remote_config["creds"]
103
- self.id_token = remote_config["id_token"]
104
- self.agent = None
105
- elif remote_agent_engine_id:
106
- self.agent = get_remote_agent(remote_agent_engine_id)
107
- self.url = None
108
- else:
109
- self.url = None
110
- if agent_callable_path is None:
111
- raise ValueError("agent_callable_path cannot be None")
112
- self.agent = get_local_agent(agent_callable_path)
113
-
114
- def log_feedback(self, feedback_dict: dict[str, Any], run_id: str) -> None:
115
- """Log user feedback for a specific run."""
116
- score = feedback_dict["score"]
117
- if score == "😞":
118
- score = 0.0
119
- elif score == "🙁":
120
- score = 0.25
121
- elif score == "😐":
122
- score = 0.5
123
- elif score == "🙂":
124
- score = 0.75
125
- elif score == "😀":
126
- score = 1.0
127
- feedback_dict["score"] = score
128
- feedback_dict["run_id"] = run_id
129
- feedback_dict["log_type"] = "feedback"
130
- feedback_dict.pop("type")
131
- url = urljoin(self.url, "feedback")
132
- headers = {
133
- "Content-Type": "application/json",
134
- }
135
- if self.url:
136
- url = urljoin(self.url, "feedback")
137
- headers = {
138
- "Content-Type": "application/json",
139
- }
140
- if self.authenticate_request:
141
- headers["Authorization"] = f"Bearer {self.id_token}"
142
- requests.post(
143
- url, data=json.dumps(feedback_dict), headers=headers, timeout=10
144
- )
145
- elif self.agent is not None:
146
- self.agent.register_feedback(feedback=feedback_dict)
147
- else:
148
- raise ValueError("No agent or URL configured for feedback logging")
149
-
150
- def stream_messages(
151
- self, data: dict[str, Any]
152
- ) -> Generator[dict[str, Any], None, None]:
153
- """Stream events from the server, yielding parsed event data."""
154
- if self.url:
155
- headers = {
156
- "Content-Type": "application/json",
157
- "Accept": "text/event-stream",
158
- }
159
- if self.authenticate_request:
160
- headers["Authorization"] = f"Bearer {self.id_token}"
161
- with requests.post(
162
- self.url, json=data, headers=headers, stream=True, timeout=60
163
- ) as response:
164
- for line in response.iter_lines():
165
- if line:
166
- try:
167
- event = json.loads(line.decode("utf-8"))
168
- yield event
169
- except json.JSONDecodeError:
170
- print(f"Failed to parse event: {line.decode('utf-8')}")
171
- elif self.agent is not None:
172
- yield from self.agent.stream_query(**data)
173
-
174
-
175
- class StreamHandler:
176
- """Handles streaming updates to a Streamlit interface."""
177
-
178
- def __init__(self, st: Any, initial_text: str = "") -> None:
179
- """Initialize the StreamHandler with Streamlit context and initial text."""
180
- self.st = st
181
- self.tool_expander = st.expander("Tool Calls:", expanded=False)
182
- self.container = st.empty()
183
- self.text = initial_text
184
- self.tools_logs = initial_text
185
-
186
- def new_token(self, token: str) -> None:
187
- """Add a new token to the main text display."""
188
- self.text += token
189
- self.container.markdown(format_content(self.text), unsafe_allow_html=True)
190
-
191
- def new_status(self, status_update: str) -> None:
192
- """Add a new status update to the tool calls expander."""
193
- self.tools_logs += status_update
194
- self.tool_expander.markdown(status_update)
195
-
196
-
197
- class EventProcessor:
198
- """Processes events from the stream and updates the UI accordingly."""
199
-
200
- def __init__(self, st: Any, client: Client, stream_handler: StreamHandler) -> None:
201
- """Initialize the EventProcessor with Streamlit context, client, and stream handler."""
202
- self.st = st
203
- self.client = client
204
- self.stream_handler = stream_handler
205
- self.final_content = ""
206
- self.tool_calls: list[dict[str, Any]] = []
207
- self.current_run_id: str | None = None
208
- self.additional_kwargs: dict[str, Any] = {}
209
-
210
- def process_events(self) -> None:
211
- """Process events from the stream, handling each event type appropriately."""
212
- messages = self.st.session_state.user_chats[
213
- self.st.session_state["session_id"]
214
- ]["messages"]
215
- self.current_run_id = str(uuid.uuid4())
216
- # Set run_id in session state at start of processing
217
- self.st.session_state["run_id"] = self.current_run_id
218
- stream = self.client.stream_messages(
219
- data={
220
- "input": {"messages": messages},
221
- "config": {
222
- "run_id": self.current_run_id,
223
- "metadata": {
224
- "user_id": self.st.session_state["user_id"],
225
- "session_id": self.st.session_state["session_id"],
226
- },
227
- },
228
- }
229
- )
230
- # Each event is a tuple message, metadata. https://langchain-ai.github.io/langgraph/how-tos/streaming/#messages
231
- for message, _ in stream:
232
- if isinstance(message, dict):
233
- if message.get("type") == "constructor":
234
- message = message["kwargs"]
235
-
236
- # Handle tool calls
237
- if message.get("tool_calls"):
238
- tool_calls = message["tool_calls"]
239
- ai_message = AIMessage(content="", tool_calls=tool_calls)
240
- self.tool_calls.append(ai_message.model_dump())
241
- for tool_call in tool_calls:
242
- msg = f"\n\nCalling tool: `{tool_call['name']}` with args: `{tool_call['args']}`"
243
- self.stream_handler.new_status(msg)
244
-
245
- # Handle tool responses
246
- elif message.get("tool_call_id"):
247
- content = message["content"]
248
- tool_call_id = message["tool_call_id"]
249
- tool_message = ToolMessage(
250
- content=content, type="tool", tool_call_id=tool_call_id
251
- ).model_dump()
252
- self.tool_calls.append(tool_message)
253
- msg = f"\n\nTool response: `{content}`"
254
- self.stream_handler.new_status(msg)
255
-
256
- # Handle incremental AI response chunks
257
- # These are partial content pieces that need to be accumulated
258
- elif (
259
- message.get("content")
260
- and message.get("type") == "AIMessageChunk"
261
- ):
262
- self.final_content += message.get("content")
263
- self.stream_handler.new_token(message.get("content"))
264
-
265
- # Handle complete AI responses
266
- # This is used when receiving a full message rather than chunks
267
- elif message.get("content") and message.get("type") == "ai":
268
- self.final_content = message.get("content")
269
-
270
- # Handle end of stream
271
- if self.final_content:
272
- final_message = AIMessage(
273
- content=self.final_content,
274
- id=self.current_run_id,
275
- additional_kwargs=self.additional_kwargs,
276
- ).model_dump()
277
- session = self.st.session_state["session_id"]
278
- self.st.session_state.user_chats[session]["messages"] = (
279
- self.st.session_state.user_chats[session]["messages"] + self.tool_calls
280
- )
281
- self.st.session_state.user_chats[session]["messages"].append(final_message)
282
- self.st.session_state.run_id = self.current_run_id
283
-
284
-
285
- def get_chain_response(st: Any, client: Client, stream_handler: StreamHandler) -> None:
286
- """Process the chain response update the Streamlit UI.
287
-
288
- This function initiates the event processing for a chain of operations,
289
- involving an AI model's response generation and potential tool calls.
290
- It creates an EventProcessor instance and starts the event processing loop.
291
-
292
- Args:
293
- st (Any): The Streamlit app instance, used for accessing session state
294
- and updating the UI.
295
- client (Client): An instance of the Client class used to stream events
296
- from the server.
297
- stream_handler (StreamHandler): An instance of the StreamHandler class
298
- used to update the Streamlit UI with
299
- streaming content.
300
-
301
- Returns:
302
- None
303
-
304
- Side effects:
305
- - Updates the Streamlit UI with streaming tokens and tool call information.
306
- - Modifies the session state to include the final AI message and run ID.
307
- - Handles various events like chain starts/ends, tool calls, and model outputs.
308
- """
309
- processor = EventProcessor(st, client, stream_handler)
310
- processor.process_events()
@@ -1,94 +0,0 @@
1
- # Copyright 2025 Google LLC
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- # mypy: disable-error-code="assignment"
16
- import os
17
- from typing import Any
18
-
19
- import google.auth
20
- from langchain_core.messages import AIMessage
21
- from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
22
- from langchain_google_vertexai import ChatVertexAI
23
-
24
- title_template = ChatPromptTemplate.from_messages(
25
- [
26
- (
27
- "system",
28
- """Given a list of messages between a human and AI, come up with a short and relevant title for the conversation. Use up to 10 words. The title needs to be concise.
29
- Examples:
30
- **Input:**
31
- ```
32
- Human: hi, what is the best italian dish?
33
- AI: That's a tough one! Italy has so many amazing dishes, it's hard to pick just one "best." To help me give you a great suggestion, tell me a little more about what you're looking for.
34
- ```
35
- **Output:** Best italian dish
36
-
37
- **Input:**
38
-
39
- ```
40
- Human: How to fix a broken laptop screen?
41
- AI: Fixing a broken laptop screen can be tricky and often requires professional help. However, there are a few things you can try at home before resorting to a repair shop.
42
- ```
43
-
44
- **Output:** Fixing a broken laptop screen
45
-
46
- **Input:**
47
-
48
- ```
49
- Human: Can you write me a poem about the beach?
50
- AI: As the sun dips down below the horizon
51
- And the waves gently kiss the shore,
52
- I sit here and watch the ocean
53
- And feel its power evermore.
54
- ```
55
-
56
- **Output:** Poem about the beach
57
-
58
- **Input:**
59
-
60
- ```
61
- Human: What's the best way to learn to code?
62
- AI: There are many ways to learn to code, and the best method for you will depend on your learning style and goals.
63
- ```
64
-
65
- **Output:** How to learn to code
66
-
67
- If there's not enough context in the conversation to create a meaningful title, create a generic title like "New Conversation", or "A simple greeting".
68
-
69
- """,
70
- ),
71
- MessagesPlaceholder(variable_name="messages"),
72
- ]
73
- )
74
- try:
75
- # Initialize Vertex AI with default project credentials
76
- _, project_id = google.auth.default()
77
-
78
- llm = ChatVertexAI(
79
- model_name="gemini-2.0-flash-001",
80
- temperature=0,
81
- project=project_id,
82
- location=os.getenv("LOCATION", "us-central1"),
83
- )
84
- chain_title = title_template | llm
85
-
86
- except Exception:
87
- # Fallback to a simple title generator when Vertex AI is unavailable
88
- print("WARNING: Failed to initialize Vertex AI. Using dummy LLM instead.")
89
-
90
- class DummyChain:
91
- def invoke(*args: Any, **kwargs: Any) -> AIMessage:
92
- return AIMessage(content="conversation")
93
-
94
- chain_title = DummyChain()