mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-09 16:18:30 +00:00
cleanup
This commit is contained in:
@@ -48,8 +48,6 @@ class ExampleFlow(Flow):
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
#TODO: NEED TO ADD AN EXAMPLE AGENT IN HERE AS WELL.
|
|
||||||
|
|
||||||
random_city = response["choices"][0]["message"]["content"]
|
random_city = response["choices"][0]["message"]["content"]
|
||||||
# Store the city in our state
|
# Store the city in our state
|
||||||
self.state["city"] = random_city
|
self.state["city"] = random_city
|
||||||
@@ -547,6 +545,97 @@ The `third_method` and `fourth_method` listen to the output of the `second_metho
|
|||||||
|
|
||||||
When you run this Flow, the output will change based on the random boolean value generated by the `start_method`.
|
When you run this Flow, the output will change based on the random boolean value generated by the `start_method`.
|
||||||
|
|
||||||
|
## Adding LiteAgent to Flows
|
||||||
|
|
||||||
|
LiteAgents can be seamlessly integrated into your flows, providing a lightweight alternative to full Crews when you need simpler, focused task execution. Here's an example of how to use a LiteAgent within a flow to perform market research:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from typing import List, cast
|
||||||
|
from crewai_tools.tools.website_search.website_search_tool import WebsiteSearchTool
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from crewai.flow.flow import Flow, listen, start
|
||||||
|
from crewai.lite_agent import LiteAgent
|
||||||
|
|
||||||
|
# Define a structured output format
|
||||||
|
class MarketAnalysis(BaseModel):
|
||||||
|
key_trends: List[str] = Field(description="List of identified market trends")
|
||||||
|
market_size: str = Field(description="Estimated market size")
|
||||||
|
competitors: List[str] = Field(description="Major competitors in the space")
|
||||||
|
|
||||||
|
# Define flow state
|
||||||
|
class MarketResearchState(BaseModel):
|
||||||
|
product: str = ""
|
||||||
|
analysis: MarketAnalysis | None = None
|
||||||
|
|
||||||
|
class MarketResearchFlow(Flow[MarketResearchState]):
|
||||||
|
@start()
|
||||||
|
def initialize_research(self):
|
||||||
|
print(f"Starting market research for {self.state.product}")
|
||||||
|
|
||||||
|
@listen(initialize_research)
|
||||||
|
def analyze_market(self):
|
||||||
|
# Create a LiteAgent for market research
|
||||||
|
analyst = LiteAgent(
|
||||||
|
role="Market Research Analyst",
|
||||||
|
goal=f"Analyze the market for {self.state.product}",
|
||||||
|
backstory="You are an experienced market analyst with expertise in "
|
||||||
|
"identifying market trends and opportunities.",
|
||||||
|
llm="gpt-4o",
|
||||||
|
tools=[WebsiteSearchTool()],
|
||||||
|
verbose=True,
|
||||||
|
response_format=MarketAnalysis,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Define the research query
|
||||||
|
query = f"""
|
||||||
|
Research the market for {self.state.product}. Include:
|
||||||
|
1. Key market trends
|
||||||
|
2. Market size
|
||||||
|
3. Major competitors
|
||||||
|
|
||||||
|
Format your response according to the specified structure.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Execute the analysis
|
||||||
|
result = analyst.kickoff(query)
|
||||||
|
self.state.analysis = cast(MarketAnalysis, result.pydantic)
|
||||||
|
return result.pydantic
|
||||||
|
|
||||||
|
@listen(analyze_market)
|
||||||
|
def present_results(self):
|
||||||
|
analysis = self.state.analysis
|
||||||
|
if analysis is None:
|
||||||
|
print("No analysis results available")
|
||||||
|
return
|
||||||
|
|
||||||
|
print("\nMarket Analysis Results")
|
||||||
|
print("=====================")
|
||||||
|
|
||||||
|
print("\nKey Market Trends:")
|
||||||
|
for trend in analysis.key_trends:
|
||||||
|
print(f"- {trend}")
|
||||||
|
|
||||||
|
print(f"\nMarket Size: {analysis.market_size}")
|
||||||
|
|
||||||
|
print("\nMajor Competitors:")
|
||||||
|
for competitor in analysis.competitors:
|
||||||
|
print(f"- {competitor}")
|
||||||
|
|
||||||
|
# Usage example
|
||||||
|
flow = MarketResearchFlow()
|
||||||
|
result = flow.kickoff(inputs={"product": "AI-powered chatbots"})
|
||||||
|
```
|
||||||
|
|
||||||
|
This example demonstrates several key features of using LiteAgents in flows:
|
||||||
|
|
||||||
|
1. **Structured Output**: Using Pydantic models to define the expected output format (`MarketAnalysis`) ensures type safety and structured data throughout the flow.
|
||||||
|
|
||||||
|
2. **State Management**: The flow state (`MarketResearchState`) maintains context between steps and stores both inputs and outputs.
|
||||||
|
|
||||||
|
3. **Tool Integration**: LiteAgents can use tools (like `WebsiteSearchTool`) to enhance their capabilities.
|
||||||
|
|
||||||
|
If you want to learn more about LiteAgents, check out the [LiteAgent](/concepts/lite-agent) page.
|
||||||
|
|
||||||
## Adding Crews to Flows
|
## Adding Crews to Flows
|
||||||
|
|
||||||
Creating a flow with multiple crews in CrewAI is straightforward.
|
Creating a flow with multiple crews in CrewAI is straightforward.
|
||||||
|
|||||||
@@ -26,7 +26,67 @@ Think of a LiteAgent as a specialized worker that excels at individual tasks. Wh
|
|||||||
|
|
||||||
## Creating a LiteAgent
|
## Creating a LiteAgent
|
||||||
|
|
||||||
Here's a simple example of creating and using a LiteAgent in a flow:
|
Here's a simple example of creating and using a standalone LiteAgent:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from typing import List, cast
|
||||||
|
|
||||||
|
from crewai_tools.tools.website_search.website_search_tool import WebsiteSearchTool
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
from crewai.lite_agent import LiteAgent
|
||||||
|
|
||||||
|
|
||||||
|
# Define a structured output format
|
||||||
|
class MovieReview(BaseModel):
|
||||||
|
title: str = Field(description="The title of the movie")
|
||||||
|
rating: float = Field(description="Rating out of 10")
|
||||||
|
pros: List[str] = Field(description="List of positive aspects")
|
||||||
|
cons: List[str] = Field(description="List of negative aspects")
|
||||||
|
|
||||||
|
|
||||||
|
# Create a LiteAgent
|
||||||
|
critic = LiteAgent(
|
||||||
|
role="Movie Critic",
|
||||||
|
goal="Provide insightful movie reviews",
|
||||||
|
backstory="You are an experienced film critic known for balanced, thoughtful reviews.",
|
||||||
|
tools=[WebsiteSearchTool()],
|
||||||
|
verbose=True,
|
||||||
|
response_format=MovieReview,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Use the agent
|
||||||
|
query = """
|
||||||
|
Review the movie 'Inception'. Include:
|
||||||
|
1. Your rating out of 10
|
||||||
|
2. Key positive aspects
|
||||||
|
3. Areas that could be improved
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = critic.kickoff(query)
|
||||||
|
|
||||||
|
# Access the structured output
|
||||||
|
review = cast(MovieReview, result.pydantic)
|
||||||
|
print(f"\nMovie Review: {review.title}")
|
||||||
|
print(f"Rating: {review.rating}/10")
|
||||||
|
print("\nPros:")
|
||||||
|
for pro in review.pros:
|
||||||
|
print(f"- {pro}")
|
||||||
|
print("\nCons:")
|
||||||
|
for con in review.cons:
|
||||||
|
print(f"- {con}")
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
This example demonstrates the core features of a LiteAgent:
|
||||||
|
- Structured output using Pydantic models
|
||||||
|
- Tool integration with WebSearchTool
|
||||||
|
- Simple execution with `kickoff()`
|
||||||
|
- Easy access to both raw and structured results
|
||||||
|
|
||||||
|
## Using LiteAgent in a Flow
|
||||||
|
|
||||||
|
For more complex scenarios, you can integrate LiteAgents into a Flow. Here's an example of a market research flow:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ class MarketResearchState(BaseModel):
|
|||||||
analysis: MarketAnalysis | None = None
|
analysis: MarketAnalysis | None = None
|
||||||
|
|
||||||
|
|
||||||
# Create a flow class
|
|
||||||
class MarketResearchFlow(Flow[MarketResearchState]):
|
class MarketResearchFlow(Flow[MarketResearchState]):
|
||||||
@start()
|
@start()
|
||||||
def initialize_research(self):
|
def initialize_research(self):
|
||||||
|
|||||||
46
examples/lite_agent_example_2.py
Normal file
46
examples/lite_agent_example_2.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
from typing import List, cast
|
||||||
|
|
||||||
|
from crewai_tools.tools.website_search.website_search_tool import WebsiteSearchTool
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
from crewai.lite_agent import LiteAgent
|
||||||
|
|
||||||
|
|
||||||
|
# Define a structured output format
|
||||||
|
class MovieReview(BaseModel):
|
||||||
|
title: str = Field(description="The title of the movie")
|
||||||
|
rating: float = Field(description="Rating out of 10")
|
||||||
|
pros: List[str] = Field(description="List of positive aspects")
|
||||||
|
cons: List[str] = Field(description="List of negative aspects")
|
||||||
|
|
||||||
|
|
||||||
|
# Create a LiteAgent
|
||||||
|
critic = LiteAgent(
|
||||||
|
role="Movie Critic",
|
||||||
|
goal="Provide insightful movie reviews",
|
||||||
|
backstory="You are an experienced film critic known for balanced, thoughtful reviews.",
|
||||||
|
tools=[WebsiteSearchTool()],
|
||||||
|
verbose=True,
|
||||||
|
response_format=MovieReview,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Use the agent
|
||||||
|
query = """
|
||||||
|
Review the movie 'Inception'. Include:
|
||||||
|
1. Your rating out of 10
|
||||||
|
2. Key positive aspects
|
||||||
|
3. Areas that could be improved
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = critic.kickoff(query)
|
||||||
|
|
||||||
|
# Access the structured output
|
||||||
|
review = cast(MovieReview, result.pydantic)
|
||||||
|
print(f"\nMovie Review: {review.title}")
|
||||||
|
print(f"Rating: {review.rating}/10")
|
||||||
|
print("\nPros:")
|
||||||
|
for pro in review.pros:
|
||||||
|
print(f"- {pro}")
|
||||||
|
print("\nCons:")
|
||||||
|
for con in review.cons:
|
||||||
|
print(f"- {con}")
|
||||||
@@ -87,7 +87,18 @@ class CrewAgentParser:
|
|||||||
r"Action\s*\d*\s*:[\s]*(.*?)[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)"
|
r"Action\s*\d*\s*:[\s]*(.*?)[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)"
|
||||||
)
|
)
|
||||||
action_match = re.search(regex, text, re.DOTALL)
|
action_match = re.search(regex, text, re.DOTALL)
|
||||||
if action_match:
|
if includes_answer:
|
||||||
|
final_answer = text.split(FINAL_ANSWER_ACTION)[-1].strip()
|
||||||
|
# Check whether the final answer ends with triple backticks.
|
||||||
|
if final_answer.endswith("```"):
|
||||||
|
# Count occurrences of triple backticks in the final answer.
|
||||||
|
count = final_answer.count("```")
|
||||||
|
# If count is odd then it's an unmatched trailing set; remove it.
|
||||||
|
if count % 2 != 0:
|
||||||
|
final_answer = final_answer[:-3].rstrip()
|
||||||
|
return AgentFinish(thought, final_answer, text)
|
||||||
|
|
||||||
|
elif action_match:
|
||||||
if includes_answer:
|
if includes_answer:
|
||||||
raise OutputParserException(
|
raise OutputParserException(
|
||||||
f"{FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE}"
|
f"{FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE}"
|
||||||
@@ -102,17 +113,6 @@ class CrewAgentParser:
|
|||||||
|
|
||||||
return AgentAction(thought, clean_action, safe_tool_input, text)
|
return AgentAction(thought, clean_action, safe_tool_input, text)
|
||||||
|
|
||||||
elif includes_answer:
|
|
||||||
final_answer = text.split(FINAL_ANSWER_ACTION)[-1].strip()
|
|
||||||
# Check whether the final answer ends with triple backticks.
|
|
||||||
if final_answer.endswith("```"):
|
|
||||||
# Count occurrences of triple backticks in the final answer.
|
|
||||||
count = final_answer.count("```")
|
|
||||||
# If count is odd then it's an unmatched trailing set; remove it.
|
|
||||||
if count % 2 != 0:
|
|
||||||
final_answer = final_answer[:-3].rstrip()
|
|
||||||
return AgentFinish(thought, final_answer, text)
|
|
||||||
|
|
||||||
if not re.search(r"Action\s*\d*\s*:[\s]*(.*?)", text, re.DOTALL):
|
if not re.search(r"Action\s*\d*\s*:[\s]*(.*?)", text, re.DOTALL):
|
||||||
raise OutputParserException(
|
raise OutputParserException(
|
||||||
f"{MISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE}\n{self._i18n.slice('final_answer_format')}",
|
f"{MISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE}\n{self._i18n.slice('final_answer_format')}",
|
||||||
|
|||||||
@@ -395,6 +395,7 @@ class LiteAgent(BaseModel):
|
|||||||
callbacks=self._callbacks,
|
callbacks=self._callbacks,
|
||||||
printer=self._printer,
|
printer=self._printer,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Emit LLM call completed event
|
# Emit LLM call completed event
|
||||||
crewai_event_bus.emit(
|
crewai_event_bus.emit(
|
||||||
self,
|
self,
|
||||||
|
|||||||
Reference in New Issue
Block a user