Skip to content

Commit 585b9e0

Browse files
author
Pierre
authored
Merge pull request #46 from WorkflowAI/pierre-example-rag
Create 13_rag.py
2 parents e4e9145 + 1d40b5c commit 585b9e0

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed

examples/13_rag.py

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
"""
2+
This example demonstrates how to create a RAG-enabled chatbot that:
3+
1. Uses a search tool to find relevant information from a knowledge base
4+
2. Incorporates search results into its responses
5+
3. Maintains conversation context
6+
4. Provides well-structured, informative responses
7+
8+
Note: WorkflowAI does not manage the RAG implementation (yet). You need to provide your own
9+
search implementation to connect to your knowledge base. This example uses a mock search
10+
function to demonstrate the pattern.
11+
"""
12+
13+
import asyncio
14+
from enum import Enum
15+
from typing import List, Optional
16+
17+
from pydantic import BaseModel, Field
18+
19+
import workflowai
20+
from workflowai import Model, Run
21+
22+
23+
class Role(str, Enum):
24+
"""Enum representing possible message roles."""
25+
USER = "user"
26+
ASSISTANT = "assistant"
27+
28+
29+
class SearchResult(BaseModel):
30+
"""Model representing a search result from the knowledge base."""
31+
content: str = Field(
32+
description="The content of the search result",
33+
)
34+
relevance_score: float = Field(
35+
description="Score indicating how relevant this result is to the query",
36+
)
37+
38+
39+
# Simulated knowledge base search tool
40+
# ruff: noqa: ARG001
41+
async def search_faq(query: str) -> List[SearchResult]:
42+
"""
43+
Search the knowledge base for relevant information.
44+
45+
Args:
46+
query: The search query to find relevant information
47+
48+
Returns:
49+
A list of search results ordered by relevance
50+
"""
51+
# This is a mock implementation - in a real system this would query your knowledge base
52+
# The results below are hardcoded but in a real implementation would be based on the query
53+
return [
54+
SearchResult(
55+
content=(
56+
"Our standard return policy allows returns within 30 days of purchase with original "
57+
"receipt. Items must be unused and in original packaging. Once received, refunds are "
58+
"processed within 5-7 business days."
59+
),
60+
relevance_score=0.95,
61+
),
62+
SearchResult(
63+
content=(
64+
"For online purchases, customers can initiate returns through their account dashboard "
65+
"or by contacting customer support. Free return shipping labels are provided for "
66+
"defective items."
67+
),
68+
relevance_score=0.88,
69+
),
70+
SearchResult(
71+
content=(
72+
"Standard shipping takes 3-5 business days within the continental US. Express shipping "
73+
"(1-2 business days) is available for an additional fee. Free shipping on orders over $50."
74+
),
75+
relevance_score=0.82,
76+
),
77+
]
78+
79+
80+
class Message(BaseModel):
81+
"""Model representing a chat message."""
82+
role: Role
83+
content: str = Field(
84+
description="The content of the message",
85+
)
86+
87+
88+
class AssistantMessage(Message):
89+
"""Model representing a message from the assistant."""
90+
role: Role = Role.ASSISTANT
91+
content: str = ""
92+
93+
94+
class ChatbotOutput(BaseModel):
95+
"""Output model for the chatbot response."""
96+
assistant_message: AssistantMessage = Field(default_factory=AssistantMessage,
97+
description="The chatbot's response message",
98+
)
99+
100+
101+
class ChatInput(BaseModel):
102+
"""Input model containing the user's message and conversation history."""
103+
conversation_history: Optional[List[Message]] = Field(
104+
default=None,
105+
description="Previous messages in the conversation, if any",
106+
)
107+
user_message: str = Field(
108+
description="The current message from the user",
109+
)
110+
111+
112+
@workflowai.agent(
113+
id="rag-chatbot",
114+
model=Model.CLAUDE_3_5_SONNET_LATEST,
115+
# The search_faq function is passed as a tool, allowing the agent to call it during execution.
116+
# You can replace this with your own search implementation that connects to your knowledge base.
117+
# The agent will automatically handle calling the tool and incorporating the results.
118+
tools=[search_faq],
119+
)
120+
async def chat_agent(chat_input: ChatInput) -> Run[ChatbotOutput]:
121+
"""
122+
Act as a knowledgeable assistant that uses search to find and incorporate relevant information.
123+
124+
You have access to a search tool that can find relevant information from the knowledge base.
125+
Use it by calling the search_faq function with your query.
126+
127+
Guidelines:
128+
1. Understand the user's query:
129+
- Analyze the question and conversation history
130+
- Identify key concepts to search for
131+
- Consider context from previous messages
132+
133+
2. Search effectively:
134+
- Use the search_faq tool to find relevant information
135+
- Construct focused search queries
136+
- Consider multiple searches if needed
137+
- Prioritize recent and authoritative sources
138+
139+
3. Provide comprehensive responses:
140+
- Synthesize information from search results
141+
- Cite sources when appropriate
142+
- Explain complex concepts clearly
143+
- Address all parts of the query
144+
145+
4. Maintain conversation flow:
146+
- Acknowledge previous context
147+
- Be natural and engaging
148+
- Ask clarifying questions if needed
149+
- Provide smooth transitions
150+
151+
5. Format responses clearly:
152+
- Structure information logically
153+
- Use clear language
154+
- Break down complex answers
155+
- Highlight key points
156+
"""
157+
...
158+
159+
160+
async def main():
161+
# Example: Question about return policy
162+
print("\nExample: Question about return policy")
163+
print("-" * 50)
164+
165+
chat_input = ChatInput(
166+
user_message="What is your return policy? Can I return items I bought online?",
167+
)
168+
169+
run = await chat_agent(chat_input)
170+
print(run)
171+
172+
173+
if __name__ == "__main__":
174+
asyncio.run(main())

0 commit comments

Comments
 (0)