dasein-core 0.2.4__tar.gz → 0.2.6__tar.gz
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.
- {dasein_core-0.2.4/src/dasein_core.egg-info → dasein_core-0.2.6}/PKG-INFO +1 -1
- {dasein_core-0.2.4 → dasein_core-0.2.6}/examples/dasein_examples.ipynb +502 -502
- {dasein_core-0.2.4 → dasein_core-0.2.6}/pyproject.toml +1 -1
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/api.py +81 -3
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/services/post_run_client.py +2 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/services/service_adapter.py +3 -2
- {dasein_core-0.2.4 → dasein_core-0.2.6/src/dasein_core.egg-info}/PKG-INFO +1 -1
- {dasein_core-0.2.4 → dasein_core-0.2.6}/LICENSE +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/MANIFEST.in +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/README.md +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/setup.cfg +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/setup.py +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/__init__.py +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/advice_format.py +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/capture.py +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/config.py +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/events.py +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/extractors.py +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/injection_strategies.py +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/injector.py +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/services/__init__.py +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/services/pre_run_client.py +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/services/service_config.py +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/trace_buffer.py +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein/types.py +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein_core.egg-info/SOURCES.txt +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein_core.egg-info/dependency_links.txt +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein_core.egg-info/requires.txt +0 -0
- {dasein_core-0.2.4 → dasein_core-0.2.6}/src/dasein_core.egg-info/top_level.txt +0 -0
@@ -1,502 +1,502 @@
|
|
1
|
-
{
|
2
|
-
"cells": [
|
3
|
-
{
|
4
|
-
"cell_type": "markdown",
|
5
|
-
"metadata": {},
|
6
|
-
"source": [
|
7
|
-
"# 🧠 Dasein Examples: Universal Memory for Agentic AI\n",
|
8
|
-
"\n",
|
9
|
-
"[](https://colab.research.google.com/github/nickswami/dasein-core/blob/main/examples/dasein_examples.ipynb)\n",
|
10
|
-
"\n",
|
11
|
-
"This notebook demonstrates **Dasein** - a universal memory system that learns from your agent's execution history and automatically improves performance, reduces costs, and increases reliability.\n",
|
12
|
-
"\n",
|
13
|
-
"## What You'll Learn\n",
|
14
|
-
"\n",
|
15
|
-
"1. **SQL Agent** - Learn query patterns for database interactions\n",
|
16
|
-
"2. **Browser Agent** - Learn web scraping and navigation strategies\n",
|
17
|
-
"3. **Deep Research Agent** - Optimize multi-agent research workflows\n",
|
18
|
-
"\n",
|
19
|
-
"## Key Features\n",
|
20
|
-
"\n",
|
21
|
-
"- ✨ **Zero-friction integration** - Wrap any agent in one line\n",
|
22
|
-
"- 🧠 **Automatic learning** - Agents learn from successes and failures\n",
|
23
|
-
"- 📊 **Performance tracking** - See token usage, timing, and improvement metrics\n",
|
24
|
-
"- 🔄 **Retry logic** - Intelligent retry with learned optimizations\n",
|
25
|
-
"- ☁️ **Cloud-powered** - Distributed rule synthesis and storage\n"
|
26
|
-
]
|
27
|
-
},
|
28
|
-
{
|
29
|
-
"cell_type": "markdown",
|
30
|
-
"metadata": {},
|
31
|
-
"source": [
|
32
|
-
"## Installation\n"
|
33
|
-
]
|
34
|
-
},
|
35
|
-
{
|
36
|
-
"cell_type": "code",
|
37
|
-
"execution_count": null,
|
38
|
-
"metadata": {},
|
39
|
-
"outputs": [],
|
40
|
-
"source": [
|
41
|
-
"# Install Dasein and dependencies\n",
|
42
|
-
"!pip install -q dasein-core\n",
|
43
|
-
"\n",
|
44
|
-
"# For browser agent example (Use Case 2)\n",
|
45
|
-
"!pip install -q playwright\n",
|
46
|
-
"!playwright install chromium\n",
|
47
|
-
"\n",
|
48
|
-
"# For deep research agent (Use Case 3)\n",
|
49
|
-
"!pip install -q git+https://github.com/langchain-ai/open_deep_research.git\n"
|
50
|
-
]
|
51
|
-
},
|
52
|
-
{
|
53
|
-
"cell_type": "markdown",
|
54
|
-
"metadata": {},
|
55
|
-
"source": [
|
56
|
-
"## Setup API Keys\n",
|
57
|
-
"\n",
|
58
|
-
"Replace the placeholders below with your actual API keys:\n",
|
59
|
-
"\n",
|
60
|
-
"- **GOOGLE_API_KEY**: Get from [Google AI Studio](https://makersuite.google.com/app/apikey)\n",
|
61
|
-
"- **TAVILY_API_KEY**: Get from [Tavily](https://tavily.com) (free tier available, 1000 searches/month)\n"
|
62
|
-
]
|
63
|
-
},
|
64
|
-
{
|
65
|
-
"cell_type": "code",
|
66
|
-
"execution_count": null,
|
67
|
-
"metadata": {},
|
68
|
-
"outputs": [],
|
69
|
-
"source": [
|
70
|
-
"import os\n",
|
71
|
-
"\n",
|
72
|
-
"# ⚠️ REPLACE THESE WITH YOUR ACTUAL API KEYS\n",
|
73
|
-
"os.environ[\"GOOGLE_API_KEY\"] = \"YOUR_GOOGLE_API_KEY_HERE\"\n",
|
74
|
-
"os.environ[\"TAVILY_API_KEY\"] = \"YOUR_TAVILY_API_KEY_HERE\" # Only needed for Use Case 3\n",
|
75
|
-
"\n",
|
76
|
-
"# Suppress warnings\n",
|
77
|
-
"os.environ[\"GOOGLE_CLOUD_DISABLE_DIRECT_PATH\"] = \"true\"\n",
|
78
|
-
"\n",
|
79
|
-
"print(\"✅ API keys configured\")\n",
|
80
|
-
"print(\"\\n⚠️ Note: You may see dependency warnings in Colab - these are safe to ignore.\")\n",
|
81
|
-
"print(\"⚠️ Note: Brief timeout warnings on first run are normal (cold start) - services will activate automatically.\")\n"
|
82
|
-
]
|
83
|
-
},
|
84
|
-
{
|
85
|
-
"cell_type": "markdown",
|
86
|
-
"metadata": {},
|
87
|
-
"source": [
|
88
|
-
"---\n",
|
89
|
-
"\n",
|
90
|
-
"# Use Case 1: SQL Agent with Learning\n",
|
91
|
-
"\n",
|
92
|
-
"This example demonstrates how Dasein learns SQL query patterns and improves database agent performance.\n",
|
93
|
-
"\n",
|
94
|
-
"**What Happens:**\n",
|
95
|
-
"1. **Baseline Run**: Agent queries the Chinook database without optimization\n",
|
96
|
-
"2. **Learning**: Dasein captures the execution trace and sends it to cloud services for rule synthesis\n",
|
97
|
-
"3. **Enhanced Run**: Agent runs again with learned rules injected, showing improved performance\n",
|
98
|
-
"\n",
|
99
|
-
"**Expected Improvements:**\n",
|
100
|
-
"- 30-50% reduction in tokens used\n",
|
101
|
-
"- Fewer SQL query iterations\n",
|
102
|
-
"- Better query formulation\n"
|
103
|
-
]
|
104
|
-
},
|
105
|
-
{
|
106
|
-
"cell_type": "code",
|
107
|
-
"execution_count": null,
|
108
|
-
"metadata": {},
|
109
|
-
"outputs": [],
|
110
|
-
"source": [
|
111
|
-
"import urllib.request\n",
|
112
|
-
"from pathlib import Path\n",
|
113
|
-
"\n",
|
114
|
-
"# Download Chinook sample database\n",
|
115
|
-
"db_path = Path(\"chinook.db\")\n",
|
116
|
-
"if not db_path.exists():\n",
|
117
|
-
" print(\"Downloading Chinook database...\")\n",
|
118
|
-
" urllib.request.urlretrieve(\n",
|
119
|
-
" \"https://raw.githubusercontent.com/lerocha/chinook-database/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite\",\n",
|
120
|
-
" str(db_path)\n",
|
121
|
-
" )\n",
|
122
|
-
" print(\"✅ Database downloaded\")\n",
|
123
|
-
"else:\n",
|
124
|
-
" print(\"✅ Database already exists\")\n"
|
125
|
-
]
|
126
|
-
},
|
127
|
-
{
|
128
|
-
"cell_type": "code",
|
129
|
-
"execution_count": null,
|
130
|
-
"metadata": {},
|
131
|
-
"outputs": [],
|
132
|
-
"source": [
|
133
|
-
"from langchain_community.utilities import SQLDatabase\n",
|
134
|
-
"from langchain_community.agent_toolkits import SQLDatabaseToolkit\n",
|
135
|
-
"from langchain_community.agent_toolkits.sql.base import create_sql_agent\n",
|
136
|
-
"from langchain_google_genai import ChatGoogleGenerativeAI\n",
|
137
|
-
"from dasein import cognate\n",
|
138
|
-
"\n",
|
139
|
-
"# Set up SQL agent\n",
|
140
|
-
"print(\"Setting up SQL agent...\")\n",
|
141
|
-
"db = SQLDatabase.from_uri(f\"sqlite:///{db_path}\")\n",
|
142
|
-
"llm = ChatGoogleGenerativeAI(model=\"gemini-2.5-flash\", temperature=0)\n",
|
143
|
-
"toolkit = SQLDatabaseToolkit(db=db, llm=llm)\n",
|
144
|
-
"agent = create_sql_agent(llm=llm, toolkit=toolkit, verbose=True, handle_parsing_errors=True)\n",
|
145
|
-
"\n",
|
146
|
-
"print(\"✅ SQL agent created\")\n"
|
147
|
-
]
|
148
|
-
},
|
149
|
-
{
|
150
|
-
"cell_type": "code",
|
151
|
-
"execution_count": null,
|
152
|
-
"metadata": {},
|
153
|
-
"outputs": [],
|
154
|
-
"source": [
|
155
|
-
"# Wrap with Dasein for automatic learning and improvement\n",
|
156
|
-
"agent = cognate(\n",
|
157
|
-
" agent,\n",
|
158
|
-
" retry=2, # Run twice: baseline + enhanced\n",
|
159
|
-
" performance_tracking=True, # Show improvement metrics\n",
|
160
|
-
" verbose=False # Set to True to see rule injection details\n",
|
161
|
-
")\n",
|
162
|
-
"\n",
|
163
|
-
"# Run the query - Dasein handles everything automatically!\n",
|
164
|
-
"query = \"Which media format accounts for the highest number of individual line-item sales?\"\n",
|
165
|
-
"\n",
|
166
|
-
"print(f\"\\nQuery: {query}\\n\")\n",
|
167
|
-
"print(\"=\" * 70)\n",
|
168
|
-
"print(\"PHASE 1: Baseline run...\")\n",
|
169
|
-
"print(\"PHASE 2: Enhanced run with learned rules...\")\n",
|
170
|
-
"print(\"=\" * 70)\n",
|
171
|
-
"\n",
|
172
|
-
"result = agent.invoke({\"input\": query})\n",
|
173
|
-
"\n",
|
174
|
-
"print(f\"\\n✅ Final Answer: {result.get('output', '')}\")\n",
|
175
|
-
"print(\"\\n📊 Check the performance metrics above to see improvement!\")\n"
|
176
|
-
]
|
177
|
-
},
|
178
|
-
{
|
179
|
-
"cell_type": "markdown",
|
180
|
-
"metadata": {},
|
181
|
-
"source": [
|
182
|
-
"---\n",
|
183
|
-
"\n",
|
184
|
-
"# Use Case 2: Browser Agent with Learning\n",
|
185
|
-
"\n",
|
186
|
-
"This example demonstrates how Dasein learns web scraping and navigation patterns.\n",
|
187
|
-
"\n",
|
188
|
-
"**What Happens:**\n",
|
189
|
-
"1. **Baseline Run**: Browser agent navigates to a website without optimization\n",
|
190
|
-
"2. **Learning**: Dasein learns which tools to use, navigation patterns, and element selection strategies\n",
|
191
|
-
"3. **Enhanced Run**: Agent runs again with learned rules, showing faster and more efficient browsing\n",
|
192
|
-
"\n",
|
193
|
-
"**Expected Improvements:**\n",
|
194
|
-
"- Fewer navigation steps\n",
|
195
|
-
"- Better tool selection\n",
|
196
|
-
"- More efficient element targeting\n",
|
197
|
-
"- Reduced token usage\n"
|
198
|
-
]
|
199
|
-
},
|
200
|
-
{
|
201
|
-
"cell_type": "code",
|
202
|
-
"execution_count": null,
|
203
|
-
"metadata": {},
|
204
|
-
"outputs": [],
|
205
|
-
"source": [
|
206
|
-
"from langchain_community.agent_toolkits import PlayWrightBrowserToolkit\n",
|
207
|
-
"from langchain_google_genai import ChatGoogleGenerativeAI\n",
|
208
|
-
"from langgraph.prebuilt import create_react_agent\n",
|
209
|
-
"from dasein import cognate\n",
|
210
|
-
"import asyncio\n",
|
211
|
-
"from playwright.async_api import async_playwright\n",
|
212
|
-
"\n",
|
213
|
-
"async def create_browser_agent():\n",
|
214
|
-
" \"\"\"Create a Playwright browser agent.\"\"\"\n",
|
215
|
-
" print(\"Setting up Playwright browser agent...\")\n",
|
216
|
-
" \n",
|
217
|
-
" # Create browser\n",
|
218
|
-
" playwright = await async_playwright().start()\n",
|
219
|
-
" async_browser = await playwright.chromium.launch(headless=True)\n",
|
220
|
-
" \n",
|
221
|
-
" # Create toolkit and tools\n",
|
222
|
-
" toolkit = PlayWrightBrowserToolkit.from_browser(async_browser=async_browser)\n",
|
223
|
-
" tools = toolkit.get_tools()\n",
|
224
|
-
" \n",
|
225
|
-
" print(f\"Available browser tools: {[tool.name for tool in tools]}\")\n",
|
226
|
-
" \n",
|
227
|
-
" # Create LLM\n",
|
228
|
-
" llm = ChatGoogleGenerativeAI(\n",
|
229
|
-
" model=\"gemini-2.5-flash\",\n",
|
230
|
-
" temperature=0,\n",
|
231
|
-
" request_timeout=180,\n",
|
232
|
-
" max_retries=2\n",
|
233
|
-
" )\n",
|
234
|
-
" \n",
|
235
|
-
" # Create agent\n",
|
236
|
-
" agent_chain = create_react_agent(model=llm, tools=tools)\n",
|
237
|
-
" agent_chain = agent_chain.with_config({\"recursion_limit\": 75})\n",
|
238
|
-
" agent_chain.llm = llm # Add LLM reference for Dasein\n",
|
239
|
-
" \n",
|
240
|
-
" print(\"✅ Browser agent created\")\n",
|
241
|
-
" return agent_chain\n",
|
242
|
-
"\n",
|
243
|
-
"# Create the agent\n",
|
244
|
-
"browser_agent = await create_browser_agent()\n"
|
245
|
-
]
|
246
|
-
},
|
247
|
-
{
|
248
|
-
"cell_type": "code",
|
249
|
-
"execution_count": null,
|
250
|
-
"metadata": {},
|
251
|
-
"outputs": [],
|
252
|
-
"source": [
|
253
|
-
"# Wrap with Dasein\n",
|
254
|
-
"browser_agent = cognate(\n",
|
255
|
-
" browser_agent,\n",
|
256
|
-
" retry=2,\n",
|
257
|
-
" performance_tracking=True,\n",
|
258
|
-
" verbose=False # Set to True to see rule injection details\n",
|
259
|
-
")\n",
|
260
|
-
"\n",
|
261
|
-
"# Test query\n",
|
262
|
-
"query = \"Go to https://python.langchain.com
|
263
|
-
"\n",
|
264
|
-
"print(f\"\\nQuery: {query}\\n\")\n",
|
265
|
-
"print(\"=\" * 70)\n",
|
266
|
-
"print(\"PHASE 1: Baseline run...\")\n",
|
267
|
-
"print(\"PHASE 2: Enhanced run with learned rules...\")\n",
|
268
|
-
"print(\"=\" * 70)\n",
|
269
|
-
"\n",
|
270
|
-
"result = await browser_agent.ainvoke({\"messages\": [(\"user\", query)]})\n",
|
271
|
-
"\n",
|
272
|
-
"print(f\"\\n✅ Final Answer: {result}\")\n",
|
273
|
-
"print(\"\\n📊 Check the performance metrics above to see improvement!\")\n"
|
274
|
-
]
|
275
|
-
},
|
276
|
-
{
|
277
|
-
"cell_type": "markdown",
|
278
|
-
"metadata": {},
|
279
|
-
"source": [
|
280
|
-
"---\n",
|
281
|
-
"\n",
|
282
|
-
"# Use Case 3: Deep Research Agent with Learning\n",
|
283
|
-
"\n",
|
284
|
-
"This example demonstrates Dasein with LangChain's **Open Deep Research Agent** - a complex multi-agent system that orchestrates research tasks.\n",
|
285
|
-
"\n",
|
286
|
-
"**What Happens:**\n",
|
287
|
-
"1. **Baseline Run**: Multi-agent research system runs without optimization\n",
|
288
|
-
" - Supervisor delegates to sub-agents\n",
|
289
|
-
" - Parallel research with Tavily search\n",
|
290
|
-
" - Context accumulation and synthesis\n",
|
291
|
-
" - Typically uses 15x more tokens than normal chat!\n",
|
292
|
-
"\n",
|
293
|
-
"2. **Learning**: Dasein learns:\n",
|
294
|
-
" - Better search query formulation\n",
|
295
|
-
" - Context filtering to reduce token bloat\n",
|
296
|
-
" - Improved delegation strategies\n",
|
297
|
-
" - Efficient tool usage patterns\n",
|
298
|
-
"\n",
|
299
|
-
"3. **Enhanced Run**: Agent runs with learned rules\n",
|
300
|
-
"\n",
|
301
|
-
"**Expected Improvements:**\n",
|
302
|
-
"- 20-40% reduction in tokens used\n",
|
303
|
-
"- Fewer redundant searches\n",
|
304
|
-
"- Better query formulation\n",
|
305
|
-
"- Faster convergence to quality results\n",
|
306
|
-
"\n",
|
307
|
-
"**Requirements:**\n",
|
308
|
-
"- TAVILY_API_KEY (free tier: 1000 searches/month)\n"
|
309
|
-
]
|
310
|
-
},
|
311
|
-
{
|
312
|
-
"cell_type": "code",
|
313
|
-
"execution_count": null,
|
314
|
-
"metadata": {},
|
315
|
-
"outputs": [],
|
316
|
-
"source": [
|
317
|
-
"# Critical fix: Force LangChain to use Google GenAI instead of Vertex AI\n",
|
318
|
-
"from langchain.chat_models import base as chat_models_base\n",
|
319
|
-
"from langchain_google_genai import ChatGoogleGenerativeAI\n",
|
320
|
-
"\n",
|
321
|
-
"original_init_helper = chat_models_base._init_chat_model_helper\n",
|
322
|
-
"_model_cache = {}\n",
|
323
|
-
"_patch_logged = set()\n",
|
324
|
-
"\n",
|
325
|
-
"def patched_init_helper(*args, **kwargs):\n",
|
326
|
-
" \"\"\"Force gemini models to use ChatGoogleGenerativeAI.\"\"\"\n",
|
327
|
-
" model = kwargs.get('model', '')\n",
|
328
|
-
" if not model and args:\n",
|
329
|
-
" model = args[0] if len(args) > 0 and isinstance(args[0], str) else ''\n",
|
330
|
-
" \n",
|
331
|
-
" if model and 'gemini' in model.lower():\n",
|
332
|
-
" if model not in _patch_logged:\n",
|
333
|
-
" print(f\"🔧 Using ChatGoogleGenerativeAI for {model}\")\n",
|
334
|
-
" _patch_logged.add(model)\n",
|
335
|
-
" \n",
|
336
|
-
" if model not in _model_cache:\n",
|
337
|
-
" _model_cache[model] = ChatGoogleGenerativeAI(model=model)\n",
|
338
|
-
" return _model_cache[model]\n",
|
339
|
-
" return original_init_helper(*args, **kwargs)\n",
|
340
|
-
"\n",
|
341
|
-
"chat_models_base._init_chat_model_helper = patched_init_helper\n",
|
342
|
-
"print(\"✅ Patched LangChain to use Google GenAI\")\n"
|
343
|
-
]
|
344
|
-
},
|
345
|
-
{
|
346
|
-
"cell_type": "code",
|
347
|
-
"execution_count": null,
|
348
|
-
"metadata": {},
|
349
|
-
"outputs": [],
|
350
|
-
"source": [
|
351
|
-
"from open_deep_research.deep_researcher import deep_researcher_builder\n",
|
352
|
-
"from open_deep_research.configuration import Configuration\n",
|
353
|
-
"from dasein import cognate\n",
|
354
|
-
"import asyncio\n",
|
355
|
-
"\n",
|
356
|
-
"async def create_research_agent():\n",
|
357
|
-
" \"\"\"Create Open Deep Research agent.\"\"\"\n",
|
358
|
-
" print(\"Setting up Open Deep Research Agent...\")\n",
|
359
|
-
" print(\"Source: https://github.com/langchain-ai/open_deep_research\\n\")\n",
|
360
|
-
" \n",
|
361
|
-
" # Configure with Gemini models and Tavily search\n",
|
362
|
-
" config = Configuration(\n",
|
363
|
-
" summarization_model=\"gemini-2.5-flash\",\n",
|
364
|
-
" research_model=\"gemini-2.5-flash\",\n",
|
365
|
-
" compression_model=\"gemini-2.5-flash\",\n",
|
366
|
-
" final_report_model=\"gemini-2.5-flash\",\n",
|
367
|
-
" allow_clarification=False,\n",
|
368
|
-
" max_concurrent_research_units=2,\n",
|
369
|
-
" max_researcher_iterations=4,\n",
|
370
|
-
" max_react_tool_calls=8,\n",
|
371
|
-
" )\n",
|
372
|
-
" \n",
|
373
|
-
" print(\"Configuration:\")\n",
|
374
|
-
" print(f\" - Models: {config.research_model}\")\n",
|
375
|
-
" print(f\" - Search API: Tavily\")\n",
|
376
|
-
" print(f\" - Max concurrent researchers: {config.max_concurrent_research_units}\\n\")\n",
|
377
|
-
" \n",
|
378
|
-
" # Create the deep researcher graph\n",
|
379
|
-
" graph = deep_researcher_builder.compile()\n",
|
380
|
-
" \n",
|
381
|
-
" print(\"✅ Research agent created\\n\")\n",
|
382
|
-
" print(\"Graph structure:\")\n",
|
383
|
-
" print(\" 1. Brief Generation\")\n",
|
384
|
-
" print(\" 2. Research Supervisor\")\n",
|
385
|
-
" print(\" 3. Research Sub-Agents (parallel)\")\n",
|
386
|
-
" print(\" 4. Report Writing\\n\")\n",
|
387
|
-
" \n",
|
388
|
-
" # Add LLM reference for Dasein\n",
|
389
|
-
" graph.llm = ChatGoogleGenerativeAI(model=\"gemini-2.5-flash\", temperature=0)\n",
|
390
|
-
" \n",
|
391
|
-
" return graph\n",
|
392
|
-
"\n",
|
393
|
-
"# Create the research agent\n",
|
394
|
-
"research_agent = await create_research_agent()\n"
|
395
|
-
]
|
396
|
-
},
|
397
|
-
{
|
398
|
-
"cell_type": "code",
|
399
|
-
"execution_count": null,
|
400
|
-
"metadata": {},
|
401
|
-
"outputs": [],
|
402
|
-
"source": [
|
403
|
-
"# Wrap with Dasein\n",
|
404
|
-
"research_agent = cognate(\n",
|
405
|
-
" research_agent,\n",
|
406
|
-
" retry=2,\n",
|
407
|
-
" performance_tracking=True,\n",
|
408
|
-
" verbose=False # Set to True to see rule injection details\n",
|
409
|
-
")\n",
|
410
|
-
"\n",
|
411
|
-
"# Research query\n",
|
412
|
-
"query = \"\"\"Research and compare LangChain vs LlamaIndex for building LLM applications.\n",
|
413
|
-
"\n",
|
414
|
-
"I want to understand:\n",
|
415
|
-
"1. Their core philosophies and approaches\n",
|
416
|
-
"2. Key features and strengths\n",
|
417
|
-
"3. Which use cases each is best suited for\n",
|
418
|
-
"\n",
|
419
|
-
"Provide a concise comparison with sources.\"\"\"\n",
|
420
|
-
"\n",
|
421
|
-
"print(f\"Research Query: {query}\\n\")\n",
|
422
|
-
"print(\"=\" * 70)\n",
|
423
|
-
"print(\"This will trigger:\")\n",
|
424
|
-
"print(\" - Supervisor creating 2 sub-agents (one per framework)\")\n",
|
425
|
-
"print(\" - Parallel research with Tavily search\")\n",
|
426
|
-
"print(\" - Multiple search rounds per sub-agent\")\n",
|
427
|
-
"print(\" - Synthesis and report writing\\n\")\n",
|
428
|
-
"print(\"PHASE 1: Baseline run...\")\n",
|
429
|
-
"print(\"PHASE 2: Enhanced run with learned rules...\")\n",
|
430
|
-
"print(\"=\" * 70)\n",
|
431
|
-
"\n",
|
432
|
-
"result = await research_agent.ainvoke(\n",
|
433
|
-
" {\"messages\": [(\"user\", query)]},\n",
|
434
|
-
" config={\n",
|
435
|
-
" \"configurable\": {\n",
|
436
|
-
" \"allow_clarification\": False,\n",
|
437
|
-
" \"summarization_model\": \"gemini-2.5-flash\",\n",
|
438
|
-
" \"research_model\": \"gemini-2.5-flash\",\n",
|
439
|
-
" }\n",
|
440
|
-
" }\n",
|
441
|
-
")\n",
|
442
|
-
"\n",
|
443
|
-
"# Display report (truncated for readability)\n",
|
444
|
-
"report = str(result.get('report', result))\n",
|
445
|
-
"if len(report) > 500:\n",
|
446
|
-
" print(f\"\\n✅ Research Report (truncated):\\n{report[:500]}...\\n[{len(report)} total chars]\")\n",
|
447
|
-
"else:\n",
|
448
|
-
" print(f\"\\n✅ Research Report:\\n{report}\")\n",
|
449
|
-
"\n",
|
450
|
-
"print(\"\\n📊 Check the performance metrics above to see massive token savings!\")\n"
|
451
|
-
]
|
452
|
-
},
|
453
|
-
{
|
454
|
-
"cell_type": "markdown",
|
455
|
-
"metadata": {},
|
456
|
-
"source": [
|
457
|
-
"---\n",
|
458
|
-
"\n",
|
459
|
-
"## Summary\n",
|
460
|
-
"\n",
|
461
|
-
"You've just seen **Dasein** in action across three different agent types:\n",
|
462
|
-
"\n",
|
463
|
-
"1. **SQL Agent** - Learned query optimization patterns\n",
|
464
|
-
"2. **Browser Agent** - Learned navigation and tool usage strategies\n",
|
465
|
-
"3. **Deep Research Agent** - Learned to optimize complex multi-agent workflows\n",
|
466
|
-
"\n",
|
467
|
-
"### Key Takeaways\n",
|
468
|
-
"\n",
|
469
|
-
"- ✨ **One-line integration**: `cognate(agent)` is all you need\n",
|
470
|
-
"- 🧠 **Automatic learning**: Agents improve themselves without manual rule engineering\n",
|
471
|
-
"- 📊 **Transparent metrics**: See exactly how much you're improving\n",
|
472
|
-
"- ☁️ **Cloud-powered**: Rules are stored and synthesized using distributed services\n",
|
473
|
-
"- 🔄 **Intelligent retry**: `retry=2` automatically runs baseline + enhanced\n",
|
474
|
-
"\n",
|
475
|
-
"### Next Steps\n",
|
476
|
-
"\n",
|
477
|
-
"1. **Try your own agents** - Dasein works with any LangChain/LangGraph agent\n",
|
478
|
-
"2. **Customize optimization** - Use the `weights` parameter to optimize for what matters to you\n",
|
479
|
-
"3. **Build rule libraries** - Run multiple times to accumulate learned rules\n",
|
480
|
-
"4. **Scale up** - The more you use Dasein, the smarter your agents become\n",
|
481
|
-
"\n",
|
482
|
-
"### Resources\n",
|
483
|
-
"\n",
|
484
|
-
"- 📖 [Documentation](https://github.com/nickswami/dasein-core#readme)\n",
|
485
|
-
"- 💻 [GitHub](https://github.com/nickswami/dasein-core)\n",
|
486
|
-
"- 💬 [Discord Community](https://discord.gg/dasein)\n",
|
487
|
-
"- 🐛 [Report Issues](https://github.com/nickswami/dasein-core/issues)\n",
|
488
|
-
"\n",
|
489
|
-
"---\n",
|
490
|
-
"\n",
|
491
|
-
"**Built with ❤️ for the agentic AI community**\n"
|
492
|
-
]
|
493
|
-
}
|
494
|
-
],
|
495
|
-
"metadata": {
|
496
|
-
"language_info": {
|
497
|
-
"name": "python"
|
498
|
-
}
|
499
|
-
},
|
500
|
-
"nbformat": 4,
|
501
|
-
"nbformat_minor": 2
|
502
|
-
}
|
1
|
+
{
|
2
|
+
"cells": [
|
3
|
+
{
|
4
|
+
"cell_type": "markdown",
|
5
|
+
"metadata": {},
|
6
|
+
"source": [
|
7
|
+
"# 🧠 Dasein Examples: Universal Memory for Agentic AI\n",
|
8
|
+
"\n",
|
9
|
+
"[](https://colab.research.google.com/github/nickswami/dasein-core/blob/main/examples/dasein_examples.ipynb)\n",
|
10
|
+
"\n",
|
11
|
+
"This notebook demonstrates **Dasein** - a universal memory system that learns from your agent's execution history and automatically improves performance, reduces costs, and increases reliability.\n",
|
12
|
+
"\n",
|
13
|
+
"## What You'll Learn\n",
|
14
|
+
"\n",
|
15
|
+
"1. **SQL Agent** - Learn query patterns for database interactions\n",
|
16
|
+
"2. **Browser Agent** - Learn web scraping and navigation strategies\n",
|
17
|
+
"3. **Deep Research Agent** - Optimize multi-agent research workflows\n",
|
18
|
+
"\n",
|
19
|
+
"## Key Features\n",
|
20
|
+
"\n",
|
21
|
+
"- ✨ **Zero-friction integration** - Wrap any agent in one line\n",
|
22
|
+
"- 🧠 **Automatic learning** - Agents learn from successes and failures\n",
|
23
|
+
"- 📊 **Performance tracking** - See token usage, timing, and improvement metrics\n",
|
24
|
+
"- 🔄 **Retry logic** - Intelligent retry with learned optimizations\n",
|
25
|
+
"- ☁️ **Cloud-powered** - Distributed rule synthesis and storage\n"
|
26
|
+
]
|
27
|
+
},
|
28
|
+
{
|
29
|
+
"cell_type": "markdown",
|
30
|
+
"metadata": {},
|
31
|
+
"source": [
|
32
|
+
"## Installation\n"
|
33
|
+
]
|
34
|
+
},
|
35
|
+
{
|
36
|
+
"cell_type": "code",
|
37
|
+
"execution_count": null,
|
38
|
+
"metadata": {},
|
39
|
+
"outputs": [],
|
40
|
+
"source": [
|
41
|
+
"# Install Dasein and dependencies\n",
|
42
|
+
"!pip install -q dasein-core\n",
|
43
|
+
"\n",
|
44
|
+
"# For browser agent example (Use Case 2)\n",
|
45
|
+
"!pip install -q playwright\n",
|
46
|
+
"!playwright install chromium\n",
|
47
|
+
"\n",
|
48
|
+
"# For deep research agent (Use Case 3)\n",
|
49
|
+
"!pip install -q git+https://github.com/langchain-ai/open_deep_research.git\n"
|
50
|
+
]
|
51
|
+
},
|
52
|
+
{
|
53
|
+
"cell_type": "markdown",
|
54
|
+
"metadata": {},
|
55
|
+
"source": [
|
56
|
+
"## Setup API Keys\n",
|
57
|
+
"\n",
|
58
|
+
"Replace the placeholders below with your actual API keys:\n",
|
59
|
+
"\n",
|
60
|
+
"- **GOOGLE_API_KEY**: Get from [Google AI Studio](https://makersuite.google.com/app/apikey)\n",
|
61
|
+
"- **TAVILY_API_KEY**: Get from [Tavily](https://tavily.com) (free tier available, 1000 searches/month)\n"
|
62
|
+
]
|
63
|
+
},
|
64
|
+
{
|
65
|
+
"cell_type": "code",
|
66
|
+
"execution_count": null,
|
67
|
+
"metadata": {},
|
68
|
+
"outputs": [],
|
69
|
+
"source": [
|
70
|
+
"import os\n",
|
71
|
+
"\n",
|
72
|
+
"# ⚠️ REPLACE THESE WITH YOUR ACTUAL API KEYS\n",
|
73
|
+
"os.environ[\"GOOGLE_API_KEY\"] = \"YOUR_GOOGLE_API_KEY_HERE\"\n",
|
74
|
+
"os.environ[\"TAVILY_API_KEY\"] = \"YOUR_TAVILY_API_KEY_HERE\" # Only needed for Use Case 3\n",
|
75
|
+
"\n",
|
76
|
+
"# Suppress warnings\n",
|
77
|
+
"os.environ[\"GOOGLE_CLOUD_DISABLE_DIRECT_PATH\"] = \"true\"\n",
|
78
|
+
"\n",
|
79
|
+
"print(\"✅ API keys configured\")\n",
|
80
|
+
"print(\"\\n⚠️ Note: You may see dependency warnings in Colab - these are safe to ignore.\")\n",
|
81
|
+
"print(\"⚠️ Note: Brief timeout warnings on first run are normal (cold start) - services will activate automatically.\")\n"
|
82
|
+
]
|
83
|
+
},
|
84
|
+
{
|
85
|
+
"cell_type": "markdown",
|
86
|
+
"metadata": {},
|
87
|
+
"source": [
|
88
|
+
"---\n",
|
89
|
+
"\n",
|
90
|
+
"# Use Case 1: SQL Agent with Learning\n",
|
91
|
+
"\n",
|
92
|
+
"This example demonstrates how Dasein learns SQL query patterns and improves database agent performance.\n",
|
93
|
+
"\n",
|
94
|
+
"**What Happens:**\n",
|
95
|
+
"1. **Baseline Run**: Agent queries the Chinook database without optimization\n",
|
96
|
+
"2. **Learning**: Dasein captures the execution trace and sends it to cloud services for rule synthesis\n",
|
97
|
+
"3. **Enhanced Run**: Agent runs again with learned rules injected, showing improved performance\n",
|
98
|
+
"\n",
|
99
|
+
"**Expected Improvements:**\n",
|
100
|
+
"- 30-50% reduction in tokens used\n",
|
101
|
+
"- Fewer SQL query iterations\n",
|
102
|
+
"- Better query formulation\n"
|
103
|
+
]
|
104
|
+
},
|
105
|
+
{
|
106
|
+
"cell_type": "code",
|
107
|
+
"execution_count": null,
|
108
|
+
"metadata": {},
|
109
|
+
"outputs": [],
|
110
|
+
"source": [
|
111
|
+
"import urllib.request\n",
|
112
|
+
"from pathlib import Path\n",
|
113
|
+
"\n",
|
114
|
+
"# Download Chinook sample database\n",
|
115
|
+
"db_path = Path(\"chinook.db\")\n",
|
116
|
+
"if not db_path.exists():\n",
|
117
|
+
" print(\"Downloading Chinook database...\")\n",
|
118
|
+
" urllib.request.urlretrieve(\n",
|
119
|
+
" \"https://raw.githubusercontent.com/lerocha/chinook-database/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite\",\n",
|
120
|
+
" str(db_path)\n",
|
121
|
+
" )\n",
|
122
|
+
" print(\"✅ Database downloaded\")\n",
|
123
|
+
"else:\n",
|
124
|
+
" print(\"✅ Database already exists\")\n"
|
125
|
+
]
|
126
|
+
},
|
127
|
+
{
|
128
|
+
"cell_type": "code",
|
129
|
+
"execution_count": null,
|
130
|
+
"metadata": {},
|
131
|
+
"outputs": [],
|
132
|
+
"source": [
|
133
|
+
"from langchain_community.utilities import SQLDatabase\n",
|
134
|
+
"from langchain_community.agent_toolkits import SQLDatabaseToolkit\n",
|
135
|
+
"from langchain_community.agent_toolkits.sql.base import create_sql_agent\n",
|
136
|
+
"from langchain_google_genai import ChatGoogleGenerativeAI\n",
|
137
|
+
"from dasein import cognate\n",
|
138
|
+
"\n",
|
139
|
+
"# Set up SQL agent\n",
|
140
|
+
"print(\"Setting up SQL agent...\")\n",
|
141
|
+
"db = SQLDatabase.from_uri(f\"sqlite:///{db_path}\")\n",
|
142
|
+
"llm = ChatGoogleGenerativeAI(model=\"gemini-2.5-flash\", temperature=0)\n",
|
143
|
+
"toolkit = SQLDatabaseToolkit(db=db, llm=llm)\n",
|
144
|
+
"agent = create_sql_agent(llm=llm, toolkit=toolkit, verbose=True, handle_parsing_errors=True)\n",
|
145
|
+
"\n",
|
146
|
+
"print(\"✅ SQL agent created\")\n"
|
147
|
+
]
|
148
|
+
},
|
149
|
+
{
|
150
|
+
"cell_type": "code",
|
151
|
+
"execution_count": null,
|
152
|
+
"metadata": {},
|
153
|
+
"outputs": [],
|
154
|
+
"source": [
|
155
|
+
"# Wrap with Dasein for automatic learning and improvement\n",
|
156
|
+
"agent = cognate(\n",
|
157
|
+
" agent,\n",
|
158
|
+
" retry=2, # Run twice: baseline + enhanced\n",
|
159
|
+
" performance_tracking=True, # Show improvement metrics\n",
|
160
|
+
" verbose=False # Set to True to see rule injection details\n",
|
161
|
+
")\n",
|
162
|
+
"\n",
|
163
|
+
"# Run the query - Dasein handles everything automatically!\n",
|
164
|
+
"query = \"Which media format accounts for the highest number of individual line-item sales?\"\n",
|
165
|
+
"\n",
|
166
|
+
"print(f\"\\nQuery: {query}\\n\")\n",
|
167
|
+
"print(\"=\" * 70)\n",
|
168
|
+
"print(\"PHASE 1: Baseline run...\")\n",
|
169
|
+
"print(\"PHASE 2: Enhanced run with learned rules...\")\n",
|
170
|
+
"print(\"=\" * 70)\n",
|
171
|
+
"\n",
|
172
|
+
"result = agent.invoke({\"input\": query})\n",
|
173
|
+
"\n",
|
174
|
+
"print(f\"\\n✅ Final Answer: {result.get('output', '')}\")\n",
|
175
|
+
"print(\"\\n📊 Check the performance metrics above to see improvement!\")\n"
|
176
|
+
]
|
177
|
+
},
|
178
|
+
{
|
179
|
+
"cell_type": "markdown",
|
180
|
+
"metadata": {},
|
181
|
+
"source": [
|
182
|
+
"---\n",
|
183
|
+
"\n",
|
184
|
+
"# Use Case 2: Browser Agent with Learning\n",
|
185
|
+
"\n",
|
186
|
+
"This example demonstrates how Dasein learns web scraping and navigation patterns.\n",
|
187
|
+
"\n",
|
188
|
+
"**What Happens:**\n",
|
189
|
+
"1. **Baseline Run**: Browser agent navigates to a website without optimization\n",
|
190
|
+
"2. **Learning**: Dasein learns which tools to use, navigation patterns, and element selection strategies\n",
|
191
|
+
"3. **Enhanced Run**: Agent runs again with learned rules, showing faster and more efficient browsing\n",
|
192
|
+
"\n",
|
193
|
+
"**Expected Improvements:**\n",
|
194
|
+
"- Fewer navigation steps\n",
|
195
|
+
"- Better tool selection\n",
|
196
|
+
"- More efficient element targeting\n",
|
197
|
+
"- Reduced token usage\n"
|
198
|
+
]
|
199
|
+
},
|
200
|
+
{
|
201
|
+
"cell_type": "code",
|
202
|
+
"execution_count": null,
|
203
|
+
"metadata": {},
|
204
|
+
"outputs": [],
|
205
|
+
"source": [
|
206
|
+
"from langchain_community.agent_toolkits import PlayWrightBrowserToolkit\n",
|
207
|
+
"from langchain_google_genai import ChatGoogleGenerativeAI\n",
|
208
|
+
"from langgraph.prebuilt import create_react_agent\n",
|
209
|
+
"from dasein import cognate\n",
|
210
|
+
"import asyncio\n",
|
211
|
+
"from playwright.async_api import async_playwright\n",
|
212
|
+
"\n",
|
213
|
+
"async def create_browser_agent():\n",
|
214
|
+
" \"\"\"Create a Playwright browser agent.\"\"\"\n",
|
215
|
+
" print(\"Setting up Playwright browser agent...\")\n",
|
216
|
+
" \n",
|
217
|
+
" # Create browser\n",
|
218
|
+
" playwright = await async_playwright().start()\n",
|
219
|
+
" async_browser = await playwright.chromium.launch(headless=True)\n",
|
220
|
+
" \n",
|
221
|
+
" # Create toolkit and tools\n",
|
222
|
+
" toolkit = PlayWrightBrowserToolkit.from_browser(async_browser=async_browser)\n",
|
223
|
+
" tools = toolkit.get_tools()\n",
|
224
|
+
" \n",
|
225
|
+
" print(f\"Available browser tools: {[tool.name for tool in tools]}\")\n",
|
226
|
+
" \n",
|
227
|
+
" # Create LLM\n",
|
228
|
+
" llm = ChatGoogleGenerativeAI(\n",
|
229
|
+
" model=\"gemini-2.5-flash\",\n",
|
230
|
+
" temperature=0,\n",
|
231
|
+
" request_timeout=180,\n",
|
232
|
+
" max_retries=2\n",
|
233
|
+
" )\n",
|
234
|
+
" \n",
|
235
|
+
" # Create agent\n",
|
236
|
+
" agent_chain = create_react_agent(model=llm, tools=tools)\n",
|
237
|
+
" agent_chain = agent_chain.with_config({\"recursion_limit\": 75})\n",
|
238
|
+
" agent_chain.llm = llm # Add LLM reference for Dasein\n",
|
239
|
+
" \n",
|
240
|
+
" print(\"✅ Browser agent created\")\n",
|
241
|
+
" return agent_chain\n",
|
242
|
+
"\n",
|
243
|
+
"# Create the agent\n",
|
244
|
+
"browser_agent = await create_browser_agent()\n"
|
245
|
+
]
|
246
|
+
},
|
247
|
+
{
|
248
|
+
"cell_type": "code",
|
249
|
+
"execution_count": null,
|
250
|
+
"metadata": {},
|
251
|
+
"outputs": [],
|
252
|
+
"source": [
|
253
|
+
"# Wrap with Dasein\n",
|
254
|
+
"browser_agent = cognate(\n",
|
255
|
+
" browser_agent,\n",
|
256
|
+
" retry=2,\n",
|
257
|
+
" performance_tracking=True,\n",
|
258
|
+
" verbose=False # Set to True to see rule injection details\n",
|
259
|
+
")\n",
|
260
|
+
"\n",
|
261
|
+
"# Test query\n",
|
262
|
+
"query = \"Go to the LangChain site (https://python.langchain.com). Is there a tutorial on how to create a browsing agent? If so where is it?\"\n",
|
263
|
+
"\n",
|
264
|
+
"print(f\"\\nQuery: {query}\\n\")\n",
|
265
|
+
"print(\"=\" * 70)\n",
|
266
|
+
"print(\"PHASE 1: Baseline run...\")\n",
|
267
|
+
"print(\"PHASE 2: Enhanced run with learned rules...\")\n",
|
268
|
+
"print(\"=\" * 70)\n",
|
269
|
+
"\n",
|
270
|
+
"result = await browser_agent.ainvoke({\"messages\": [(\"user\", query)]})\n",
|
271
|
+
"\n",
|
272
|
+
"print(f\"\\n✅ Final Answer: {result}\")\n",
|
273
|
+
"print(\"\\n📊 Check the performance metrics above to see improvement!\")\n"
|
274
|
+
]
|
275
|
+
},
|
276
|
+
{
|
277
|
+
"cell_type": "markdown",
|
278
|
+
"metadata": {},
|
279
|
+
"source": [
|
280
|
+
"---\n",
|
281
|
+
"\n",
|
282
|
+
"# Use Case 3: Deep Research Agent with Learning\n",
|
283
|
+
"\n",
|
284
|
+
"This example demonstrates Dasein with LangChain's **Open Deep Research Agent** - a complex multi-agent system that orchestrates research tasks.\n",
|
285
|
+
"\n",
|
286
|
+
"**What Happens:**\n",
|
287
|
+
"1. **Baseline Run**: Multi-agent research system runs without optimization\n",
|
288
|
+
" - Supervisor delegates to sub-agents\n",
|
289
|
+
" - Parallel research with Tavily search\n",
|
290
|
+
" - Context accumulation and synthesis\n",
|
291
|
+
" - Typically uses 15x more tokens than normal chat!\n",
|
292
|
+
"\n",
|
293
|
+
"2. **Learning**: Dasein learns:\n",
|
294
|
+
" - Better search query formulation\n",
|
295
|
+
" - Context filtering to reduce token bloat\n",
|
296
|
+
" - Improved delegation strategies\n",
|
297
|
+
" - Efficient tool usage patterns\n",
|
298
|
+
"\n",
|
299
|
+
"3. **Enhanced Run**: Agent runs with learned rules\n",
|
300
|
+
"\n",
|
301
|
+
"**Expected Improvements:**\n",
|
302
|
+
"- 20-40% reduction in tokens used\n",
|
303
|
+
"- Fewer redundant searches\n",
|
304
|
+
"- Better query formulation\n",
|
305
|
+
"- Faster convergence to quality results\n",
|
306
|
+
"\n",
|
307
|
+
"**Requirements:**\n",
|
308
|
+
"- TAVILY_API_KEY (free tier: 1000 searches/month)\n"
|
309
|
+
]
|
310
|
+
},
|
311
|
+
{
|
312
|
+
"cell_type": "code",
|
313
|
+
"execution_count": null,
|
314
|
+
"metadata": {},
|
315
|
+
"outputs": [],
|
316
|
+
"source": [
|
317
|
+
"# Critical fix: Force LangChain to use Google GenAI instead of Vertex AI\n",
|
318
|
+
"from langchain.chat_models import base as chat_models_base\n",
|
319
|
+
"from langchain_google_genai import ChatGoogleGenerativeAI\n",
|
320
|
+
"\n",
|
321
|
+
"original_init_helper = chat_models_base._init_chat_model_helper\n",
|
322
|
+
"_model_cache = {}\n",
|
323
|
+
"_patch_logged = set()\n",
|
324
|
+
"\n",
|
325
|
+
"def patched_init_helper(*args, **kwargs):\n",
|
326
|
+
" \"\"\"Force gemini models to use ChatGoogleGenerativeAI.\"\"\"\n",
|
327
|
+
" model = kwargs.get('model', '')\n",
|
328
|
+
" if not model and args:\n",
|
329
|
+
" model = args[0] if len(args) > 0 and isinstance(args[0], str) else ''\n",
|
330
|
+
" \n",
|
331
|
+
" if model and 'gemini' in model.lower():\n",
|
332
|
+
" if model not in _patch_logged:\n",
|
333
|
+
" print(f\"🔧 Using ChatGoogleGenerativeAI for {model}\")\n",
|
334
|
+
" _patch_logged.add(model)\n",
|
335
|
+
" \n",
|
336
|
+
" if model not in _model_cache:\n",
|
337
|
+
" _model_cache[model] = ChatGoogleGenerativeAI(model=model)\n",
|
338
|
+
" return _model_cache[model]\n",
|
339
|
+
" return original_init_helper(*args, **kwargs)\n",
|
340
|
+
"\n",
|
341
|
+
"chat_models_base._init_chat_model_helper = patched_init_helper\n",
|
342
|
+
"print(\"✅ Patched LangChain to use Google GenAI\")\n"
|
343
|
+
]
|
344
|
+
},
|
345
|
+
{
|
346
|
+
"cell_type": "code",
|
347
|
+
"execution_count": null,
|
348
|
+
"metadata": {},
|
349
|
+
"outputs": [],
|
350
|
+
"source": [
|
351
|
+
"from open_deep_research.deep_researcher import deep_researcher_builder\n",
|
352
|
+
"from open_deep_research.configuration import Configuration\n",
|
353
|
+
"from dasein import cognate\n",
|
354
|
+
"import asyncio\n",
|
355
|
+
"\n",
|
356
|
+
"async def create_research_agent():\n",
|
357
|
+
" \"\"\"Create Open Deep Research agent.\"\"\"\n",
|
358
|
+
" print(\"Setting up Open Deep Research Agent...\")\n",
|
359
|
+
" print(\"Source: https://github.com/langchain-ai/open_deep_research\\n\")\n",
|
360
|
+
" \n",
|
361
|
+
" # Configure with Gemini models and Tavily search\n",
|
362
|
+
" config = Configuration(\n",
|
363
|
+
" summarization_model=\"gemini-2.5-flash\",\n",
|
364
|
+
" research_model=\"gemini-2.5-flash\",\n",
|
365
|
+
" compression_model=\"gemini-2.5-flash\",\n",
|
366
|
+
" final_report_model=\"gemini-2.5-flash\",\n",
|
367
|
+
" allow_clarification=False,\n",
|
368
|
+
" max_concurrent_research_units=2,\n",
|
369
|
+
" max_researcher_iterations=4,\n",
|
370
|
+
" max_react_tool_calls=8,\n",
|
371
|
+
" )\n",
|
372
|
+
" \n",
|
373
|
+
" print(\"Configuration:\")\n",
|
374
|
+
" print(f\" - Models: {config.research_model}\")\n",
|
375
|
+
" print(f\" - Search API: Tavily\")\n",
|
376
|
+
" print(f\" - Max concurrent researchers: {config.max_concurrent_research_units}\\n\")\n",
|
377
|
+
" \n",
|
378
|
+
" # Create the deep researcher graph\n",
|
379
|
+
" graph = deep_researcher_builder.compile()\n",
|
380
|
+
" \n",
|
381
|
+
" print(\"✅ Research agent created\\n\")\n",
|
382
|
+
" print(\"Graph structure:\")\n",
|
383
|
+
" print(\" 1. Brief Generation\")\n",
|
384
|
+
" print(\" 2. Research Supervisor\")\n",
|
385
|
+
" print(\" 3. Research Sub-Agents (parallel)\")\n",
|
386
|
+
" print(\" 4. Report Writing\\n\")\n",
|
387
|
+
" \n",
|
388
|
+
" # Add LLM reference for Dasein\n",
|
389
|
+
" graph.llm = ChatGoogleGenerativeAI(model=\"gemini-2.5-flash\", temperature=0)\n",
|
390
|
+
" \n",
|
391
|
+
" return graph\n",
|
392
|
+
"\n",
|
393
|
+
"# Create the research agent\n",
|
394
|
+
"research_agent = await create_research_agent()\n"
|
395
|
+
]
|
396
|
+
},
|
397
|
+
{
|
398
|
+
"cell_type": "code",
|
399
|
+
"execution_count": null,
|
400
|
+
"metadata": {},
|
401
|
+
"outputs": [],
|
402
|
+
"source": [
|
403
|
+
"# Wrap with Dasein\n",
|
404
|
+
"research_agent = cognate(\n",
|
405
|
+
" research_agent,\n",
|
406
|
+
" retry=2,\n",
|
407
|
+
" performance_tracking=True,\n",
|
408
|
+
" verbose=False # Set to True to see rule injection details\n",
|
409
|
+
")\n",
|
410
|
+
"\n",
|
411
|
+
"# Research query\n",
|
412
|
+
"query = \"\"\"Research and compare LangChain vs LlamaIndex for building LLM applications.\n",
|
413
|
+
"\n",
|
414
|
+
"I want to understand:\n",
|
415
|
+
"1. Their core philosophies and approaches\n",
|
416
|
+
"2. Key features and strengths\n",
|
417
|
+
"3. Which use cases each is best suited for\n",
|
418
|
+
"\n",
|
419
|
+
"Provide a concise comparison with sources.\"\"\"\n",
|
420
|
+
"\n",
|
421
|
+
"print(f\"Research Query: {query}\\n\")\n",
|
422
|
+
"print(\"=\" * 70)\n",
|
423
|
+
"print(\"This will trigger:\")\n",
|
424
|
+
"print(\" - Supervisor creating 2 sub-agents (one per framework)\")\n",
|
425
|
+
"print(\" - Parallel research with Tavily search\")\n",
|
426
|
+
"print(\" - Multiple search rounds per sub-agent\")\n",
|
427
|
+
"print(\" - Synthesis and report writing\\n\")\n",
|
428
|
+
"print(\"PHASE 1: Baseline run...\")\n",
|
429
|
+
"print(\"PHASE 2: Enhanced run with learned rules...\")\n",
|
430
|
+
"print(\"=\" * 70)\n",
|
431
|
+
"\n",
|
432
|
+
"result = await research_agent.ainvoke(\n",
|
433
|
+
" {\"messages\": [(\"user\", query)]},\n",
|
434
|
+
" config={\n",
|
435
|
+
" \"configurable\": {\n",
|
436
|
+
" \"allow_clarification\": False,\n",
|
437
|
+
" \"summarization_model\": \"gemini-2.5-flash\",\n",
|
438
|
+
" \"research_model\": \"gemini-2.5-flash\",\n",
|
439
|
+
" }\n",
|
440
|
+
" }\n",
|
441
|
+
")\n",
|
442
|
+
"\n",
|
443
|
+
"# Display report (truncated for readability)\n",
|
444
|
+
"report = str(result.get('report', result))\n",
|
445
|
+
"if len(report) > 500:\n",
|
446
|
+
" print(f\"\\n✅ Research Report (truncated):\\n{report[:500]}...\\n[{len(report)} total chars]\")\n",
|
447
|
+
"else:\n",
|
448
|
+
" print(f\"\\n✅ Research Report:\\n{report}\")\n",
|
449
|
+
"\n",
|
450
|
+
"print(\"\\n📊 Check the performance metrics above to see massive token savings!\")\n"
|
451
|
+
]
|
452
|
+
},
|
453
|
+
{
|
454
|
+
"cell_type": "markdown",
|
455
|
+
"metadata": {},
|
456
|
+
"source": [
|
457
|
+
"---\n",
|
458
|
+
"\n",
|
459
|
+
"## Summary\n",
|
460
|
+
"\n",
|
461
|
+
"You've just seen **Dasein** in action across three different agent types:\n",
|
462
|
+
"\n",
|
463
|
+
"1. **SQL Agent** - Learned query optimization patterns\n",
|
464
|
+
"2. **Browser Agent** - Learned navigation and tool usage strategies\n",
|
465
|
+
"3. **Deep Research Agent** - Learned to optimize complex multi-agent workflows\n",
|
466
|
+
"\n",
|
467
|
+
"### Key Takeaways\n",
|
468
|
+
"\n",
|
469
|
+
"- ✨ **One-line integration**: `cognate(agent)` is all you need\n",
|
470
|
+
"- 🧠 **Automatic learning**: Agents improve themselves without manual rule engineering\n",
|
471
|
+
"- 📊 **Transparent metrics**: See exactly how much you're improving\n",
|
472
|
+
"- ☁️ **Cloud-powered**: Rules are stored and synthesized using distributed services\n",
|
473
|
+
"- 🔄 **Intelligent retry**: `retry=2` automatically runs baseline + enhanced\n",
|
474
|
+
"\n",
|
475
|
+
"### Next Steps\n",
|
476
|
+
"\n",
|
477
|
+
"1. **Try your own agents** - Dasein works with any LangChain/LangGraph agent\n",
|
478
|
+
"2. **Customize optimization** - Use the `weights` parameter to optimize for what matters to you\n",
|
479
|
+
"3. **Build rule libraries** - Run multiple times to accumulate learned rules\n",
|
480
|
+
"4. **Scale up** - The more you use Dasein, the smarter your agents become\n",
|
481
|
+
"\n",
|
482
|
+
"### Resources\n",
|
483
|
+
"\n",
|
484
|
+
"- 📖 [Documentation](https://github.com/nickswami/dasein-core#readme)\n",
|
485
|
+
"- 💻 [GitHub](https://github.com/nickswami/dasein-core)\n",
|
486
|
+
"- 💬 [Discord Community](https://discord.gg/dasein)\n",
|
487
|
+
"- 🐛 [Report Issues](https://github.com/nickswami/dasein-core/issues)\n",
|
488
|
+
"\n",
|
489
|
+
"---\n",
|
490
|
+
"\n",
|
491
|
+
"**Built with ❤️ for the agentic AI community**\n"
|
492
|
+
]
|
493
|
+
}
|
494
|
+
],
|
495
|
+
"metadata": {
|
496
|
+
"language_info": {
|
497
|
+
"name": "python"
|
498
|
+
}
|
499
|
+
},
|
500
|
+
"nbformat": 4,
|
501
|
+
"nbformat_minor": 2
|
502
|
+
}
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "dasein-core"
|
7
|
-
version = "0.2.
|
7
|
+
version = "0.2.6"
|
8
8
|
description = "Universal memory for agentic AI. Attach a brain to any LangChain/LangGraph agent in a single line."
|
9
9
|
readme = "README.md"
|
10
10
|
requires-python = ">=3.8"
|
@@ -2163,12 +2163,14 @@ Follow these rules when planning your actions."""
|
|
2163
2163
|
tool_calls = len([step for step in trace if step.get('step_type') == 'tool_start'])
|
2164
2164
|
total_turns = len(trace)
|
2165
2165
|
|
2166
|
-
# Sum up tokens and time
|
2166
|
+
# Sum up tokens and calculate average time
|
2167
2167
|
input_tokens = sum(step.get('tokens_input', 0) for step in trace)
|
2168
2168
|
output_tokens = sum(step.get('tokens_output', 0) for step in trace)
|
2169
2169
|
total_tokens = input_tokens + output_tokens
|
2170
2170
|
|
2171
|
-
|
2171
|
+
# Calculate average duration_ms across all steps that have timing data
|
2172
|
+
durations = [step.get('duration_ms', 0) for step in trace if step.get('duration_ms', 0) > 0]
|
2173
|
+
trace_time_ms = int(sum(durations) / len(durations)) if durations else 0
|
2172
2174
|
|
2173
2175
|
# Calculate wall time from timestamps (they are ISO format strings)
|
2174
2176
|
if len(trace) > 1:
|
@@ -2823,6 +2825,81 @@ Follow these rules when planning your actions."""
|
|
2823
2825
|
return getattr(agent, 'agent_id', None) or f"agent_{id(agent)}"
|
2824
2826
|
|
2825
2827
|
agent_fingerprint = _minimal_agent_fingerprint(self._agent)
|
2828
|
+
|
2829
|
+
# Extract tool metadata for Stage 3.5 tool grounding
|
2830
|
+
def _extract_tool_metadata(agent):
|
2831
|
+
"""
|
2832
|
+
Extract tool metadata (name, description, args_schema) from agent.
|
2833
|
+
|
2834
|
+
CRITICAL: Extracts ALL available tools from the agent, not just tools used in trace.
|
2835
|
+
Why: If agent used wrong tool (e.g., extract_text instead of get_elements),
|
2836
|
+
the trace won't show the correct tool. Stage 3.5 needs to see all options
|
2837
|
+
to suggest better alternatives.
|
2838
|
+
"""
|
2839
|
+
tools_metadata = []
|
2840
|
+
tools_to_process = []
|
2841
|
+
|
2842
|
+
# Get ALL tools from agent (LangChain or LangGraph) - not filtered by trace usage
|
2843
|
+
tools_attr = getattr(agent, 'tools', None)
|
2844
|
+
if tools_attr:
|
2845
|
+
try:
|
2846
|
+
tools_to_process = list(tools_attr)
|
2847
|
+
except Exception:
|
2848
|
+
pass
|
2849
|
+
elif getattr(agent, 'toolkit', None):
|
2850
|
+
tk = getattr(agent, 'toolkit')
|
2851
|
+
tk_tools = getattr(tk, 'tools', None) or getattr(tk, 'get_tools', None)
|
2852
|
+
try:
|
2853
|
+
tools_to_process = list(tk_tools() if callable(tk_tools) else tk_tools or [])
|
2854
|
+
except Exception:
|
2855
|
+
pass
|
2856
|
+
|
2857
|
+
# Also try LangGraph tools from compiled graph
|
2858
|
+
if hasattr(agent, 'nodes') and 'tools' in agent.nodes:
|
2859
|
+
tools_node = agent.nodes['tools']
|
2860
|
+
if hasattr(tools_node, 'node') and hasattr(tools_node.node, 'steps'):
|
2861
|
+
for step in tools_node.node.steps:
|
2862
|
+
if hasattr(step, 'tools_by_name'):
|
2863
|
+
tools_to_process.extend(step.tools_by_name.values())
|
2864
|
+
break
|
2865
|
+
|
2866
|
+
# Extract metadata from each tool
|
2867
|
+
for tool in tools_to_process:
|
2868
|
+
try:
|
2869
|
+
tool_meta = {
|
2870
|
+
'name': getattr(tool, 'name', str(tool.__class__.__name__)),
|
2871
|
+
'description': getattr(tool, 'description', ''),
|
2872
|
+
}
|
2873
|
+
|
2874
|
+
# Extract args_schema if available
|
2875
|
+
if hasattr(tool, 'args_schema') and tool.args_schema:
|
2876
|
+
try:
|
2877
|
+
# Try Pydantic v2 method
|
2878
|
+
if hasattr(tool.args_schema, 'model_json_schema'):
|
2879
|
+
tool_meta['args_schema'] = tool.args_schema.model_json_schema()
|
2880
|
+
# Fallback to Pydantic v1 method
|
2881
|
+
elif hasattr(tool.args_schema, 'schema'):
|
2882
|
+
tool_meta['args_schema'] = tool.args_schema.schema()
|
2883
|
+
else:
|
2884
|
+
tool_meta['args_schema'] = {}
|
2885
|
+
except Exception:
|
2886
|
+
tool_meta['args_schema'] = {}
|
2887
|
+
else:
|
2888
|
+
tool_meta['args_schema'] = {}
|
2889
|
+
|
2890
|
+
tools_metadata.append(tool_meta)
|
2891
|
+
except Exception as e:
|
2892
|
+
# Skip tools that fail to extract
|
2893
|
+
pass
|
2894
|
+
|
2895
|
+
return tools_metadata
|
2896
|
+
|
2897
|
+
tools_metadata = _extract_tool_metadata(self._agent)
|
2898
|
+
print(f"[DASEIN] Extracted metadata for {len(tools_metadata)} tools")
|
2899
|
+
if tools_metadata:
|
2900
|
+
print(f"[DASEIN] Sample tool: {tools_metadata[0].get('name', 'unknown')}")
|
2901
|
+
else:
|
2902
|
+
print(f"[DASEIN] WARNING: No tools extracted! Agent type: {type(self._agent)}")
|
2826
2903
|
|
2827
2904
|
response = self._service_adapter.synthesize_rules(
|
2828
2905
|
run_id=None, # Will use stored run_id from pre-run phase
|
@@ -2837,7 +2914,8 @@ Follow these rules when planning your actions."""
|
|
2837
2914
|
agent_fingerprint=agent_fingerprint, # Reuse fingerprint from pre-run (line 2613)
|
2838
2915
|
step_id=self._current_step_id, # Pass step_id for parallel execution tracking
|
2839
2916
|
post_run_mode=self._post_run, # Pass post_run mode ("full" or "kpi_only")
|
2840
|
-
wait_for_synthesis=wait_for_synthesis # Wait for synthesis on retry runs (except last)
|
2917
|
+
wait_for_synthesis=wait_for_synthesis, # Wait for synthesis on retry runs (except last)
|
2918
|
+
tools_metadata=tools_metadata # Tool metadata for Stage 3.5 tool grounding
|
2841
2919
|
)
|
2842
2920
|
|
2843
2921
|
# response is a dict from ServiceAdapter; handle accordingly
|
@@ -32,6 +32,7 @@ class RuleSynthesisRequest:
|
|
32
32
|
skip_synthesis: bool = False
|
33
33
|
wait_for_synthesis: bool = False
|
34
34
|
step_id: Optional[str] = None
|
35
|
+
tools_metadata: Optional[List[Dict[str, Any]]] = None # Tool metadata for Stage 3.5 grounding
|
35
36
|
|
36
37
|
|
37
38
|
@dataclass
|
@@ -95,6 +96,7 @@ class PostRunClient:
|
|
95
96
|
"performance_tracking_id": request.performance_tracking_id,
|
96
97
|
"skip_synthesis": request.skip_synthesis,
|
97
98
|
"wait_for_synthesis": request.wait_for_synthesis,
|
99
|
+
"tools_metadata": request.tools_metadata or [], # Tool metadata for Stage 3.5 grounding
|
98
100
|
}
|
99
101
|
|
100
102
|
logger.info(f"Synthesizing rules for run: {request.run_id}")
|
@@ -95,7 +95,7 @@ class ServiceAdapter:
|
|
95
95
|
max_rules: Optional[int] = 5, performance_tracking_id: Optional[str] = None,
|
96
96
|
skip_synthesis: bool = False, agent_fingerprint: Optional[str] = None,
|
97
97
|
step_id: Optional[str] = None, post_run_mode: str = "full",
|
98
|
-
wait_for_synthesis: bool = False) -> Dict[str, Any]:
|
98
|
+
wait_for_synthesis: bool = False, tools_metadata: Optional[List[Dict[str, Any]]] = None) -> Dict[str, Any]:
|
99
99
|
"""
|
100
100
|
Synthesize rules from run telemetry (replaces local rule synthesis)
|
101
101
|
|
@@ -138,7 +138,8 @@ class ServiceAdapter:
|
|
138
138
|
performance_tracking_id=performance_tracking_id,
|
139
139
|
skip_synthesis=should_skip_synthesis,
|
140
140
|
wait_for_synthesis=wait_for_synthesis,
|
141
|
-
step_id=step_id
|
141
|
+
step_id=step_id,
|
142
|
+
tools_metadata=tools_metadata
|
142
143
|
)
|
143
144
|
|
144
145
|
response = self.post_run_client.synthesize_rules(request)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|