@@ -109,28 +109,7 @@ python 01_ask_llm.py
109109` ` `
110110<!-- END_STEP -->
111111
112- This example demonstrates the simplest way to use Dapr Agents' OpenAIChatClient :
113-
114- ` ` ` python
115- from dotenv import load_dotenv
116-
117- from dapr_agents import OpenAIChatClient
118- from dapr_agents.types.message import LLMChatResponse
119-
120- # load environment variables from .env file
121- load_dotenv()
122-
123- # Initialize the OpenAI chat client
124- llm = OpenAIChatClient()
125-
126- # Generate a response from the LLM
127- response: LLMChatResponse = llm.generate("Tell me a joke")
128-
129- # Print the Message content if it exists
130- if response.get_message() is not None:
131- content = response.get_message().content
132- print("Got response:", content)
133- ` ` `
112+ This example demonstrates the simplest way to use Dapr Agents' OpenAIChatClient.
134113
135114**Expected output:** The LLM will respond with a joke.
136115
@@ -157,34 +136,7 @@ python 02_build_agent.py
157136` ` `
158137<!-- END_STEP -->
159138
160- This example shows how to create a basic agent with a custom tool :
161-
162- ` ` ` python
163- import asyncio
164- from dapr_agents import tool, Agent
165- from dotenv import load_dotenv
166-
167- load_dotenv()
168-
169- @tool
170- def my_weather_func() -> str:
171- """Get current weather."""
172- return "It's 72°F and sunny"
173-
174- async def main():
175- weather_agent = Agent(
176- name="WeatherAgent",
177- role="Weather Assistant",
178- instructions=["Help users with weather information"],
179- tools=[my_weather_func]
180- )
181-
182- response = await weather_agent.run("What's the weather?")
183- print(response)
184-
185- if __name__ == "__main__":
186- asyncio.run(main())
187- ` ` `
139+ This example shows how to create a basic agent with a custom tool.
188140
189141**Expected output:** The agent will use the weather tool to provide the current weather.
190142
@@ -226,85 +178,12 @@ dapr run --app-id stateful-llm --dapr-http-port 3500 --resources-path $(../resol
226178
227179<!-- END_STEP -->
228180
229-
230181This example demonstrates a stateful travel planning assistant that :
2311821. Remembers user context persistently (across restarts)
2321832. Uses a tool to search for flight options
2331843. Exposes a REST API for workflow interaction
2341854. Stores execution state in Dapr workflow state stores
235186
236- ` ` ` python
237- #!/usr/bin/env python3
238- """
239- Stateful Augmented LLM Pattern demonstrates:
240- 1. Memory - remembering user preferences
241- 2. Tool use - accessing external data
242- 3. LLM abstraction
243- 4. Durable execution of tools as workflow actions
244- """
245- import asyncio
246- import logging
247- from typing import List
248- from pydantic import BaseModel, Field
249- from dapr_agents import tool, DurableAgent
250- from dapr_agents.memory import ConversationDaprStateMemory
251- from dotenv import load_dotenv
252-
253- # Define tool output model
254- class FlightOption(BaseModel):
255- airline: str = Field(description="Airline name")
256- price: float = Field(description="Price in USD")
257-
258- # Define tool input model
259- class DestinationSchema(BaseModel):
260- destination: str = Field(description="Destination city name")
261-
262- # Define flight search tool
263- @tool(args_model=DestinationSchema)
264- def search_flights(destination: str) -> List[FlightOption]:
265- """Search for flights to the specified destination."""
266- # Mock flight data (would be an external API call in a real app)
267- return [
268- FlightOption(airline="SkyHighAir", price=450.00),
269- FlightOption(airline="GlobalWings", price=375.50)
270- ]
271-
272- async def main():
273- try:
274- # Initialize TravelBuddy agent
275- travel_planner = DurableAgent(
276- name="TravelBuddy",
277- role="Travel Planner",
278- goal="Help users find flights and remember preferences",
279- instructions=[
280- "Find flights to destinations",
281- "Remember user preferences",
282- "Provide clear flight info"
283- ],
284- tools=[search_flights],
285- message_bus_name="messagepubsub",
286- state_store_name="workflowstatestore",
287- state_key="workflow_state",
288- agents_registry_store_name="registrystatestore",
289- agents_registry_key="agents_registry",
290- memory=ConversationDaprStateMemory(
291- store_name="conversationstore", session_id="my-unique-id"
292- )
293- )
294-
295- travel_planner.as_service(port=8001)
296- await travel_planner.start()
297- print("Travel Planner Agent is running")
298-
299- except Exception as e:
300- print(f"Error starting service: {e}")
301-
302- if __name__ == "__main__":
303- load_dotenv()
304- logging.basicConfig(level=logging.INFO)
305- asyncio.run(main())
306- ` ` `
307-
308187# ## Interacting with the Agent
309188
310189Unlike simpler agents, this stateful agent exposes a REST API for workflow interactions :
@@ -360,40 +239,7 @@ dapr run --app-id dapr-agent-wf --resources-path $(../resolve_env_templates.py .
360239` ` `
361240<!-- END_STEP -->
362241
363- This example demonstrates how to create a workflow with multiple tasks :
364-
365- ` ` ` python
366- from dapr_agents.workflow import WorkflowApp, workflow, task
367- from dapr.ext.workflow import DaprWorkflowContext
368-
369- from dotenv import load_dotenv
370-
371- load_dotenv()
372-
373- @workflow(name='analyze_topic')
374- def analyze_topic(ctx: DaprWorkflowContext, topic: str):
375- # Each step is durable and can be retried
376- outline = yield ctx.call_activity(create_outline, input=topic)
377- blog_post = yield ctx.call_activity(write_blog, input=outline)
378- return blog_post
379-
380- @task(description="Create a detailed outline about {topic}")
381- def create_outline(topic: str) -> str:
382- pass
383-
384- @task(description="Write a comprehensive blog post following this outline: {outline}")
385- def write_blog(outline: str) -> str:
386- pass
387-
388- if __name__ == '__main__':
389- wfapp = WorkflowApp()
390-
391- results = wfapp.run_and_monitor_workflow_sync(
392- analyze_topic,
393- input="AI Agents"
394- )
395- print(f"Result: {results}")
396- ` ` `
242+ This example demonstrates how to create a workflow with multiple tasks.
397243
398244**Expected output:** The workflow will create an outline about AI Agents and then generate a blog post based on that outline.
399245
@@ -439,142 +285,11 @@ output_match_mode: substring
439285` ` ` bash
440286source .venv/bin/activate
441287
442- python 05_agent_with_vectorstore.py
288+ dapr run --app-id vectorstore --resources-path $(../resolve_env_templates.py ./components) -- python 05_agent_with_vectorstore.py
443289` ` `
444290<!-- END_STEP -->
445291
446- This example demonstrates how to create an agent with vector store capabilities, including logging, structured Document usage, and a tool to add a machine learning basics document :
447-
448- ` ` ` python
449- import logging
450-
451- from dotenv import load_dotenv
452-
453- from dapr_agents import Agent
454- from dapr_agents.document.embedder.sentence import SentenceTransformerEmbedder
455- from dapr_agents.storage.vectorstores import ChromaVectorStore
456- from dapr_agents.tool import tool
457- from dapr_agents.types.document import Document
458-
459- logging.basicConfig(level=logging.INFO)
460-
461- embedding_function = SentenceTransformerEmbedder(model="all-MiniLM-L6-v2")
462- vector_store = ChromaVectorStore(
463- name="demo_vectorstore",
464- embedding_function=embedding_function,
465- persistent=True,
466- path="./chroma_db",
467- )
468-
469- @tool
470- def search_documents(query: str) -> str:
471- """Search for documents in the vector store"""
472- logging.info(f"Searching for documents with query: {query}")
473- results = vector_store.search_similar(query_texts=query, k=3)
474- docs = results.get("documents", [])
475- metadatas = results.get("metadatas", [])
476- if not docs:
477- logging.info(f"No documents found for query: '{query}'")
478- return f"No documents found for query: '{query}'"
479- response = []
480- for doc, meta in zip(docs, metadatas):
481- response.append(f"Text: {doc}\n Metadata: {meta}")
482- logging.info(f"Found {len(docs)} documents for query: '{query}'")
483- return "\n ---\n ".join(response)
484-
485- @tool
486- def add_document(content: str, metadata: str = "") -> str:
487- """Add a document to the vector store"""
488- import json
489- try:
490- meta = json.loads(metadata) if metadata else {}
491- except Exception:
492- meta = {"info": metadata}
493- doc = Document(text=content, metadata=meta)
494- logging.info(f"Adding document: {content[:50]}... with metadata: {meta}")
495- ids = vector_store.add_documents(documents=[doc])
496- if ids and isinstance(ids, list) and len(ids) > 0:
497- logging.info(f"Added document with ID {ids[0]}")
498- return f"Added document with ID {ids[0]}: {content[:50]}..."
499- else:
500- logging.info("Added document, but no ID was returned.")
501- return "Added document (no ID returned)"
502-
503- @tool
504- def add_machine_learning_doc() -> str:
505- """Add a synthetic machine learning basics document to the vector store."""
506- content = (
507- "Machine Learning Basics: Machine learning is a field of artificial intelligence "
508- "that uses statistical techniques to give computer systems the ability to learn "
509- "from data, without being explicitly programmed. Key concepts include supervised "
510- "learning, unsupervised learning, and reinforcement learning."
511- )
512- metadata = {"topic": "machine learning", "category": "AI", "level": "beginner"}
513- doc = Document(text=content, metadata=metadata)
514- logging.info(f"Adding synthetic ML document: {content[:50]}... with metadata: {metadata}")
515- ids = vector_store.add_documents(documents=[doc])
516- if ids and isinstance(ids, list) and len(ids) > 0:
517- logging.info(f"Added ML document with ID {ids[0]}")
518- return f"Added machine learning basics document with ID {ids[0]}"
519- else:
520- logging.info("Added ML document, but no ID was returned.")
521- return "Added machine learning basics document (no ID returned)"
522-
523- async def main():
524- # Seed the vector store with initial documents using Document class
525- documents = [
526- Document(
527- text="Gandalf: A wizard is never late, Frodo Baggins. Nor is he early; he arrives precisely when he means to.",
528- metadata={"topic": "wisdom", "location": "The Shire"}
529- ),
530- Document(
531- text="Frodo: I wish the Ring had never come to me. I wish none of this had happened.",
532- metadata={"topic": "destiny", "location": "Moria"}
533- ),
534- Document(
535- text="Sam: I can't carry it for you, but I can carry you!",
536- metadata={"topic": "friendship", "location": "Mount Doom"}
537- ),
538- ]
539- logging.info("Seeding vector store with initial documents...")
540- vector_store.add_documents(documents=documents)
541- logging.info(f"Seeded {len(documents)} initial documents.")
542-
543- agent = Agent(
544- name="VectorBot",
545- role="Vector Database Assistant",
546- goal="Help with document search and storage",
547- instructions=[
548- "Search documents in vector store",
549- "Add documents to vector store",
550- "Add a machine learning basics document",
551- "Provide relevant information from stored documents",
552- ],
553- tools=[search_documents, add_document, add_machine_learning_doc],
554- vector_store=vector_store,
555- )
556-
557- logging.info("Starting Vector Database Agent...")
558- logging.info("Adding a synthetic machine learning basics document...")
559- response = await agent.run("Add a machine learning basics document")
560- logging.info("Add Machine Learning Document Response:")
561- print(response)
562- print()
563-
564- logging.info("Searching for machine learning documents...")
565- response = await agent.run("Search for documents about machine learning")
566- logging.info("Search Response:")
567- print(response)
568-
569- if __name__ == "__main__":
570- import asyncio
571- try:
572- asyncio.run(main())
573- except KeyboardInterrupt:
574- print("\n Interrupted by user. Exiting gracefully...")
575- except Exception as e:
576- print(f"\n Error occurred: {e}")
577- ` ` `
292+ This example demonstrates how to create an agent with vector store capabilities, including logging, structured Document usage, and a tool to add a machine learning basics document.
578293
579294# # Key Concepts
580295
0 commit comments