mirror of
https://github.com/crewAIInc/crewAI.git
synced 2025-12-18 13:28:31 +00:00
Compare commits
3 Commits
feat/testi
...
feature/ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0d1161699 | ||
|
|
c31c99337f | ||
|
|
1ba66f06b8 |
@@ -32,7 +32,6 @@ A crew in crewAI represents a collaborative group of agents working together to
|
||||
| **Manager Agent** _(optional)_ | `manager_agent` | `manager` sets a custom agent that will be used as a manager. |
|
||||
| **Manager Callbacks** _(optional)_ | `manager_callbacks` | `manager_callbacks` takes a list of callback handlers to be executed by the manager agent when a hierarchical process is used. |
|
||||
| **Prompt File** _(optional)_ | `prompt_file` | Path to the prompt JSON file to be used for the crew. |
|
||||
| **Planning** *(optional)* | `planning` | Adds planning ability to the Crew. When activated before each Crew iteration, all Crew data is sent to an AgentPlanner that will plan the tasks and this plan will be added to each task description.
|
||||
|
||||
!!! note "Crew Max RPM"
|
||||
The `max_rpm` attribute sets the maximum number of requests per minute the crew can perform to avoid rate limits and will override individual agents' `max_rpm` settings if you set it.
|
||||
@@ -46,12 +45,6 @@ When assembling a crew, you combine agents with complementary roles and tools, a
|
||||
```python
|
||||
from crewai import Crew, Agent, Task, Process
|
||||
from langchain_community.tools import DuckDuckGoSearchRun
|
||||
from crewai_tools import tool
|
||||
|
||||
@tool('DuckDuckGoSearch')
|
||||
def search(search_query: str):
|
||||
"""Search the web for information on a given topic"""
|
||||
return DuckDuckGoSearchRun().run(search_query)
|
||||
|
||||
# Define agents with specific roles and tools
|
||||
researcher = Agent(
|
||||
@@ -62,7 +55,7 @@ researcher = Agent(
|
||||
to the business.
|
||||
You're currently working on a project to analyze the
|
||||
trends and innovations in the space of artificial intelligence.""",
|
||||
tools=[search]
|
||||
tools=[DuckDuckGoSearchRun()]
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
@@ -220,7 +213,7 @@ These methods provide flexibility in how you manage and execute tasks within you
|
||||
### Replaying from specific task:
|
||||
You can now replay from a specific task using our cli command replay.
|
||||
|
||||
The replay feature in CrewAI allows you to replay from a specific task using the command-line interface (CLI). By running the command `crewai replay -t <task_id>`, you can specify the `task_id` for the replay process.
|
||||
The replay_from_tasks feature in CrewAI allows you to replay from a specific task using the command-line interface (CLI). By running the command `crewai replay -t <task_id>`, you can specify the `task_id` for the replay process.
|
||||
|
||||
Kickoffs will now save the latest kickoffs returned task outputs locally for you to be able to replay from.
|
||||
|
||||
|
||||
@@ -29,11 +29,6 @@ description: Leveraging memory systems in the crewAI framework to enhance agent
|
||||
When configuring a crew, you can enable and customize each memory component to suit the crew's objectives and the nature of tasks it will perform.
|
||||
By default, the memory system is disabled, and you can ensure it is active by setting `memory=True` in the crew configuration. The memory will use OpenAI Embeddings by default, but you can change it by setting `embedder` to a different model.
|
||||
|
||||
The 'embedder' only applies to **Short-Term Memory** which uses Chroma for RAG using EmbedChain package.
|
||||
The **Long-Term Memory** uses SQLLite3 to store task results. Currently, there is no way to override these storage implementations.
|
||||
The data storage files are saved into a platform specific location found using the appdirs package
|
||||
and the name of the project which can be overridden using the **CREWAI_STORAGE_DIR** environment variable.
|
||||
|
||||
### Example: Configuring Memory for a Crew
|
||||
|
||||
```python
|
||||
@@ -166,39 +161,6 @@ my_crew = Crew(
|
||||
)
|
||||
```
|
||||
|
||||
### Resetting Memory
|
||||
```sh
|
||||
crewai reset_memories [OPTIONS]
|
||||
```
|
||||
|
||||
#### Resetting Memory Options
|
||||
- **`-l, --long`**
|
||||
- **Description:** Reset LONG TERM memory.
|
||||
- **Type:** Flag (boolean)
|
||||
- **Default:** False
|
||||
|
||||
- **`-s, --short`**
|
||||
- **Description:** Reset SHORT TERM memory.
|
||||
- **Type:** Flag (boolean)
|
||||
- **Default:** False
|
||||
|
||||
- **`-e, --entities`**
|
||||
- **Description:** Reset ENTITIES memory.
|
||||
- **Type:** Flag (boolean)
|
||||
- **Default:** False
|
||||
|
||||
- **`-k, --kickoff-outputs`**
|
||||
- **Description:** Reset LATEST KICKOFF TASK OUTPUTS.
|
||||
- **Type:** Flag (boolean)
|
||||
- **Default:** False
|
||||
|
||||
- **`-a, --all`**
|
||||
- **Description:** Reset ALL memories.
|
||||
- **Type:** Flag (boolean)
|
||||
- **Default:** False
|
||||
|
||||
|
||||
|
||||
## Benefits of Using crewAI's Memory System
|
||||
- **Adaptive Learning:** Crews become more efficient over time, adapting to new information and refining their approach to tasks.
|
||||
- **Enhanced Personalization:** Memory enables agents to remember user preferences and historical interactions, leading to personalized experiences.
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
---
|
||||
title: crewAI Planning
|
||||
description: Learn how to add planning to your crewAI Crew and improve their performance.
|
||||
---
|
||||
|
||||
## Introduction
|
||||
The planning feature in CrewAI allows you to add planning capability to your crew. When enabled, before each Crew iteration, all Crew information is sent to an AgentPlanner that will plan the tasks step by step, and this plan will be added to each task description.
|
||||
|
||||
### Using the Planning Feature
|
||||
Getting started with the planning feature is very easy, the only step required is to add `planning=True` to your Crew:
|
||||
|
||||
```python
|
||||
from crewai import Crew, Agent, Task, Process
|
||||
|
||||
# Assemble your crew with planning capabilities
|
||||
my_crew = Crew(
|
||||
agents=self.agents,
|
||||
tasks=self.tasks,
|
||||
process=Process.sequential,
|
||||
planning=True,
|
||||
)
|
||||
```
|
||||
|
||||
From this point on, your crew will have planning enabled, and the tasks will be planned before each iteration.
|
||||
|
||||
### Example
|
||||
|
||||
When running the base case example, you will see something like the following output, which represents the output of the AgentPlanner responsible for creating the step-by-step logic to add to the Agents tasks.
|
||||
|
||||
```bash
|
||||
|
||||
[2024-07-15 16:49:11][INFO]: Planning the crew execution
|
||||
**Step-by-Step Plan for Task Execution**
|
||||
|
||||
**Task Number 1: Conduct a thorough research about AI LLMs**
|
||||
|
||||
**Agent:** AI LLMs Senior Data Researcher
|
||||
|
||||
**Agent Goal:** Uncover cutting-edge developments in AI LLMs
|
||||
|
||||
**Task Expected Output:** A list with 10 bullet points of the most relevant information about AI LLMs
|
||||
|
||||
**Task Tools:** None specified
|
||||
|
||||
**Agent Tools:** None specified
|
||||
|
||||
**Step-by-Step Plan:**
|
||||
|
||||
1. **Define Research Scope:**
|
||||
- Determine the specific areas of AI LLMs to focus on, such as advancements in architecture, use cases, ethical considerations, and performance metrics.
|
||||
|
||||
2. **Identify Reliable Sources:**
|
||||
- List reputable sources for AI research, including academic journals, industry reports, conferences (e.g., NeurIPS, ACL), AI research labs (e.g., OpenAI, Google AI), and online databases (e.g., IEEE Xplore, arXiv).
|
||||
|
||||
3. **Collect Data:**
|
||||
- Search for the latest papers, articles, and reports published in 2023 and early 2024.
|
||||
- Use keywords like "Large Language Models 2024", "AI LLM advancements", "AI ethics 2024", etc.
|
||||
|
||||
4. **Analyze Findings:**
|
||||
- Read and summarize the key points from each source.
|
||||
- Highlight new techniques, models, and applications introduced in the past year.
|
||||
|
||||
5. **Organize Information:**
|
||||
- Categorize the information into relevant topics (e.g., new architectures, ethical implications, real-world applications).
|
||||
- Ensure each bullet point is concise but informative.
|
||||
|
||||
6. **Create the List:**
|
||||
- Compile the 10 most relevant pieces of information into a bullet point list.
|
||||
- Review the list to ensure clarity and relevance.
|
||||
|
||||
**Expected Output:**
|
||||
A list with 10 bullet points of the most relevant information about AI LLMs.
|
||||
|
||||
---
|
||||
|
||||
**Task Number 2: Review the context you got and expand each topic into a full section for a report**
|
||||
|
||||
**Agent:** AI LLMs Reporting Analyst
|
||||
|
||||
**Agent Goal:** Create detailed reports based on AI LLMs data analysis and research findings
|
||||
|
||||
**Task Expected Output:** A fully fledge report with the main topics, each with a full section of information. Formatted as markdown without '```'
|
||||
|
||||
**Task Tools:** None specified
|
||||
|
||||
**Agent Tools:** None specified
|
||||
|
||||
**Step-by-Step Plan:**
|
||||
|
||||
1. **Review the Bullet Points:**
|
||||
- Carefully read through the list of 10 bullet points provided by the AI LLMs Senior Data Researcher.
|
||||
|
||||
2. **Outline the Report:**
|
||||
- Create an outline with each bullet point as a main section heading.
|
||||
- Plan sub-sections under each main heading to cover different aspects of the topic.
|
||||
|
||||
3. **Research Further Details:**
|
||||
- For each bullet point, conduct additional research if necessary to gather more detailed information.
|
||||
- Look for case studies, examples, and statistical data to support each section.
|
||||
|
||||
4. **Write Detailed Sections:**
|
||||
- Expand each bullet point into a comprehensive section.
|
||||
- Ensure each section includes an introduction, detailed explanation, examples, and a conclusion.
|
||||
- Use markdown formatting for headings, subheadings, lists, and emphasis.
|
||||
|
||||
5. **Review and Edit:**
|
||||
- Proofread the report for clarity, coherence, and correctness.
|
||||
- Make sure the report flows logically from one section to the next.
|
||||
- Format the report according to markdown standards.
|
||||
|
||||
6. **Finalize the Report:**
|
||||
- Ensure the report is complete with all sections expanded and detailed.
|
||||
- Double-check formatting and make any necessary adjustments.
|
||||
|
||||
**Expected Output:**
|
||||
A fully-fledged report with the main topics, each with a full section of information. Formatted as markdown without '```'.
|
||||
|
||||
---
|
||||
```
|
||||
@@ -1,41 +0,0 @@
|
||||
---
|
||||
title: crewAI Testing
|
||||
description: Learn how to test your crewAI Crew and evaluate their performance.
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
Testing is a crucial part of the development process, and it is essential to ensure that your crew is performing as expected. And with crewAI, you can easily test your crew and evaluate its performance using the built-in testing capabilities.
|
||||
|
||||
### Using the Testing Feature
|
||||
|
||||
We added the CLI command `crewai test` to make it easy to test your crew. This command will run your crew for a specified number of iterations and provide detailed performance metrics.
|
||||
The parameters are `n_iterations` and `model` which are optional and default to 2 and `gpt-4o-mini` respectively. For now the only provider available is OpenAI.
|
||||
|
||||
```bash
|
||||
crewai test
|
||||
```
|
||||
|
||||
If you want to run more iterations or use a different model, you can specify the parameters like this:
|
||||
|
||||
```bash
|
||||
crewai test --n_iterations 5 --model gpt-4o
|
||||
```
|
||||
|
||||
What happens when you run the `crewai test` command is that the crew will be executed for the specified number of iterations, and the performance metrics will be displayed at the end of the run.
|
||||
|
||||
A table of scores at the end will show the performance of the crew in terms of the following metrics:
|
||||
```
|
||||
Task Scores
|
||||
(1-10 Higher is better)
|
||||
┏━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━┓
|
||||
┃ Tasks/Crew ┃ Run 1 ┃ Run 2 ┃ Avg. Total ┃
|
||||
┡━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━┩
|
||||
│ Task 1 │ 10.0 │ 9.0 │ 9.5 │
|
||||
│ Task 2 │ 9.0 │ 9.0 │ 9.0 │
|
||||
│ Crew │ 9.5 │ 9.0 │ 9.2 │
|
||||
└────────────┴───────┴───────┴────────────┘
|
||||
```
|
||||
|
||||
The example above shows the test results for two runs of the crew with two tasks, with the average total score for each task and the crew as a whole.
|
||||
|
||||
@@ -100,24 +100,16 @@ Here is a list of the available tools and their descriptions:
|
||||
|
||||
| Tool | Description |
|
||||
| :-------------------------- | :-------------------------------------------------------------------------------------------- |
|
||||
| **BrowserbaseLoadTool** | A tool for interacting with and extracting data from web browsers. |
|
||||
| **CodeDocsSearchTool** | A RAG tool optimized for searching through code documentation and related technical documents. |
|
||||
| **CodeInterpreterTool** | A tool for interpreting python code. |
|
||||
| **ComposioTool** | Enables use of Composio tools. |
|
||||
| **CSVSearchTool** | A RAG tool designed for searching within CSV files, tailored to handle structured data. |
|
||||
| **DirectorySearchTool** | A RAG tool for searching within directories, useful for navigating through file systems. |
|
||||
| **DOCXSearchTool** | A RAG tool aimed at searching within DOCX documents, ideal for processing Word files. |
|
||||
| **DirectoryReadTool** | Facilitates reading and processing of directory structures and their contents. |
|
||||
| **EXASearchTool** | A tool designed for performing exhaustive searches across various data sources. |
|
||||
| **FileReadTool** | Enables reading and extracting data from files, supporting various file formats. |
|
||||
| **FirecrawlSearchTool** | A tool to search webpages using Firecrawl and return the results. |
|
||||
| **FirecrawlCrawlWebsiteTool** | A tool for crawling webpages using Firecrawl. |
|
||||
| **FirecrawlScrapeWebsiteTool** | A tool for scraping webpages url using Firecrawl and returning its contents. |
|
||||
| **GithubSearchTool** | A RAG tool for searching within GitHub repositories, useful for code and documentation search.|
|
||||
| **SerperDevTool** | A specialized tool for development purposes, with specific functionalities under development. |
|
||||
| **TXTSearchTool** | A RAG tool focused on searching within text (.txt) files, suitable for unstructured data. |
|
||||
| **JSONSearchTool** | A RAG tool designed for searching within JSON files, catering to structured data handling. |
|
||||
| **LlamaIndexTool** | Enables the use of LlamaIndex tools. |
|
||||
| **MDXSearchTool** | A RAG tool tailored for searching within Markdown (MDX) files, useful for documentation. |
|
||||
| **PDFSearchTool** | A RAG tool aimed at searching within PDF documents, ideal for processing scanned documents. |
|
||||
| **PGSearchTool** | A RAG tool optimized for searching within PostgreSQL databases, suitable for database queries. |
|
||||
@@ -128,6 +120,8 @@ Here is a list of the available tools and their descriptions:
|
||||
| **XMLSearchTool** | A RAG tool designed for searching within XML files, suitable for structured data formats. |
|
||||
| **YoutubeChannelSearchTool**| A RAG tool for searching within YouTube channels, useful for video content analysis. |
|
||||
| **YoutubeVideoSearchTool** | A RAG tool aimed at searching within YouTube videos, ideal for video data extraction. |
|
||||
| **BrowserbaseTool** | A tool for interacting with and extracting data from web browsers. |
|
||||
| **ExaSearchTool** | A tool designed for performing exhaustive searches across various data sources. |
|
||||
|
||||
## Creating your own Tools
|
||||
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
---
|
||||
title: Conditional Tasks
|
||||
description: Learn how to use conditional tasks in a crewAI kickoff
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
Conditional Tasks in crewAI allow for dynamic workflow adaptation based on the outcomes of previous tasks. This powerful feature enables crews to make decisions and execute tasks selectively, enhancing the flexibility and efficiency of your AI-driven processes.
|
||||
|
||||
```python
|
||||
from typing import List
|
||||
|
||||
from pydantic import BaseModel
|
||||
from crewai import Agent, Crew
|
||||
from crewai.tasks.conditional_task import ConditionalTask
|
||||
from crewai.tasks.task_output import TaskOutput
|
||||
from crewai.task import Task
|
||||
from crewai_tools import SerperDevTool
|
||||
|
||||
|
||||
# Define a condition function for the conditional task
|
||||
# if false task will be skipped, true, then execute task
|
||||
def is_data_missing(output: TaskOutput) -> bool:
|
||||
return len(output.pydantic.events) < 10: # this will skip this task
|
||||
|
||||
# Define the agents
|
||||
data_fetcher_agent = Agent(
|
||||
role="Data Fetcher",
|
||||
goal="Fetch data online using Serper tool",
|
||||
backstory="Backstory 1",
|
||||
verbose=True,
|
||||
tools=[SerperDevTool()],
|
||||
)
|
||||
|
||||
data_processor_agent = Agent(
|
||||
role="Data Processor",
|
||||
goal="Process fetched data",
|
||||
backstory="Backstory 2",
|
||||
verbose=True,
|
||||
)
|
||||
|
||||
summary_generator_agent = Agent(
|
||||
role="Summary Generator",
|
||||
goal="Generate summary from fetched data",
|
||||
backstory="Backstory 3",
|
||||
verbose=True,
|
||||
)
|
||||
|
||||
|
||||
class EventOutput(BaseModel):
|
||||
events: List[str]
|
||||
|
||||
|
||||
task1 = Task(
|
||||
description="Fetch data about events in San Francisco using Serper tool",
|
||||
expected_output="List of 10 things to do in SF this week",
|
||||
agent=data_fetcher_agent,
|
||||
output_pydantic=EventOutput,
|
||||
)
|
||||
|
||||
conditional_task = ConditionalTask(
|
||||
description="""
|
||||
Check if data is missing. If we have less than 10 events,
|
||||
fetch more events using Serper tool so that
|
||||
we have a total of 10 events in SF this week..
|
||||
""",
|
||||
expected_output="List of 10 Things to do in SF this week ",
|
||||
condition=is_data_missing,
|
||||
agent=data_processor_agent,
|
||||
)
|
||||
|
||||
task3 = Task(
|
||||
description="Generate summary of events in San Francisco from fetched data",
|
||||
expected_output="summary_generated",
|
||||
agent=summary_generator_agent,
|
||||
)
|
||||
|
||||
# Create a crew with the tasks
|
||||
crew = Crew(
|
||||
agents=[data_fetcher_agent, data_processor_agent, summary_generator_agent],
|
||||
tasks=[task1, conditional_task, task3],
|
||||
verbose=2,
|
||||
)
|
||||
|
||||
result = crew.kickoff()
|
||||
print("results", result)
|
||||
```
|
||||
@@ -21,16 +21,14 @@ Define your agents with distinct roles, backstories, and enhanced capabilities.
|
||||
import os
|
||||
from langchain.llms import OpenAI
|
||||
from crewai import Agent
|
||||
from crewai_tools import SerperDevTool, BrowserbaseLoadTool, EXASearchTool
|
||||
from crewai_tools import SerperDevTool, BrowserbaseTool, ExaSearchTool
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "Your OpenAI Key"
|
||||
os.environ["SERPER_API_KEY"] = "Your Serper Key"
|
||||
os.environ["BROWSERBASE_API_KEY"] = "Your BrowserBase Key"
|
||||
os.environ["BROWSERBASE_PROJECT_ID"] = "Your BrowserBase Project Id"
|
||||
|
||||
search_tool = SerperDevTool()
|
||||
browser_tool = BrowserbaseLoadTool()
|
||||
exa_search_tool = EXASearchTool()
|
||||
browser_tool = BrowserbaseTool()
|
||||
exa_search_tool = ExaSearchTool()
|
||||
|
||||
# Creating a senior researcher agent with advanced configurations
|
||||
researcher = Agent(
|
||||
|
||||
@@ -36,14 +36,14 @@ To replay from a task programmatically, use the following steps:
|
||||
2. Execute the replay command within a try-except block to handle potential errors.
|
||||
|
||||
```python
|
||||
def replay():
|
||||
def replay_from_task():
|
||||
"""
|
||||
Replay the crew execution from a specific task.
|
||||
"""
|
||||
task_id = '<task_id>'
|
||||
inputs = {"topic": "CrewAI Training"} # this is optional, you can pass in the inputs you want to replay otherwise uses the previous kickoffs inputs
|
||||
try:
|
||||
YourCrewName_Crew().crew().replay(task_id=task_id, inputs=inputs)
|
||||
YourCrewName_Crew().crew().replay_from_task(task_id=task_id, inputs=inputs)
|
||||
|
||||
except Exception as e:
|
||||
raise Exception(f"An error occurred while replaying the crew: {e}")
|
||||
@@ -9,7 +9,7 @@ Welcome to the ultimate guide for starting a new CrewAI project. This document w
|
||||
|
||||
## Prerequisites
|
||||
|
||||
We assume you have already installed CrewAI. If not, please refer to the [installation guide](https://docs.crewai.com/how-to/Installing-CrewAI/) to install CrewAI and its dependencies.
|
||||
We assume you have already installed CrewAI. If not, please refer to the [installation guide](how-to/Installing-CrewAI.md) to install CrewAI and its dependencies.
|
||||
|
||||
## Creating a New Project
|
||||
|
||||
|
||||
@@ -43,11 +43,6 @@ Cutting-edge framework for orchestrating role-playing, autonomous AI agents. By
|
||||
Memory
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="./core-concepts/Planning">
|
||||
Planning
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="width:30%">
|
||||
@@ -123,11 +118,6 @@ Cutting-edge framework for orchestrating role-playing, autonomous AI agents. By
|
||||
Replay from a Task
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="./how-to/Conditional-Tasks">
|
||||
Conditional Tasks
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="./how-to/AgentOps-Observability">
|
||||
Agent Monitoring with AgentOps
|
||||
|
||||
@@ -128,8 +128,6 @@ nav:
|
||||
- Collaboration: 'core-concepts/Collaboration.md'
|
||||
- Training: 'core-concepts/Training-Crew.md'
|
||||
- Memory: 'core-concepts/Memory.md'
|
||||
- Planning: 'core-concepts/Planning.md'
|
||||
- Testing: 'core-concepts/Testing.md'
|
||||
- Using LangChain Tools: 'core-concepts/Using-LangChain-Tools.md'
|
||||
- Using LlamaIndex Tools: 'core-concepts/Using-LlamaIndex-Tools.md'
|
||||
- How to Guides:
|
||||
@@ -148,7 +146,6 @@ nav:
|
||||
- Kickoff a Crew Asynchronously: 'how-to/Kickoff-async.md'
|
||||
- Kickoff a Crew for a List: 'how-to/Kickoff-for-each.md'
|
||||
- Replay from a specific task from a kickoff: 'how-to/Replay-tasks-from-latest-Crew-Kickoff.md'
|
||||
- Conditional Tasks: 'how-to/Conditional-Tasks.md'
|
||||
- Agent Monitoring with AgentOps: 'how-to/AgentOps-Observability.md'
|
||||
- Agent Monitoring with LangTrace: 'how-to/Langtrace-Observability.md'
|
||||
- Tools Docs:
|
||||
|
||||
1201
poetry.lock
generated
1201
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "crewai"
|
||||
version = "0.41.1"
|
||||
version = "0.36.0"
|
||||
description = "Cutting-edge framework for orchestrating role-playing, autonomous AI agents. By fostering collaborative intelligence, CrewAI empowers agents to work together seamlessly, tackling complex tasks."
|
||||
authors = ["Joao Moura <joao@crewai.com>"]
|
||||
readme = "README.md"
|
||||
@@ -21,12 +21,12 @@ opentelemetry-sdk = "^1.22.0"
|
||||
opentelemetry-exporter-otlp-proto-http = "^1.22.0"
|
||||
instructor = "1.3.3"
|
||||
regex = "^2023.12.25"
|
||||
crewai-tools = { version = "^0.4.26", optional = true }
|
||||
crewai-tools = { version = "^0.4.8", optional = true }
|
||||
click = "^8.1.7"
|
||||
python-dotenv = "^1.0.0"
|
||||
appdirs = "^1.4.4"
|
||||
jsonref = "^1.1.0"
|
||||
agentops = { version = "^0.3.0", optional = true }
|
||||
agentops = { version = "^0.1.9", optional = true }
|
||||
embedchain = "^0.1.114"
|
||||
json-repair = "^0.25.2"
|
||||
|
||||
@@ -46,7 +46,7 @@ mkdocs-material = { extras = ["imaging"], version = "^9.5.7" }
|
||||
mkdocs-material-extensions = "^1.3.1"
|
||||
pillow = "^10.2.0"
|
||||
cairosvg = "^2.7.1"
|
||||
crewai-tools = "^0.4.26"
|
||||
crewai-tools = "^0.4.8"
|
||||
|
||||
[tool.poetry.group.test.dependencies]
|
||||
pytest = "^8.0.0"
|
||||
|
||||
@@ -181,6 +181,7 @@ class Agent(BaseAgent):
|
||||
self.agent_executor.tools = parsed_tools
|
||||
self.agent_executor.task = task
|
||||
|
||||
# TODO: COMPARE WITH ARGS AND WITHOUT ARGS
|
||||
self.agent_executor.tools_description = self._render_text_description_and_args(
|
||||
parsed_tools
|
||||
)
|
||||
@@ -203,7 +204,7 @@ class Agent(BaseAgent):
|
||||
self._times_executed += 1
|
||||
if self._times_executed > self.max_retry_limit:
|
||||
raise e
|
||||
result = self.execute_task(task, context, tools)
|
||||
self.execute_task(task, context, tools)
|
||||
|
||||
if self.max_rpm:
|
||||
self._rpm_controller.stop_rpm_counter()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import uuid
|
||||
from abc import ABC, abstractmethod
|
||||
from copy import copy as shallow_copy
|
||||
from hashlib import md5
|
||||
from typing import Any, Dict, List, Optional, TypeVar
|
||||
|
||||
from pydantic import (
|
||||
@@ -163,11 +162,6 @@ class BaseAgent(ABC, BaseModel):
|
||||
self._token_process = TokenProcess()
|
||||
return self
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
source = [self.role, self.goal, self.backstory]
|
||||
return md5("|".join(source).encode()).hexdigest()
|
||||
|
||||
@abstractmethod
|
||||
def execute_task(
|
||||
self,
|
||||
|
||||
@@ -242,8 +242,6 @@ class CrewAgentExecutor(AgentExecutor, CrewAgentExecutorMixin):
|
||||
else:
|
||||
if tool_calling.tool_name.casefold().strip() in [
|
||||
name.casefold().strip() for name in name_to_tool_map
|
||||
] or tool_calling.tool_name.casefold().replace("_", " ") in [
|
||||
name.casefold().strip() for name in name_to_tool_map
|
||||
]:
|
||||
observation = tool_usage.use(tool_calling, agent_action.log)
|
||||
else:
|
||||
|
||||
@@ -5,11 +5,10 @@ from crewai.memory.storage.kickoff_task_outputs_storage import (
|
||||
KickoffTaskOutputsSQLiteStorage,
|
||||
)
|
||||
|
||||
|
||||
from .create_crew import create_crew
|
||||
from .replay_from_task import replay_task_command
|
||||
from .reset_memories_command import reset_memories_command
|
||||
from .test_crew import test_crew
|
||||
from .train_crew import train_crew
|
||||
from .replay_from_task import replay_task_command
|
||||
|
||||
|
||||
@click.group()
|
||||
@@ -100,52 +99,5 @@ def log_tasks_outputs() -> None:
|
||||
click.echo(f"An error occurred while logging task outputs: {e}", err=True)
|
||||
|
||||
|
||||
@crewai.command()
|
||||
@click.option("-l", "--long", is_flag=True, help="Reset LONG TERM memory")
|
||||
@click.option("-s", "--short", is_flag=True, help="Reset SHORT TERM memory")
|
||||
@click.option("-e", "--entities", is_flag=True, help="Reset ENTITIES memory")
|
||||
@click.option(
|
||||
"-k",
|
||||
"--kickoff-outputs",
|
||||
is_flag=True,
|
||||
help="Reset LATEST KICKOFF TASK OUTPUTS",
|
||||
)
|
||||
@click.option("-a", "--all", is_flag=True, help="Reset ALL memories")
|
||||
def reset_memories(long, short, entities, kickoff_outputs, all):
|
||||
"""
|
||||
Reset the crew memories (long, short, entity, latest_crew_kickoff_ouputs). This will delete all the data saved.
|
||||
"""
|
||||
try:
|
||||
if not all and not (long or short or entities or kickoff_outputs):
|
||||
click.echo(
|
||||
"Please specify at least one memory type to reset using the appropriate flags."
|
||||
)
|
||||
return
|
||||
reset_memories_command(long, short, entities, kickoff_outputs, all)
|
||||
except Exception as e:
|
||||
click.echo(f"An error occurred while resetting memories: {e}", err=True)
|
||||
|
||||
|
||||
@crewai.command()
|
||||
@click.option(
|
||||
"-n",
|
||||
"--n_iterations",
|
||||
type=int,
|
||||
default=3,
|
||||
help="Number of iterations to Test the crew",
|
||||
)
|
||||
@click.option(
|
||||
"-m",
|
||||
"--model",
|
||||
type=str,
|
||||
default="gpt-4o-mini",
|
||||
help="LLM Model to run the tests on the Crew. For now only accepting only OpenAI models.",
|
||||
)
|
||||
def test(n_iterations: int, model: str):
|
||||
"""Test the crew and evaluate the results."""
|
||||
click.echo(f"Testing the crew for {n_iterations} iterations with model {model}")
|
||||
test_crew(n_iterations, model)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
crewai()
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
import subprocess
|
||||
import click
|
||||
|
||||
from crewai.memory.entity.entity_memory import EntityMemory
|
||||
from crewai.memory.long_term.long_term_memory import LongTermMemory
|
||||
from crewai.memory.short_term.short_term_memory import ShortTermMemory
|
||||
from crewai.utilities.task_output_storage_handler import TaskOutputStorageHandler
|
||||
|
||||
|
||||
def reset_memories_command(long, short, entity, kickoff_outputs, all) -> None:
|
||||
"""
|
||||
Replay the crew execution from a specific task.
|
||||
|
||||
Args:
|
||||
task_id (str): The ID of the task to replay from.
|
||||
"""
|
||||
|
||||
try:
|
||||
if all:
|
||||
ShortTermMemory().reset()
|
||||
EntityMemory().reset()
|
||||
LongTermMemory().reset()
|
||||
TaskOutputStorageHandler().reset()
|
||||
click.echo("All memories have been reset.")
|
||||
else:
|
||||
if long:
|
||||
LongTermMemory().reset()
|
||||
click.echo("Long term memory has been reset.")
|
||||
|
||||
if short:
|
||||
ShortTermMemory().reset()
|
||||
click.echo("Short term memory has been reset.")
|
||||
if entity:
|
||||
EntityMemory().reset()
|
||||
click.echo("Entity memory has been reset.")
|
||||
if kickoff_outputs:
|
||||
TaskOutputStorageHandler().reset()
|
||||
click.echo("Latest Kickoff outputs stored has been reset.")
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
click.echo(f"An error occurred while resetting the memories: {e}", err=True)
|
||||
click.echo(e.output, err=True)
|
||||
|
||||
except Exception as e:
|
||||
click.echo(f"An unexpected error occurred: {e}", err=True)
|
||||
@@ -2,15 +2,9 @@
|
||||
import sys
|
||||
from {{folder_name}}.crew import {{crew_name}}Crew
|
||||
|
||||
# This main file is intended to be a way for your to run your
|
||||
# crew locally, so refrain from adding necessary logic into this file.
|
||||
# Replace with inputs you want to test with, it will automatically
|
||||
# interpolate any tasks and agents information
|
||||
|
||||
def run():
|
||||
"""
|
||||
Run the crew.
|
||||
"""
|
||||
# Replace with your inputs, it will automatically interpolate any tasks and agents information
|
||||
inputs = {
|
||||
'topic': 'AI LLMs'
|
||||
}
|
||||
@@ -21,34 +15,19 @@ def train():
|
||||
"""
|
||||
Train the crew for a given number of iterations.
|
||||
"""
|
||||
inputs = {
|
||||
"topic": "AI LLMs"
|
||||
}
|
||||
inputs = {"topic": "AI LLMs"}
|
||||
try:
|
||||
{{crew_name}}Crew().crew().train(n_iterations=int(sys.argv[1]), inputs=inputs)
|
||||
|
||||
except Exception as e:
|
||||
raise Exception(f"An error occurred while training the crew: {e}")
|
||||
|
||||
def replay():
|
||||
def replay_from_task():
|
||||
"""
|
||||
Replay the crew execution from a specific task.
|
||||
"""
|
||||
try:
|
||||
{{crew_name}}Crew().crew().replay(task_id=sys.argv[1])
|
||||
|
||||
except Exception as e:
|
||||
raise Exception(f"An error occurred while replaying the crew: {e}")
|
||||
|
||||
def test():
|
||||
"""
|
||||
Test the crew execution and returns the results.
|
||||
"""
|
||||
inputs = {
|
||||
"topic": "AI LLMs"
|
||||
}
|
||||
try:
|
||||
{{crew_name}}Crew().crew().test(n_iterations=int(sys.argv[1]), openai_model_name=sys.argv[2], inputs=inputs)
|
||||
{{crew_name}}Crew().crew().replay_from_task(task_id=sys.argv[1])
|
||||
|
||||
except Exception as e:
|
||||
raise Exception(f"An error occurred while replaying the crew: {e}")
|
||||
|
||||
@@ -6,13 +6,12 @@ authors = ["Your Name <you@example.com>"]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.10,<=3.13"
|
||||
crewai = { extras = ["tools"], version = "^0.41.1" }
|
||||
crewai = { extras = ["tools"], version = "^0.35.8" }
|
||||
|
||||
[tool.poetry.scripts]
|
||||
{{folder_name}} = "{{folder_name}}.main:run"
|
||||
train = "{{folder_name}}.main:train"
|
||||
replay = "{{folder_name}}.main:replay"
|
||||
test = "{{folder_name}}.main:test"
|
||||
replay = "{{folder_name}}.main:replay_from_task"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import subprocess
|
||||
|
||||
import click
|
||||
|
||||
|
||||
def test_crew(n_iterations: int, model: str) -> None:
|
||||
"""
|
||||
Test the crew by running a command in the Poetry environment.
|
||||
|
||||
Args:
|
||||
n_iterations (int): The number of iterations to test the crew.
|
||||
model (str): The model to test the crew with.
|
||||
"""
|
||||
command = ["poetry", "run", "test", str(n_iterations), model]
|
||||
|
||||
try:
|
||||
if n_iterations <= 0:
|
||||
raise ValueError("The number of iterations must be a positive integer.")
|
||||
|
||||
result = subprocess.run(command, capture_output=False, text=True, check=True)
|
||||
|
||||
if result.stderr:
|
||||
click.echo(result.stderr, err=True)
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
click.echo(f"An error occurred while testing the crew: {e}", err=True)
|
||||
click.echo(e.output, err=True)
|
||||
|
||||
except Exception as e:
|
||||
click.echo(f"An unexpected error occurred: {e}", err=True)
|
||||
@@ -2,7 +2,6 @@ import asyncio
|
||||
import json
|
||||
import uuid
|
||||
from concurrent.futures import Future
|
||||
from hashlib import md5
|
||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||
|
||||
from langchain_core.callbacks import BaseCallbackHandler
|
||||
@@ -28,7 +27,6 @@ from crewai.memory.long_term.long_term_memory import LongTermMemory
|
||||
from crewai.memory.short_term.short_term_memory import ShortTermMemory
|
||||
from crewai.process import Process
|
||||
from crewai.task import Task
|
||||
from crewai.tasks.conditional_task import ConditionalTask
|
||||
from crewai.tasks.task_output import TaskOutput
|
||||
from crewai.telemetry import Telemetry
|
||||
from crewai.tools.agent_tools import AgentTools
|
||||
@@ -37,14 +35,13 @@ from crewai.utilities.constants import (
|
||||
TRAINED_AGENTS_DATA_FILE,
|
||||
TRAINING_DATA_FILE,
|
||||
)
|
||||
from crewai.utilities.evaluators.crew_evaluator_handler import CrewEvaluator
|
||||
from crewai.utilities.evaluators.task_evaluator import TaskEvaluator
|
||||
from crewai.utilities.task_output_storage_handler import TaskOutputStorageHandler
|
||||
|
||||
from crewai.utilities.formatter import (
|
||||
aggregate_raw_outputs_from_task_outputs,
|
||||
aggregate_raw_outputs_from_tasks,
|
||||
)
|
||||
from crewai.utilities.planning_handler import CrewPlanner
|
||||
from crewai.utilities.task_output_storage_handler import TaskOutputStorageHandler
|
||||
from crewai.utilities.training_handler import CrewTrainingHandler
|
||||
|
||||
try:
|
||||
@@ -75,7 +72,6 @@ class Crew(BaseModel):
|
||||
task_callback: Callback to be executed after each task for every agents execution.
|
||||
step_callback: Callback to be executed after each step for every agents execution.
|
||||
share_crew: Whether you want to share the complete crew information and execution with crewAI to make the library better, and allow us to train models.
|
||||
planning: Plan the crew execution and add the plan to the crew.
|
||||
"""
|
||||
|
||||
__hash__ = object.__hash__ # type: ignore
|
||||
@@ -151,10 +147,6 @@ class Crew(BaseModel):
|
||||
default=False,
|
||||
description="output_log_file",
|
||||
)
|
||||
planning: Optional[bool] = Field(
|
||||
default=False,
|
||||
description="Plan the crew execution and add the plan to the crew.",
|
||||
)
|
||||
task_execution_output_json_files: Optional[List[str]] = Field(
|
||||
default=None,
|
||||
description="List of file paths for task execution JSON files.",
|
||||
@@ -302,29 +294,6 @@ class Crew(BaseModel):
|
||||
|
||||
return self
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_first_task(self) -> "Crew":
|
||||
"""Ensure the first task is not a ConditionalTask."""
|
||||
if self.tasks and isinstance(self.tasks[0], ConditionalTask):
|
||||
raise PydanticCustomError(
|
||||
"invalid_first_task",
|
||||
"The first task cannot be a ConditionalTask.",
|
||||
{},
|
||||
)
|
||||
return self
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_async_tasks_not_async(self) -> "Crew":
|
||||
"""Ensure that ConditionalTask is not async."""
|
||||
for task in self.tasks:
|
||||
if task.async_execution and isinstance(task, ConditionalTask):
|
||||
raise PydanticCustomError(
|
||||
"invalid_async_conditional_task",
|
||||
f"Conditional Task: {task.description} , cannot be executed asynchronously.", # type: ignore # Argument of type "str" cannot be assigned to parameter "message_template" of type "LiteralString"
|
||||
{},
|
||||
)
|
||||
return self
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_async_task_cannot_include_sequential_async_tasks_in_context(self):
|
||||
"""
|
||||
@@ -361,13 +330,6 @@ class Crew(BaseModel):
|
||||
)
|
||||
return self
|
||||
|
||||
@property
|
||||
def key(self) -> str:
|
||||
source = [agent.key for agent in self.agents] + [
|
||||
task.key for task in self.tasks
|
||||
]
|
||||
return md5("|".join(source).encode()).hexdigest()
|
||||
|
||||
def _setup_from_config(self):
|
||||
assert self.config is not None, "Config should not be None."
|
||||
|
||||
@@ -460,9 +422,6 @@ class Crew(BaseModel):
|
||||
|
||||
agent.create_agent_executor()
|
||||
|
||||
if self.planning:
|
||||
self._handle_crew_planning()
|
||||
|
||||
metrics = []
|
||||
|
||||
if self.process == Process.sequential:
|
||||
@@ -557,19 +516,6 @@ class Crew(BaseModel):
|
||||
self._task_output_handler.reset()
|
||||
return results
|
||||
|
||||
def _handle_crew_planning(self):
|
||||
"""Handles the Crew planning."""
|
||||
self._logger.log("info", "Planning the crew execution")
|
||||
result = CrewPlanner(self.tasks)._handle_crew_planning()
|
||||
|
||||
if result is not None and hasattr(result, "list_of_plans_per_task"):
|
||||
for task, step_plan in zip(self.tasks, result.list_of_plans_per_task):
|
||||
task.description += step_plan
|
||||
else:
|
||||
self._logger.log(
|
||||
"info", "Something went wrong with the planning process of the Crew"
|
||||
)
|
||||
|
||||
def _store_execution_log(
|
||||
self,
|
||||
task: Task,
|
||||
@@ -658,21 +604,16 @@ class Crew(BaseModel):
|
||||
last_sync_output = task.output
|
||||
continue
|
||||
|
||||
agent_to_use = self._get_agent_to_use(task, manager)
|
||||
self._prepare_task(task, manager)
|
||||
if self.process == Process.hierarchical:
|
||||
agent_to_use = manager
|
||||
else:
|
||||
agent_to_use = task.agent
|
||||
if agent_to_use is None:
|
||||
raise ValueError(
|
||||
f"No agent available for task: {task.description}. Ensure that either the task has an assigned agent or a manager agent is provided."
|
||||
)
|
||||
|
||||
self._prepare_agent_tools(task, manager)
|
||||
self._log_task_start(task, agent_to_use.role)
|
||||
|
||||
if isinstance(task, ConditionalTask):
|
||||
skipped_task_output = self._handle_conditional_task(
|
||||
task, task_outputs, futures, task_index, was_replayed
|
||||
)
|
||||
if skipped_task_output:
|
||||
continue
|
||||
self._log_task_start(task, agent_to_use)
|
||||
|
||||
if task.async_execution:
|
||||
context = self._get_context(
|
||||
@@ -686,7 +627,9 @@ class Crew(BaseModel):
|
||||
futures.append((task, future, task_index))
|
||||
else:
|
||||
if futures:
|
||||
task_outputs = self._process_async_tasks(futures, was_replayed)
|
||||
task_outputs.extend(
|
||||
self._process_async_tasks(futures, was_replayed)
|
||||
)
|
||||
futures.clear()
|
||||
|
||||
context = self._get_context(task, task_outputs)
|
||||
@@ -704,48 +647,12 @@ class Crew(BaseModel):
|
||||
|
||||
return self._create_crew_output(task_outputs)
|
||||
|
||||
def _handle_conditional_task(
|
||||
self,
|
||||
task: ConditionalTask,
|
||||
task_outputs: List[TaskOutput],
|
||||
futures: List[Tuple[Task, Future[TaskOutput], int]],
|
||||
task_index: int,
|
||||
was_replayed: bool,
|
||||
) -> Optional[TaskOutput]:
|
||||
if futures:
|
||||
task_outputs = self._process_async_tasks(futures, was_replayed)
|
||||
futures.clear()
|
||||
|
||||
previous_output = task_outputs[task_index - 1] if task_outputs else None
|
||||
if previous_output is not None and not task.should_execute(previous_output):
|
||||
self._logger.log(
|
||||
"debug",
|
||||
f"Skipping conditional task: {task.description}",
|
||||
color="yellow",
|
||||
)
|
||||
skipped_task_output = task.get_skipped_task_output()
|
||||
|
||||
if not was_replayed:
|
||||
self._store_execution_log(task, skipped_task_output, task_index)
|
||||
return skipped_task_output
|
||||
return None
|
||||
|
||||
def _prepare_agent_tools(self, task: Task, manager: Optional[BaseAgent]):
|
||||
def _prepare_task(self, task: Task, manager: Optional[BaseAgent]):
|
||||
if self.process == Process.hierarchical:
|
||||
if manager:
|
||||
self._update_manager_tools(task, manager)
|
||||
else:
|
||||
raise ValueError("Manager agent is required for hierarchical process.")
|
||||
elif task.agent and task.agent.allow_delegation:
|
||||
self._add_delegation_tools(task)
|
||||
|
||||
def _get_agent_to_use(
|
||||
self, task: Task, manager: Optional[BaseAgent]
|
||||
) -> Optional[BaseAgent]:
|
||||
if self.process == Process.hierarchical:
|
||||
return manager
|
||||
return task.agent
|
||||
|
||||
def _add_delegation_tools(self, task: Task):
|
||||
agents_for_delegation = [agent for agent in self.agents if agent != task.agent]
|
||||
if len(self.agents) > 1 and len(agents_for_delegation) > 0 and task.agent:
|
||||
@@ -772,17 +679,18 @@ class Crew(BaseModel):
|
||||
# Add the new tool
|
||||
task.tools.append(new_tool)
|
||||
|
||||
def _log_task_start(self, task: Task, role: str = "None"):
|
||||
def _log_task_start(self, task: Task, agent: Optional[BaseAgent]):
|
||||
color = self._logging_color
|
||||
role = agent.role if agent else "None"
|
||||
self._logger.log("debug", f"== Working Agent: {role}", color=color)
|
||||
self._logger.log("info", f"== Starting Task: {task.description}", color=color)
|
||||
if self.output_log_file:
|
||||
self._file_handler.log(agent=role, task=task.description, status="started")
|
||||
|
||||
def _update_manager_tools(self, task: Task, manager: BaseAgent):
|
||||
if task.agent:
|
||||
def _update_manager_tools(self, task: Task, manager: Optional[BaseAgent]):
|
||||
if task.agent and manager:
|
||||
manager.tools = task.agent.get_delegation_tools([task.agent])
|
||||
else:
|
||||
if manager:
|
||||
manager.tools = manager.get_delegation_tools(self.agents)
|
||||
|
||||
def _get_context(self, task: Task, task_outputs: List[TaskOutput]):
|
||||
@@ -822,7 +730,7 @@ class Crew(BaseModel):
|
||||
futures: List[Tuple[Task, Future[TaskOutput], int]],
|
||||
was_replayed: bool = False,
|
||||
) -> List[TaskOutput]:
|
||||
task_outputs: List[TaskOutput] = []
|
||||
task_outputs = []
|
||||
for future_task, future, task_index in futures:
|
||||
task_output = future.result()
|
||||
task_outputs.append(task_output)
|
||||
@@ -844,7 +752,7 @@ class Crew(BaseModel):
|
||||
None,
|
||||
)
|
||||
|
||||
def replay(
|
||||
def replay_from_task(
|
||||
self, task_id: str, inputs: Optional[Dict[str, Any]] = None
|
||||
) -> CrewOutput:
|
||||
stored_outputs = self._task_output_handler.load()
|
||||
@@ -967,20 +875,5 @@ class Crew(BaseModel):
|
||||
|
||||
return total_usage_metrics
|
||||
|
||||
def test(
|
||||
self,
|
||||
n_iterations: int,
|
||||
openai_model_name: str,
|
||||
inputs: Optional[Dict[str, Any]] = None,
|
||||
) -> None:
|
||||
"""Test and evaluate the Crew with the given inputs for n iterations."""
|
||||
evaluator = CrewEvaluator(self, openai_model_name)
|
||||
|
||||
for i in range(1, n_iterations + 1):
|
||||
evaluator.set_iteration(i)
|
||||
self.kickoff(inputs=inputs)
|
||||
|
||||
evaluator.print_crew_evaluation_result()
|
||||
|
||||
def __repr__(self):
|
||||
return f"Crew(id={self.id}, process={self.process}, number_of_agents={len(self.agents)}, number_of_tasks={len(self.tasks)})"
|
||||
|
||||
@@ -23,9 +23,3 @@ class EntityMemory(Memory):
|
||||
"""Saves an entity item into the SQLite storage."""
|
||||
data = f"{item.name}({item.type}): {item.description}"
|
||||
super().save(data, item.metadata)
|
||||
|
||||
def reset(self) -> None:
|
||||
try:
|
||||
self.storage.reset()
|
||||
except Exception as e:
|
||||
raise Exception(f"An error occurred while resetting the entity memory: {e}")
|
||||
|
||||
@@ -30,6 +30,3 @@ class LongTermMemory(Memory):
|
||||
|
||||
def search(self, task: str, latest_n: int = 3) -> Dict[str, Any]:
|
||||
return self.storage.load(task, latest_n) # type: ignore # BUG?: "Storage" has no attribute "load"
|
||||
|
||||
def reset(self) -> None:
|
||||
self.storage.reset()
|
||||
|
||||
@@ -18,16 +18,8 @@ class ShortTermMemory(Memory):
|
||||
)
|
||||
super().__init__(storage)
|
||||
|
||||
def save(self, item: ShortTermMemoryItem) -> None:
|
||||
def save(self, item: ShortTermMemoryItem) -> None: # type: ignore # BUG?: Signature of "save" incompatible with supertype "Memory"
|
||||
super().save(item.data, item.metadata, item.agent)
|
||||
|
||||
def search(self, query: str, score_threshold: float = 0.35):
|
||||
return self.storage.search(query=query, score_threshold=score_threshold) # type: ignore # BUG? The reference is to the parent class, but the parent class does not have this parameters
|
||||
|
||||
def reset(self) -> None:
|
||||
try:
|
||||
self.storage.reset()
|
||||
except Exception as e:
|
||||
raise Exception(
|
||||
f"An error occurred while resetting the short-term memory: {e}"
|
||||
)
|
||||
|
||||
@@ -9,6 +9,3 @@ class Storage:
|
||||
|
||||
def search(self, key: str) -> Dict[str, Any]: # type: ignore
|
||||
pass
|
||||
|
||||
def reset(self) -> None:
|
||||
pass
|
||||
|
||||
@@ -103,20 +103,3 @@ class LTMSQLiteStorage:
|
||||
color="red",
|
||||
)
|
||||
return None
|
||||
|
||||
def reset(
|
||||
self,
|
||||
) -> None:
|
||||
"""Resets the LTM table with error handling."""
|
||||
try:
|
||||
with sqlite3.connect(self.db_path) as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("DELETE FROM long_term_memories")
|
||||
conn.commit()
|
||||
|
||||
except sqlite3.Error as e:
|
||||
self._printer.print(
|
||||
content=f"MEMORY ERROR: An error occurred while deleting all rows in LTM: {e}",
|
||||
color="red",
|
||||
)
|
||||
return None
|
||||
|
||||
@@ -2,7 +2,6 @@ import contextlib
|
||||
import io
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from embedchain import App
|
||||
@@ -72,13 +71,13 @@ class RAGStorage(Storage):
|
||||
|
||||
if embedder_config:
|
||||
config["embedder"] = embedder_config
|
||||
self.type = type
|
||||
|
||||
self.app = App.from_config(config=config)
|
||||
self.app.llm = FakeLLM()
|
||||
if allow_reset:
|
||||
self.app.reset()
|
||||
|
||||
def save(self, value: Any, metadata: Dict[str, Any]) -> None:
|
||||
def save(self, value: Any, metadata: Dict[str, Any]) -> None: # type: ignore # BUG?: Should be save(key, value, metadata) Signature of "save" incompatible with supertype "Storage"
|
||||
self._generate_embedding(value, metadata)
|
||||
|
||||
def search( # type: ignore # BUG?: Signature of "search" incompatible with supertype "Storage"
|
||||
@@ -103,11 +102,3 @@ class RAGStorage(Storage):
|
||||
def _generate_embedding(self, text: str, metadata: Dict[str, Any]) -> Any:
|
||||
with suppress_logging():
|
||||
self.app.add(text, data_type="text", metadata=metadata)
|
||||
|
||||
def reset(self) -> None:
|
||||
try:
|
||||
shutil.rmtree(f"{db_storage_path()}/{self.type}")
|
||||
except Exception as e:
|
||||
raise Exception(
|
||||
f"An error occurred while resetting the {self.type} memory: {e}"
|
||||
)
|
||||
|
||||
@@ -5,7 +5,6 @@ import threading
|
||||
import uuid
|
||||
from concurrent.futures import Future
|
||||
from copy import copy
|
||||
from hashlib import md5
|
||||
from typing import Any, Dict, List, Optional, Tuple, Type, Union
|
||||
|
||||
from langchain_openai import ChatOpenAI
|
||||
@@ -174,14 +173,6 @@ class Task(BaseModel):
|
||||
"""Execute the task synchronously."""
|
||||
return self._execute_core(agent, context, tools)
|
||||
|
||||
@property
|
||||
def key(self) -> str:
|
||||
description = self._original_description or self.description
|
||||
expected_output = self._original_expected_output or self.expected_output
|
||||
source = [description, expected_output]
|
||||
|
||||
return md5("|".join(source).encode()).hexdigest()
|
||||
|
||||
def execute_async(
|
||||
self,
|
||||
agent: BaseAgent | None = None,
|
||||
@@ -213,8 +204,8 @@ class Task(BaseModel):
|
||||
tools: Optional[List[Any]],
|
||||
) -> TaskOutput:
|
||||
"""Run the core execution logic of the task."""
|
||||
agent = agent or self.agent
|
||||
self.agent = agent
|
||||
agent = agent or self.agent
|
||||
if not agent:
|
||||
raise Exception(
|
||||
f"The task '{self.description}' has no agent assigned, therefore it can't be executed directly and should be executed in a Crew using a specific process that support that, like hierarchical."
|
||||
@@ -247,7 +238,7 @@ class Task(BaseModel):
|
||||
self.callback(self.output)
|
||||
|
||||
if self._execution_span:
|
||||
self._telemetry.task_ended(self._execution_span, self, agent.crew)
|
||||
self._telemetry.task_ended(self._execution_span, self)
|
||||
self._execution_span = None
|
||||
|
||||
if self.output_file:
|
||||
@@ -328,14 +319,9 @@ class Task(BaseModel):
|
||||
|
||||
def _create_converter(self, *args, **kwargs) -> Converter:
|
||||
"""Create a converter instance."""
|
||||
if self.agent and not self.converter_cls:
|
||||
converter = self.agent.get_output_converter(*args, **kwargs)
|
||||
elif self.converter_cls:
|
||||
if self.converter_cls:
|
||||
converter = self.converter_cls(*args, **kwargs)
|
||||
|
||||
if not converter:
|
||||
raise Exception("No output converter found or set.")
|
||||
|
||||
return converter
|
||||
|
||||
def _export_output(
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
from typing import Any, Callable
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from crewai.task import Task
|
||||
from crewai.tasks.output_format import OutputFormat
|
||||
from crewai.tasks.task_output import TaskOutput
|
||||
|
||||
|
||||
class ConditionalTask(Task):
|
||||
"""
|
||||
A task that can be conditionally executed based on the output of another task.
|
||||
Note: This cannot be the only task you have in your crew and cannot be the first since its needs context from the previous task.
|
||||
"""
|
||||
|
||||
condition: Callable[[TaskOutput], bool] = Field(
|
||||
default=None,
|
||||
description="Maximum number of retries for an agent to execute a task when an error occurs.",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
condition: Callable[[Any], bool],
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(**kwargs)
|
||||
self.condition = condition
|
||||
|
||||
def should_execute(self, context: TaskOutput) -> bool:
|
||||
"""
|
||||
Determines whether the conditional task should be executed based on the provided context.
|
||||
|
||||
Args:
|
||||
context (Any): The context or output from the previous task that will be evaluated by the condition.
|
||||
|
||||
Returns:
|
||||
bool: True if the task should be executed, False otherwise.
|
||||
"""
|
||||
return self.condition(context)
|
||||
|
||||
def get_skipped_task_output(self):
|
||||
return TaskOutput(
|
||||
description=self.description,
|
||||
raw="",
|
||||
agent=self.agent.role if self.agent else "",
|
||||
output_format=OutputFormat.RAW,
|
||||
)
|
||||
@@ -92,8 +92,13 @@ class Telemetry:
|
||||
pkg_resources.get_distribution("crewai").version,
|
||||
)
|
||||
self._add_attribute(span, "python_version", platform.python_version())
|
||||
self._add_attribute(span, "crew_key", crew.key)
|
||||
self._add_attribute(span, "crew_id", str(crew.id))
|
||||
|
||||
if crew.share_crew:
|
||||
self._add_attribute(
|
||||
span, "crew_inputs", json.dumps(inputs) if inputs else None
|
||||
)
|
||||
|
||||
self._add_attribute(span, "crew_process", crew.process)
|
||||
self._add_attribute(span, "crew_memory", crew.memory)
|
||||
self._add_attribute(span, "crew_number_of_tasks", len(crew.tasks))
|
||||
@@ -104,7 +109,6 @@ class Telemetry:
|
||||
json.dumps(
|
||||
[
|
||||
{
|
||||
"key": agent.key,
|
||||
"id": str(agent.id),
|
||||
"role": agent.role,
|
||||
"goal": agent.goal,
|
||||
@@ -129,14 +133,12 @@ class Telemetry:
|
||||
json.dumps(
|
||||
[
|
||||
{
|
||||
"key": task.key,
|
||||
"id": str(task.id),
|
||||
"description": task.description,
|
||||
"expected_output": task.expected_output,
|
||||
"async_execution?": task.async_execution,
|
||||
"human_input?": task.human_input,
|
||||
"agent_role": task.agent.role if task.agent else "None",
|
||||
"agent_key": task.agent.key if task.agent else None,
|
||||
"context": (
|
||||
[task.description for task in task.context]
|
||||
if task.context
|
||||
@@ -155,12 +157,6 @@ class Telemetry:
|
||||
self._add_attribute(span, "platform_system", platform.system())
|
||||
self._add_attribute(span, "platform_version", platform.version())
|
||||
self._add_attribute(span, "cpus", os.cpu_count())
|
||||
|
||||
if crew.share_crew:
|
||||
self._add_attribute(
|
||||
span, "crew_inputs", json.dumps(inputs) if inputs else None
|
||||
)
|
||||
|
||||
span.set_status(Status(StatusCode.OK))
|
||||
span.end()
|
||||
except Exception:
|
||||
@@ -174,9 +170,8 @@ class Telemetry:
|
||||
|
||||
created_span = tracer.start_span("Task Created")
|
||||
|
||||
self._add_attribute(created_span, "crew_key", crew.key)
|
||||
self._add_attribute(created_span, "crew_id", str(crew.id))
|
||||
self._add_attribute(created_span, "task_key", task.key)
|
||||
self._add_attribute(created_span, "task_index", crew.tasks.index(task))
|
||||
self._add_attribute(created_span, "task_id", str(task.id))
|
||||
|
||||
if crew.share_crew:
|
||||
@@ -192,9 +187,8 @@ class Telemetry:
|
||||
|
||||
span = tracer.start_span("Task Execution")
|
||||
|
||||
self._add_attribute(span, "crew_key", crew.key)
|
||||
self._add_attribute(span, "crew_id", str(crew.id))
|
||||
self._add_attribute(span, "task_key", task.key)
|
||||
self._add_attribute(span, "task_index", crew.tasks.index(task))
|
||||
self._add_attribute(span, "task_id", str(task.id))
|
||||
|
||||
if crew.share_crew:
|
||||
@@ -209,15 +203,12 @@ class Telemetry:
|
||||
|
||||
return None
|
||||
|
||||
def task_ended(self, span: Span, task: Task, crew: Crew):
|
||||
def task_ended(self, span: Span, task: Task):
|
||||
"""Records task execution in a crew."""
|
||||
if self.ready:
|
||||
try:
|
||||
if crew.share_crew:
|
||||
self._add_attribute(
|
||||
span,
|
||||
"task_output",
|
||||
task.output.raw if task.output else "",
|
||||
span, "output", task.output.raw_output if task.output else ""
|
||||
)
|
||||
|
||||
span.set_status(Status(StatusCode.OK))
|
||||
@@ -293,10 +284,10 @@ class Telemetry:
|
||||
"""Records the complete execution of a crew.
|
||||
This is only collected if the user has opted-in to share the crew.
|
||||
"""
|
||||
self.crew_creation(crew, inputs)
|
||||
|
||||
if (self.ready) and (crew.share_crew):
|
||||
try:
|
||||
self.crew_creation(crew, inputs)
|
||||
|
||||
tracer = trace.get_tracer("crewai.telemetry")
|
||||
span = tracer.start_span("Crew Execution")
|
||||
self._add_attribute(
|
||||
@@ -304,7 +295,6 @@ class Telemetry:
|
||||
"crewai_version",
|
||||
pkg_resources.get_distribution("crewai").version,
|
||||
)
|
||||
self._add_attribute(span, "crew_key", crew.key)
|
||||
self._add_attribute(span, "crew_id", str(crew.id))
|
||||
self._add_attribute(
|
||||
span, "crew_inputs", json.dumps(inputs) if inputs else None
|
||||
@@ -315,7 +305,6 @@ class Telemetry:
|
||||
json.dumps(
|
||||
[
|
||||
{
|
||||
"key": agent.key,
|
||||
"id": str(agent.id),
|
||||
"role": agent.role,
|
||||
"goal": agent.goal,
|
||||
@@ -346,7 +335,6 @@ class Telemetry:
|
||||
"async_execution?": task.async_execution,
|
||||
"human_input?": task.human_input,
|
||||
"agent_role": task.agent.role if task.agent else "None",
|
||||
"agent_key": task.agent.key if task.agent else None,
|
||||
"context": (
|
||||
[task.description for task in task.context]
|
||||
if task.context
|
||||
|
||||
@@ -38,10 +38,10 @@ class Converter(OutputConverter):
|
||||
return self._create_instructor().to_json()
|
||||
else:
|
||||
return json.dumps(self._create_chain().invoke({}).model_dump())
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
if current_attempt < self.max_attempts:
|
||||
return self.to_json(current_attempt + 1)
|
||||
return ConverterError(f"Failed to convert text into JSON, error: {e}.")
|
||||
return ConverterError("Failed to convert text into JSON.")
|
||||
|
||||
def _create_instructor(self):
|
||||
"""Create an instructor."""
|
||||
|
||||
@@ -17,16 +17,6 @@ class CrewPydanticOutputParser(PydanticOutputParser):
|
||||
|
||||
def parse_result(self, result: List[Generation], *, partial: bool = False) -> Any:
|
||||
result[0].text = self._transform_in_valid_json(result[0].text)
|
||||
|
||||
# Treating edge case of function calling llm returning the name instead of tool_name
|
||||
json_object = json.loads(result[0].text)
|
||||
json_object["tool_name"] = (
|
||||
json_object["name"]
|
||||
if "tool_name" not in json_object
|
||||
else json_object["tool_name"]
|
||||
)
|
||||
result[0].text = json.dumps(json_object)
|
||||
|
||||
json_object = super().parse_result(result)
|
||||
try:
|
||||
return self.pydantic_object.parse_obj(json_object)
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
from collections import defaultdict
|
||||
|
||||
from langchain_openai import ChatOpenAI
|
||||
from pydantic import BaseModel, Field
|
||||
from rich.console import Console
|
||||
from rich.table import Table
|
||||
|
||||
from crewai.agent import Agent
|
||||
from crewai.task import Task
|
||||
from crewai.tasks.task_output import TaskOutput
|
||||
|
||||
|
||||
class TaskEvaluationPydanticOutput(BaseModel):
|
||||
quality: float = Field(
|
||||
description="A score from 1 to 10 evaluating on completion, quality, and overall performance from the task_description and task_expected_output to the actual Task Output."
|
||||
)
|
||||
|
||||
|
||||
class CrewEvaluator:
|
||||
"""
|
||||
A class to evaluate the performance of the agents in the crew based on the tasks they have performed.
|
||||
|
||||
Attributes:
|
||||
crew (Crew): The crew of agents to evaluate.
|
||||
openai_model_name (str): The model to use for evaluating the performance of the agents (for now ONLY OpenAI accepted).
|
||||
tasks_scores (defaultdict): A dictionary to store the scores of the agents for each task.
|
||||
iteration (int): The current iteration of the evaluation.
|
||||
"""
|
||||
|
||||
tasks_scores: defaultdict = defaultdict(list)
|
||||
iteration: int = 0
|
||||
|
||||
def __init__(self, crew, openai_model_name: str):
|
||||
self.crew = crew
|
||||
self.openai_model_name = openai_model_name
|
||||
self._setup_for_evaluating()
|
||||
|
||||
def _setup_for_evaluating(self) -> None:
|
||||
"""Sets up the crew for evaluating."""
|
||||
for task in self.crew.tasks:
|
||||
task.callback = self.evaluate
|
||||
|
||||
def set_iteration(self, iteration: int) -> None:
|
||||
self.iteration = iteration
|
||||
|
||||
def _evaluator_agent(self):
|
||||
return Agent(
|
||||
role="Task Execution Evaluator",
|
||||
goal=(
|
||||
"Your goal is to evaluate the performance of the agents in the crew based on the tasks they have performed using score from 1 to 10 evaluating on completion, quality, and overall performance."
|
||||
),
|
||||
backstory="Evaluator agent for crew evaluation with precise capabilities to evaluate the performance of the agents in the crew based on the tasks they have performed",
|
||||
verbose=False,
|
||||
llm=ChatOpenAI(model=self.openai_model_name),
|
||||
)
|
||||
|
||||
def _evaluation_task(
|
||||
self, evaluator_agent: Agent, task_to_evaluate: Task, task_output: str
|
||||
) -> Task:
|
||||
return Task(
|
||||
description=(
|
||||
"Based on the task description and the expected output, compare and evaluate the performance of the agents in the crew based on the Task Output they have performed using score from 1 to 10 evaluating on completion, quality, and overall performance."
|
||||
f"task_description: {task_to_evaluate.description} "
|
||||
f"task_expected_output: {task_to_evaluate.expected_output} "
|
||||
f"agent: {task_to_evaluate.agent.role if task_to_evaluate.agent else None} "
|
||||
f"agent_goal: {task_to_evaluate.agent.goal if task_to_evaluate.agent else None} "
|
||||
f"Task Output: {task_output}"
|
||||
),
|
||||
expected_output="Evaluation Score from 1 to 10 based on the performance of the agents on the tasks",
|
||||
agent=evaluator_agent,
|
||||
output_pydantic=TaskEvaluationPydanticOutput,
|
||||
)
|
||||
|
||||
def print_crew_evaluation_result(self) -> None:
|
||||
"""
|
||||
Prints the evaluation result of the crew in a table.
|
||||
A Crew with 2 tasks using the command crewai test -n 2
|
||||
will output the following table:
|
||||
|
||||
Task Scores
|
||||
(1-10 Higher is better)
|
||||
┏━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━┓
|
||||
┃ Tasks/Crew ┃ Run 1 ┃ Run 2 ┃ Avg. Total ┃
|
||||
┡━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━┩
|
||||
│ Task 1 │ 10.0 │ 9.0 │ 9.5 │
|
||||
│ Task 2 │ 9.0 │ 9.0 │ 9.0 │
|
||||
│ Crew │ 9.5 │ 9.0 │ 9.2 │
|
||||
└────────────┴───────┴───────┴────────────┘
|
||||
"""
|
||||
task_averages = [
|
||||
sum(scores) / len(scores) for scores in zip(*self.tasks_scores.values())
|
||||
]
|
||||
crew_average = sum(task_averages) / len(task_averages)
|
||||
|
||||
# Create a table
|
||||
table = Table(title="Tasks Scores \n (1-10 Higher is better)")
|
||||
|
||||
# Add columns for the table
|
||||
table.add_column("Tasks/Crew")
|
||||
for run in range(1, len(self.tasks_scores) + 1):
|
||||
table.add_column(f"Run {run}")
|
||||
table.add_column("Avg. Total")
|
||||
|
||||
# Add rows for each task
|
||||
for task_index in range(len(task_averages)):
|
||||
task_scores = [
|
||||
self.tasks_scores[run][task_index]
|
||||
for run in range(1, len(self.tasks_scores) + 1)
|
||||
]
|
||||
avg_score = task_averages[task_index]
|
||||
table.add_row(
|
||||
f"Task {task_index + 1}", *map(str, task_scores), f"{avg_score:.1f}"
|
||||
)
|
||||
|
||||
# Add a row for the crew average
|
||||
crew_scores = [
|
||||
sum(self.tasks_scores[run]) / len(self.tasks_scores[run])
|
||||
for run in range(1, len(self.tasks_scores) + 1)
|
||||
]
|
||||
table.add_row("Crew", *map(str, crew_scores), f"{crew_average:.1f}")
|
||||
|
||||
# Display the table in the terminal
|
||||
console = Console()
|
||||
console.print(table)
|
||||
|
||||
def evaluate(self, task_output: TaskOutput):
|
||||
"""Evaluates the performance of the agents in the crew based on the tasks they have performed."""
|
||||
current_task = None
|
||||
for task in self.crew.tasks:
|
||||
if task.description == task_output.description:
|
||||
current_task = task
|
||||
break
|
||||
|
||||
if not current_task or not task_output:
|
||||
raise ValueError(
|
||||
"Task to evaluate and task output are required for evaluation"
|
||||
)
|
||||
|
||||
evaluator_agent = self._evaluator_agent()
|
||||
evaluation_task = self._evaluation_task(
|
||||
evaluator_agent, current_task, task_output.raw
|
||||
)
|
||||
|
||||
evaluation_result = evaluation_task.execute_sync()
|
||||
|
||||
if isinstance(evaluation_result.pydantic, TaskEvaluationPydanticOutput):
|
||||
self.tasks_scores[self.iteration].append(evaluation_result.pydantic.quality)
|
||||
else:
|
||||
raise ValueError("Evaluation result is not in the expected format")
|
||||
@@ -1,64 +0,0 @@
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from crewai.agent import Agent
|
||||
from crewai.task import Task
|
||||
|
||||
|
||||
class PlannerTaskPydanticOutput(BaseModel):
|
||||
list_of_plans_per_task: List[str]
|
||||
|
||||
|
||||
class CrewPlanner:
|
||||
def __init__(self, tasks: List[Task]):
|
||||
self.tasks = tasks
|
||||
|
||||
def _handle_crew_planning(self) -> Optional[BaseModel]:
|
||||
"""Handles the Crew planning by creating detailed step-by-step plans for each task."""
|
||||
planning_agent = self._create_planning_agent()
|
||||
tasks_summary = self._create_tasks_summary()
|
||||
|
||||
planner_task = self._create_planner_task(planning_agent, tasks_summary)
|
||||
|
||||
return planner_task.execute_sync().pydantic
|
||||
|
||||
def _create_planning_agent(self) -> Agent:
|
||||
"""Creates the planning agent for the crew planning."""
|
||||
return Agent(
|
||||
role="Task Execution Planner",
|
||||
goal=(
|
||||
"Your goal is to create an extremely detailed, step-by-step plan based on the tasks and tools "
|
||||
"available to each agent so that they can perform the tasks in an exemplary manner"
|
||||
),
|
||||
backstory="Planner agent for crew planning",
|
||||
)
|
||||
|
||||
def _create_planner_task(self, planning_agent: Agent, tasks_summary: str) -> Task:
|
||||
"""Creates the planner task using the given agent and tasks summary."""
|
||||
return Task(
|
||||
description=(
|
||||
f"Based on these tasks summary: {tasks_summary} \n Create the most descriptive plan based on the tasks "
|
||||
"descriptions, tools available, and agents' goals for them to execute their goals with perfection."
|
||||
),
|
||||
expected_output="Step by step plan on how the agents can execute their tasks using the available tools with mastery",
|
||||
agent=planning_agent,
|
||||
output_pydantic=PlannerTaskPydanticOutput,
|
||||
)
|
||||
|
||||
def _create_tasks_summary(self) -> str:
|
||||
"""Creates a summary of all tasks."""
|
||||
tasks_summary = []
|
||||
for idx, task in enumerate(self.tasks):
|
||||
tasks_summary.append(
|
||||
f"""
|
||||
Task Number {idx + 1} - {task.description}
|
||||
"task_description": {task.description}
|
||||
"task_expected_output": {task.expected_output}
|
||||
"agent": {task.agent.role if task.agent else "None"}
|
||||
"agent_goal": {task.agent.goal if task.agent else "None"}
|
||||
"task_tools": {task.tools}
|
||||
"agent_tools": {task.agent.tools if task.agent else "None"}
|
||||
"""
|
||||
)
|
||||
return " ".join(tasks_summary)
|
||||
@@ -10,8 +10,6 @@ class Printer:
|
||||
self._print_bold_purple(content)
|
||||
elif color == "bold_blue":
|
||||
self._print_bold_blue(content)
|
||||
elif color == "yellow":
|
||||
self._print_yellow(content)
|
||||
else:
|
||||
print(content)
|
||||
|
||||
@@ -29,6 +27,3 @@ class Printer:
|
||||
|
||||
def _print_bold_blue(self, content):
|
||||
print("\033[1m\033[94m {}\033[00m".format(content))
|
||||
|
||||
def _print_yellow(self, content):
|
||||
print("\033[93m {}\033[00m".format(content))
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import hashlib
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from crewai.agents.agent_builder.base_agent import BaseAgent
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class TestAgent(BaseAgent):
|
||||
def execute_task(
|
||||
self,
|
||||
task: Any,
|
||||
context: Optional[str] = None,
|
||||
tools: Optional[List[Any]] = None,
|
||||
) -> str:
|
||||
return ""
|
||||
|
||||
def create_agent_executor(self, tools=None) -> None: ...
|
||||
|
||||
def _parse_tools(self, tools: List[Any]) -> List[Any]:
|
||||
return []
|
||||
|
||||
def get_delegation_tools(self, agents: List["BaseAgent"]): ...
|
||||
|
||||
def get_output_converter(
|
||||
self, llm: Any, text: str, model: type[BaseModel] | None, instructions: str
|
||||
): ...
|
||||
|
||||
|
||||
def test_key():
|
||||
agent = TestAgent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory",
|
||||
)
|
||||
hash = hashlib.md5("test role|test goal|test backstory".encode()).hexdigest()
|
||||
assert agent.key == hash
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,151 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: '{"messages": [{"content": "You are Researcher. You''re an expert researcher,
|
||||
specialized in technology, software engineering, AI and startups. You work as
|
||||
a freelancer and is now working on doing research and analysis for a new customer.\nYour
|
||||
personal goal is: Make the best research and analysis on content about AI and
|
||||
AI agentsTo give my best complete final answer to the task use the exact following
|
||||
format:\n\nThought: I now can give a great answer\nFinal Answer: my best complete
|
||||
final answer to the task.\nYour final answer must be the great and the most
|
||||
complete as possible, it must be outcome described.\n\nI MUST use these formats,
|
||||
my job depends on it!\nCurrent Task: Say Hi\n\nThis is the expect criteria for
|
||||
your final answer: Hi \n you MUST return the actual complete content as the
|
||||
final answer, not a summary.\n\nBegin! This is VERY important to you, use the
|
||||
tools available and give your best Final Answer, your job depends on it!\n\nThought:\n",
|
||||
"role": "user"}], "model": "gpt-4o", "n": 1, "stop": ["\nObservation"], "stream":
|
||||
true, "temperature": 0.7}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '1072'
|
||||
content-type:
|
||||
- application/json
|
||||
cookie:
|
||||
- _cfuvid=Nxp5RE8CN2EyHxMIvB_SaTizIH5w0eWt9SPilMuIjMk-1721227661802-0.0.1.1-604800000;
|
||||
__cf_bm=jadAYV2gh7qPDzgKO9A4JzJTaI9c2fnnjxloIQZeOIw-1721227661-1.0.1.1-apaA8kQyGiEV3kOuXHe8z1zeyvxd_jBHCQpdqWirUlylrUo.uRZjRDueI.sSXS4hXoWkyIW6kIMt7lamQM2mdw
|
||||
host:
|
||||
- api.openai.com
|
||||
user-agent:
|
||||
- OpenAI/Python 1.35.10
|
||||
x-stainless-arch:
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 1.35.10
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.12.3
|
||||
method: POST
|
||||
uri: https://api.openai.com/v1/chat/completions
|
||||
response:
|
||||
body:
|
||||
string: 'data: {"id":"chatcmpl-9m0FB4Oy6X0apYX2wcQ30rTBkmtxT","object":"chat.completion.chunk","created":1721227709,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9m0FB4Oy6X0apYX2wcQ30rTBkmtxT","object":"chat.completion.chunk","created":1721227709,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"I"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9m0FB4Oy6X0apYX2wcQ30rTBkmtxT","object":"chat.completion.chunk","created":1721227709,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
now"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9m0FB4Oy6X0apYX2wcQ30rTBkmtxT","object":"chat.completion.chunk","created":1721227709,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
can"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9m0FB4Oy6X0apYX2wcQ30rTBkmtxT","object":"chat.completion.chunk","created":1721227709,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
give"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9m0FB4Oy6X0apYX2wcQ30rTBkmtxT","object":"chat.completion.chunk","created":1721227709,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
a"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9m0FB4Oy6X0apYX2wcQ30rTBkmtxT","object":"chat.completion.chunk","created":1721227709,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
great"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9m0FB4Oy6X0apYX2wcQ30rTBkmtxT","object":"chat.completion.chunk","created":1721227709,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
answer"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9m0FB4Oy6X0apYX2wcQ30rTBkmtxT","object":"chat.completion.chunk","created":1721227709,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":".\n"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9m0FB4Oy6X0apYX2wcQ30rTBkmtxT","object":"chat.completion.chunk","created":1721227709,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"Final"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9m0FB4Oy6X0apYX2wcQ30rTBkmtxT","object":"chat.completion.chunk","created":1721227709,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
Answer"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9m0FB4Oy6X0apYX2wcQ30rTBkmtxT","object":"chat.completion.chunk","created":1721227709,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":":"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9m0FB4Oy6X0apYX2wcQ30rTBkmtxT","object":"chat.completion.chunk","created":1721227709,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
Hi"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9m0FB4Oy6X0apYX2wcQ30rTBkmtxT","object":"chat.completion.chunk","created":1721227709,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}]}
|
||||
|
||||
|
||||
data: [DONE]
|
||||
|
||||
|
||||
'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8a4b087e7d024593-ATL
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- text/event-stream; charset=utf-8
|
||||
Date:
|
||||
- Wed, 17 Jul 2024 14:48:29 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
openai-organization:
|
||||
- crewai-iuxna1
|
||||
openai-processing-ms:
|
||||
- '142'
|
||||
openai-version:
|
||||
- '2020-10-01'
|
||||
strict-transport-security:
|
||||
- max-age=15552000; includeSubDomains; preload
|
||||
x-ratelimit-limit-requests:
|
||||
- '10000'
|
||||
x-ratelimit-limit-tokens:
|
||||
- '30000000'
|
||||
x-ratelimit-remaining-requests:
|
||||
- '9999'
|
||||
x-ratelimit-remaining-tokens:
|
||||
- '29999753'
|
||||
x-ratelimit-reset-requests:
|
||||
- 6ms
|
||||
x-ratelimit-reset-tokens:
|
||||
- 0s
|
||||
x-request-id:
|
||||
- req_75100793afc289eaf8b56127e1cc0532
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,262 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: '{"messages": [{"content": "You are Scorer. You''re an expert scorer, specialized
|
||||
in scoring titles.\nYour personal goal is: Score the titleTo give my best complete
|
||||
final answer to the task use the exact following format:\n\nThought: I now can
|
||||
give a great answer\nFinal Answer: my best complete final answer to the task.\nYour
|
||||
final answer must be the great and the most complete as possible, it must be
|
||||
outcome described.\n\nI MUST use these formats, my job depends on it!\nCurrent
|
||||
Task: Give me an integer score between 1-5 for the following title: ''The impact
|
||||
of AI in the future of work''\n\nThis is the expect criteria for your final
|
||||
answer: The score of the title. \n you MUST return the actual complete content
|
||||
as the final answer, not a summary.\n\nBegin! This is VERY important to you,
|
||||
use the tools available and give your best Final Answer, your job depends on
|
||||
it!\n\nThought:\n", "role": "user"}], "model": "gpt-4o", "n": 1, "stop": ["\nObservation"],
|
||||
"stream": true, "temperature": 0.7}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '997'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.openai.com
|
||||
user-agent:
|
||||
- OpenAI/Python 1.35.14
|
||||
x-stainless-arch:
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 1.35.14
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.11.7
|
||||
method: POST
|
||||
uri: https://api.openai.com/v1/chat/completions
|
||||
response:
|
||||
body:
|
||||
string: 'data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"Thought"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":":"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
I"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
now"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
can"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
give"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
a"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
great"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
answer"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"\n"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"Final"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
Answer"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":":"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"4"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltULlJQMDDjI2f7PpkjJ7DsxWjEQ","object":"chat.completion.chunk","created":1721201741,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}]}
|
||||
|
||||
|
||||
data: [DONE]
|
||||
|
||||
|
||||
'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8a488e81aa7f0c7e-EWR
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- text/event-stream; charset=utf-8
|
||||
Date:
|
||||
- Wed, 17 Jul 2024 07:35:41 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- __cf_bm=Ypr9N3lq.OD8hpimnkpN61rAsWyk216I8Tq7RA8.uwQ-1721201741-1.0.1.1-6Cj4aX9I96QHMmPwJBpO1iCFOJsvzq_agUIrl3XS.YhlPuGyA4K9sDONExvLn.cDe3W_p_1ET7Pt_hxjtHPAXQ;
|
||||
path=/; expires=Wed, 17-Jul-24 08:05:41 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=NLa1BaUsRvD7shojIzUH9YSRXQIEzaoJVcq2_gNwqm0-1721201741646-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
openai-organization:
|
||||
- crewai-iuxna1
|
||||
openai-processing-ms:
|
||||
- '106'
|
||||
openai-version:
|
||||
- '2020-10-01'
|
||||
strict-transport-security:
|
||||
- max-age=15552000; includeSubDomains; preload
|
||||
x-ratelimit-limit-requests:
|
||||
- '10000'
|
||||
x-ratelimit-limit-tokens:
|
||||
- '30000000'
|
||||
x-ratelimit-remaining-requests:
|
||||
- '9999'
|
||||
x-ratelimit-remaining-tokens:
|
||||
- '29999771'
|
||||
x-ratelimit-reset-requests:
|
||||
- 6ms
|
||||
x-ratelimit-reset-tokens:
|
||||
- 0s
|
||||
x-request-id:
|
||||
- req_e52461a1ab2702e360f6303fbcb4cc3c
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: '{"messages": [{"role": "user", "content": "4"}, {"role": "system", "content":
|
||||
"I''m gonna convert this raw text into valid JSON."}], "model": "gpt-4o", "tool_choice":
|
||||
{"type": "function", "function": {"name": "ScoreOutput"}}, "tools": [{"type":
|
||||
"function", "function": {"name": "ScoreOutput", "description": "Correctly extracted
|
||||
`ScoreOutput` with all the required parameters with correct types", "parameters":
|
||||
{"properties": {"score": {"title": "Score", "type": "integer"}}, "required":
|
||||
["score"], "type": "object"}}}]}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '519'
|
||||
content-type:
|
||||
- application/json
|
||||
cookie:
|
||||
- __cf_bm=Ypr9N3lq.OD8hpimnkpN61rAsWyk216I8Tq7RA8.uwQ-1721201741-1.0.1.1-6Cj4aX9I96QHMmPwJBpO1iCFOJsvzq_agUIrl3XS.YhlPuGyA4K9sDONExvLn.cDe3W_p_1ET7Pt_hxjtHPAXQ;
|
||||
_cfuvid=NLa1BaUsRvD7shojIzUH9YSRXQIEzaoJVcq2_gNwqm0-1721201741646-0.0.1.1-604800000
|
||||
host:
|
||||
- api.openai.com
|
||||
user-agent:
|
||||
- OpenAI/Python 1.35.14
|
||||
x-stainless-arch:
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 1.35.14
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.11.7
|
||||
method: POST
|
||||
uri: https://api.openai.com/v1/chat/completions
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAA2xS22rjMBB991eIeY6LHTubrR9LKYUttKWUvbUYRRnb6sqSVhqTJiH/vshxYzes
|
||||
H8QwZ86FGe8jxkCuoWAgGk6itSq+VPR8d8O/vXXZbiOzx13S5D9/PNwSv8nvYBYYZvWGgj5YF8K0
|
||||
ViFJo4+wcMgJg2q6nKfzJF3maQ+0Zo0q0GpLcW7ieTLP42QRp9lAbIwU6KFgvyPGGNv3b4io1/gO
|
||||
BUtmH50Wvec1QnEaYgycUaED3HvpiWuC2QgKowl1SK07pSYAGaNKwZUajY/fflKPe+JKlVe/nqvV
|
||||
98vNtslul3/Xj7vrzaZ6StOJ31F6a/tAVafFaT8T/NQvzswYA83bnvskjMP7jmxHZ3TGgLu6a1FT
|
||||
iA77F/Bh+AWK/ACfRg/R/+rXoTqc1qpMbZ1Z+bMtQSW19E3pkPs+LXgy9mgR5F7783WfLgLWmdZS
|
||||
SeYP6iD4dbgejP/LCC4GjAxxNeEsoiEe+K0nbMtK6hqddbI/JVS2FDkuVl8qnqUQHaJ/AAAA//8D
|
||||
ACb4o2zTAgAA
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8a488e858ca50c7e-EWR
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Wed, 17 Jul 2024 07:35:42 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
openai-organization:
|
||||
- crewai-iuxna1
|
||||
openai-processing-ms:
|
||||
- '241'
|
||||
openai-version:
|
||||
- '2020-10-01'
|
||||
strict-transport-security:
|
||||
- max-age=15552000; includeSubDomains; preload
|
||||
x-ratelimit-limit-requests:
|
||||
- '10000'
|
||||
x-ratelimit-limit-tokens:
|
||||
- '30000000'
|
||||
x-ratelimit-remaining-requests:
|
||||
- '9999'
|
||||
x-ratelimit-remaining-tokens:
|
||||
- '29999968'
|
||||
x-ratelimit-reset-requests:
|
||||
- 6ms
|
||||
x-ratelimit-reset-tokens:
|
||||
- 0s
|
||||
x-request-id:
|
||||
- req_01c2f40fe9c73f883b7ed5b60c8067e5
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,159 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: '{"messages": [{"content": "You are test_agent. Test Description\nYour personal
|
||||
goal is: Test GoalTo give my best complete final answer to the task use the
|
||||
exact following format:\n\nThought: I now can give a great answer\nFinal Answer:
|
||||
my best complete final answer to the task.\nYour final answer must be the great
|
||||
and the most complete as possible, it must be outcome described.\n\nI MUST use
|
||||
these formats, my job depends on it!\nCurrent Task: Test Task\n\nThis is the
|
||||
expect criteria for your final answer: Say Hi \n you MUST return the actual
|
||||
complete content as the final answer, not a summary.\n\nThis is the context
|
||||
you''re working with:\ncontext raw output\n\nBegin! This is VERY important to
|
||||
you, use the tools available and give your best Final Answer, your job depends
|
||||
on it!\n\nThought:\n", "role": "user"}], "model": "gpt-4o", "n": 1, "stop":
|
||||
["\nObservation"], "stream": true, "temperature": 0.7}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '910'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.openai.com
|
||||
user-agent:
|
||||
- OpenAI/Python 1.35.14
|
||||
x-stainless-arch:
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 1.35.14
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.11.7
|
||||
method: POST
|
||||
uri: https://api.openai.com/v1/chat/completions
|
||||
response:
|
||||
body:
|
||||
string: 'data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"Thought"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":":"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
I"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
now"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
can"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
give"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
a"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
great"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
answer"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"\n"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"Final"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
Answer"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":":"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
Hi"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9ltUKsvuhS55Ng70kOmxKNQcksxm4","object":"chat.completion.chunk","created":1721201740,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}]}
|
||||
|
||||
|
||||
data: [DONE]
|
||||
|
||||
|
||||
'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8a488e7859304288-EWR
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- text/event-stream; charset=utf-8
|
||||
Date:
|
||||
- Wed, 17 Jul 2024 07:35:40 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- __cf_bm=tBullt04HIYduv1QEpAn86_ghx9PQ4DMe9LwLp7.bu4-1721201740-1.0.1.1-sGn3OYi9ntPGIzwuC4RH0UTUQFVy.BUFIvy9v9IrjorYeAsecsuuuREs7b19i4dXygWnZZEkH6cxvnQeJ62g7g;
|
||||
path=/; expires=Wed, 17-Jul-24 08:05:40 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=uSSEccAecytxcWKGJoaQXLVBAwHLrZ.QckpcK..rN48-1721201740355-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
openai-organization:
|
||||
- crewai-iuxna1
|
||||
openai-processing-ms:
|
||||
- '83'
|
||||
openai-version:
|
||||
- '2020-10-01'
|
||||
strict-transport-security:
|
||||
- max-age=15552000; includeSubDomains; preload
|
||||
x-ratelimit-limit-requests:
|
||||
- '10000'
|
||||
x-ratelimit-limit-tokens:
|
||||
- '30000000'
|
||||
x-ratelimit-remaining-requests:
|
||||
- '9999'
|
||||
x-ratelimit-remaining-tokens:
|
||||
- '29999793'
|
||||
x-ratelimit-reset-requests:
|
||||
- 6ms
|
||||
x-ratelimit-reset-tokens:
|
||||
- 0s
|
||||
x-request-id:
|
||||
- req_89b4947eaf51788bd7a69d6cc0da6c08
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,163 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: '{"messages": [{"content": "You are test_agent. Test Description\nYour personal
|
||||
goal is: Test GoalTo give my best complete final answer to the task use the
|
||||
exact following format:\n\nThought: I now can give a great answer\nFinal Answer:
|
||||
my best complete final answer to the task.\nYour final answer must be the great
|
||||
and the most complete as possible, it must be outcome described.\n\nI MUST use
|
||||
these formats, my job depends on it!\nCurrent Task: Test Task\n\nThis is the
|
||||
expect criteria for your final answer: Say Hi to John \n you MUST return the
|
||||
actual complete content as the final answer, not a summary.\n\nThis is the context
|
||||
you''re working with:\ncontext raw output\n\nBegin! This is VERY important to
|
||||
you, use the tools available and give your best Final Answer, your job depends
|
||||
on it!\n\nThought:\n", "role": "user"}], "model": "gpt-4o", "logprobs": false,
|
||||
"n": 1, "stop": ["\nObservation"], "stream": true, "temperature": 0.7}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '937'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.openai.com
|
||||
user-agent:
|
||||
- OpenAI/Python 1.36.0
|
||||
x-stainless-arch:
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 1.36.0
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.11.7
|
||||
method: POST
|
||||
uri: https://api.openai.com/v1/chat/completions
|
||||
response:
|
||||
body:
|
||||
string: 'data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"Thought"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":":"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
I"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
now"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
can"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
give"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
a"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
great"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
answer"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"\n"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"Final"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
Answer"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":":"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
Hi"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{"content":"
|
||||
John"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wQ7bzZKcXAmiNgs4nn5Of0EFiM","object":"chat.completion.chunk","created":1721491782,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_400f27fa1f","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}]}
|
||||
|
||||
|
||||
data: [DONE]
|
||||
|
||||
|
||||
'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8a643794fe0341e9-EWR
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- text/event-stream; charset=utf-8
|
||||
Date:
|
||||
- Sat, 20 Jul 2024 16:09:42 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- __cf_bm=7kfE3khl2E.6zM44yel5nToHzdtz0QeQ4wkLuGYyqSs-1721491782-1.0.1.1-XUb95eXTriHvSUSCH.TCyAmCGCbPK6L7p_tRTDBon8Fo6ns8TDbDoDGA.wVCFI4MTXSxkqrjD0GpYDj4GBTeSQ;
|
||||
path=/; expires=Sat, 20-Jul-24 16:39:42 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=iN41lAEk.DjpRMAtG.K0NEvIN0xB9eS0CUCU2iWmjv4-1721491782137-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
openai-organization:
|
||||
- crewai-iuxna1
|
||||
openai-processing-ms:
|
||||
- '104'
|
||||
openai-version:
|
||||
- '2020-10-01'
|
||||
strict-transport-security:
|
||||
- max-age=15552000; includeSubDomains; preload
|
||||
x-ratelimit-limit-requests:
|
||||
- '10000'
|
||||
x-ratelimit-limit-tokens:
|
||||
- '30000000'
|
||||
x-ratelimit-remaining-requests:
|
||||
- '9999'
|
||||
x-ratelimit-remaining-tokens:
|
||||
- '29999791'
|
||||
x-ratelimit-reset-requests:
|
||||
- 6ms
|
||||
x-ratelimit-reset-tokens:
|
||||
- 0s
|
||||
x-request-id:
|
||||
- req_4d90924dd28a0fb48c857f03515f0ca8
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,449 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: !!binary |
|
||||
CrG5AQokCiIKDHNlcnZpY2UubmFtZRISChBjcmV3QUktdGVsZW1ldHJ5Eoe5AQoSChBjcmV3YWku
|
||||
dGVsZW1ldHJ5EpACChB1aPb7uNmPUxB3quhKypN4EgjnW4at80oLKCoOVGFzayBFeGVjdXRpb24w
|
||||
ATnIwfLEssXiF0FI2USctcXiF0ouCghjcmV3X2tleRIiCiA5OGE3ZDIxNDI1MjEwNzY5MzhjYzg3
|
||||
Yzc2OWRlZGNkM0oxCgdjcmV3X2lkEiYKJDQzOTNlYjRmLTRiMDMtNDgzOS1hMmMwLWViY2IwNTMy
|
||||
NDJjNEouCgh0YXNrX2tleRIiCiBhZmE2OThiMjYyZDM1NDNmOWE2MTFlNGQ1MTQ1ZWQ2YUoxCgd0
|
||||
YXNrX2lkEiYKJDM1ZTA0MTVkLTlhNzYtNDc5YS1hOGFkLTI2NjJiZDQ0NjRiMXoCGAGFAQABAAAS
|
||||
ig0KEBXTWyRbS66PohO2H7pX1jQSCBQxHUkWdA7dKgxDcmV3IENyZWF0ZWQwATmAAQ+ftcXiF0E4
|
||||
fhGftcXiF0oaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjM2LjBKGgoOcHl0aG9uX3ZlcnNpb24SCAoG
|
||||
My4xMS41Si4KCGNyZXdfa2V5EiIKIGNhN2MwMTM2ZWM3YmY1ZGU3NWRlNWQyNjY5OWRhM2I0SjEK
|
||||
B2NyZXdfaWQSJgokYzk5MzVhMDItOGJjYi00YTJlLThhZjktYTU5NWNmMTgyMzYzShwKDGNyZXdf
|
||||
cHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJlcl9v
|
||||
Zl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUr+BAoLY3Jld19hZ2VudHMS
|
||||
7gQK6wRbeyJrZXkiOiAiOGJkMjEzOWI1OTc1MTgxNTA2ZTQxZmQ5YzQ1NjNkNzUiLCAiaWQiOiAi
|
||||
Yjg4NzA5MjYtYzNiYi00MDUyLWIxYTctNDY3ZDdjNDJmMjVkIiwgInJvbGUiOiAiUmVzZWFyY2hl
|
||||
ciIsICJnb2FsIjogIk1ha2UgdGhlIGJlc3QgcmVzZWFyY2ggYW5kIGFuYWx5c2lzIG9uIGNvbnRl
|
||||
bnQgYWJvdXQgQUkgYW5kIEFJIGFnZW50cyIsICJiYWNrc3RvcnkiOiAiWW91J3JlIGFuIGV4cGVy
|
||||
dCByZXNlYXJjaGVyLCBzcGVjaWFsaXplZCBpbiB0ZWNobm9sb2d5LCBzb2Z0d2FyZSBlbmdpbmVl
|
||||
cmluZywgQUkgYW5kIHN0YXJ0dXBzLiBZb3Ugd29yayBhcyBhIGZyZWVsYW5jZXIgYW5kIGlzIG5v
|
||||
dyB3b3JraW5nIG9uIGRvaW5nIHJlc2VhcmNoIGFuZCBhbmFseXNpcyBmb3IgYSBuZXcgY3VzdG9t
|
||||
ZXIuIiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDI1LCAibWF4X3JwbSI6IG51bGws
|
||||
ICJpMThuIjogbnVsbCwgImxsbSI6ICJ7XCJuYW1lXCI6IG51bGwsIFwibW9kZWxfbmFtZVwiOiBc
|
||||
ImdwdC00b1wiLCBcInRlbXBlcmF0dXJlXCI6IDAuNywgXCJjbGFzc1wiOiBcIkNoYXRPcGVuQUlc
|
||||
In0iLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAidG9vbHNfbmFtZXMiOiBbXX1dSskD
|
||||
CgpjcmV3X3Rhc2tzEroDCrcDW3sia2V5IjogIjk0NGFlZjBiYWM4NDBmMWMyN2JkODNhOTM3YmMz
|
||||
NjFiIiwgImlkIjogIjVkZDRjMTJhLThmOWItNDRmNi1iYjRhLWVkODdiNTgzZGU1MCIsICJkZXNj
|
||||
cmlwdGlvbiI6ICJHaXZlIG1lIGEgbGlzdCBvZiA1IGludGVyZXN0aW5nIGlkZWFzIHRvIGV4cGxv
|
||||
cmUgZm9yIG5hIGFydGljbGUsIHdoYXQgbWFrZXMgdGhlbSB1bmlxdWUgYW5kIGludGVyZXN0aW5n
|
||||
LiIsICJleHBlY3RlZF9vdXRwdXQiOiAiQnVsbGV0IHBvaW50IGxpc3Qgb2YgNSBpbXBvcnRhbnQg
|
||||
ZXZlbnRzLiIsICJhc3luY19leGVjdXRpb24/IjogdHJ1ZSwgImh1bWFuX2lucHV0PyI6IGZhbHNl
|
||||
LCAiYWdlbnRfcm9sZSI6ICJSZXNlYXJjaGVyIiwgImFnZW50X2tleSI6ICI4YmQyMTM5YjU5NzUx
|
||||
ODE1MDZlNDFmZDljNDU2M2Q3NSIsICJjb250ZXh0IjogbnVsbCwgInRvb2xzX25hbWVzIjogW119
|
||||
XUoqCghwbGF0Zm9ybRIeChxtYWNPUy0xNC4xLjEtYXJtNjQtYXJtLTY0Yml0ShwKEHBsYXRmb3Jt
|
||||
X3JlbGVhc2USCAoGMjMuMS4wShsKD3BsYXRmb3JtX3N5c3RlbRIICgZEYXJ3aW5KewoQcGxhdGZv
|
||||
cm1fdmVyc2lvbhJnCmVEYXJ3aW4gS2VybmVsIFZlcnNpb24gMjMuMS4wOiBNb24gT2N0ICA5IDIx
|
||||
OjI3OjI0IFBEVCAyMDIzOyByb290OnhudS0xMDAwMi40MS45fjYvUkVMRUFTRV9BUk02NF9UNjAw
|
||||
MEoKCgRjcHVzEgIYCnoCGAGFAQABAAASjgIKEIq7Mjq32M5Kt5dKJnjskZ0SCMx1TtvU1+T2KgxU
|
||||
YXNrIENyZWF0ZWQwATkI9iiftcXiF0HAfimftcXiF0ouCghjcmV3X2tleRIiCiBjYTdjMDEzNmVj
|
||||
N2JmNWRlNzVkZTVkMjY2OTlkYTNiNEoxCgdjcmV3X2lkEiYKJGM5OTM1YTAyLThiY2ItNGEyZS04
|
||||
YWY5LWE1OTVjZjE4MjM2M0ouCgh0YXNrX2tleRIiCiA5NDRhZWYwYmFjODQwZjFjMjdiZDgzYTkz
|
||||
N2JjMzYxYkoxCgd0YXNrX2lkEiYKJDVkZDRjMTJhLThmOWItNDRmNi1iYjRhLWVkODdiNTgzZGU1
|
||||
MHoCGAGFAQABAAASkAIKEE4G7Oi0pafO3nARt5VKez4SCM6Ua5kmBYFDKg5UYXNrIEV4ZWN1dGlv
|
||||
bjABOXC1KZ+1xeIXQWDhMJ+1xeIXSi4KCGNyZXdfa2V5EiIKIGNhN2MwMTM2ZWM3YmY1ZGU3NWRl
|
||||
NWQyNjY5OWRhM2I0SjEKB2NyZXdfaWQSJgokYzk5MzVhMDItOGJjYi00YTJlLThhZjktYTU5NWNm
|
||||
MTgyMzYzSi4KCHRhc2tfa2V5EiIKIDk0NGFlZjBiYWM4NDBmMWMyN2JkODNhOTM3YmMzNjFiSjEK
|
||||
B3Rhc2tfaWQSJgokNWRkNGMxMmEtOGY5Yi00NGY2LWJiNGEtZWQ4N2I1ODNkZTUwegIYAYUBAAEA
|
||||
ABLUGQoQX+5PRYVQ3O7KzTa1tWKiRxIIuu8x8CYW2KEqDENyZXcgQ3JlYXRlZDABOUjW1qO1xeIX
|
||||
QUjE2aO1xeIXShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuMzYuMEoaCg5weXRob25fdmVyc2lvbhII
|
||||
CgYzLjExLjVKLgoIY3Jld19rZXkSIgogYTBhYzk1MzU0ZDMyOWJhN2Y2OTQ4M2FkZmUwYzdkMjhK
|
||||
MQoHY3Jld19pZBImCiQ5MzgzYzU2Yy1lNzQ3LTQwYmItOTlhYi01NGE2NGRkY2Q3YTlKHAoMY3Jl
|
||||
d19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkSAhAAShoKFGNyZXdfbnVtYmVy
|
||||
X29mX3Rhc2tzEgIYBEobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgCSvcHCgtjcmV3X2FnZW50
|
||||
cxLnBwrkB1t7ImtleSI6ICJkYWI1MjFlYmQzMWFlMTJmZWUxODlhMzhkMzA5MGQ5MyIsICJpZCI6
|
||||
ICJhMzAzNTliZi01Y2QwLTQ3MGYtOTk2NS0yYjZhZTU0YmVmY2MiLCAicm9sZSI6ICJXcml0ZXIi
|
||||
LCAiZ29hbCI6ICJZb3Ugd3JpdGUgbGVzc3NvbnMgb2YgbWF0aCBmb3Iga2lkcy4iLCAiYmFja3N0
|
||||
b3J5IjogIllvdSdyZSBhbiBleHBlcnQgaW4gd3JpdHRpbmcgYW5kIHlvdSBsb3ZlIHRvIHRlYWNo
|
||||
IGtpZHMgYnV0IHlvdSBrbm93IG5vdGhpbmcgb2YgbWF0aC4iLCAidmVyYm9zZT8iOiBmYWxzZSwg
|
||||
Im1heF9pdGVyIjogMjUsICJtYXhfcnBtIjogbnVsbCwgImkxOG4iOiBudWxsLCAibGxtIjogIntc
|
||||
Im5hbWVcIjogbnVsbCwgXCJtb2RlbF9uYW1lXCI6IFwiZ3B0LTRvXCIsIFwidGVtcGVyYXR1cmVc
|
||||
IjogMC43LCBcImNsYXNzXCI6IFwiQ2hhdE9wZW5BSVwifSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/
|
||||
IjogZmFsc2UsICJ0b29sc19uYW1lcyI6IFsibXVsdGlwbGNhdGlvbl90b29sIl19LCB7ImtleSI6
|
||||
ICJkYWI1MjFlYmQzMWFlMTJmZWUxODlhMzhkMzA5MGQ5MyIsICJpZCI6ICJhN2JiNTI4ZS0yM2M4
|
||||
LTQ1MzItYjNiYS0yOWU1NDNiMGFhN2YiLCAicm9sZSI6ICJXcml0ZXIiLCAiZ29hbCI6ICJZb3Ug
|
||||
d3JpdGUgbGVzc3NvbnMgb2YgbWF0aCBmb3Iga2lkcy4iLCAiYmFja3N0b3J5IjogIllvdSdyZSBh
|
||||
biBleHBlcnQgaW4gd3JpdHRpbmcgYW5kIHlvdSBsb3ZlIHRvIHRlYWNoIGtpZHMgYnV0IHlvdSBr
|
||||
bm93IG5vdGhpbmcgb2YgbWF0aC4iLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjUs
|
||||
ICJtYXhfcnBtIjogbnVsbCwgImkxOG4iOiBudWxsLCAibGxtIjogIntcIm5hbWVcIjogbnVsbCwg
|
||||
XCJtb2RlbF9uYW1lXCI6IFwiZ3B0LTRvXCIsIFwidGVtcGVyYXR1cmVcIjogMC43LCBcImNsYXNz
|
||||
XCI6IFwiQ2hhdE9wZW5BSVwifSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJ0b29s
|
||||
c19uYW1lcyI6IFsibXVsdGlwbGNhdGlvbl90b29sIl19XUqaDQoKY3Jld190YXNrcxKLDQqIDVt7
|
||||
ImtleSI6ICIzMGYzMjg2M2EyZWI3OThkMTA5NmM5MDcwMjgwOTgzMCIsICJpZCI6ICIxNjhlOWNm
|
||||
Ny1hYWJjLTRkMGUtYTg1OS01ODEyZGM4MDg4NTYiLCAiZGVzY3JpcHRpb24iOiAiV2hhdCBpcyAy
|
||||
IHRpbWVzIDY/IFJldHVybiBvbmx5IHRoZSBudW1iZXIgYWZ0ZXIgdXNpbmcgdGhlIG11bHRpcGxp
|
||||
Y2F0aW9uIHRvb2wuIiwgImV4cGVjdGVkX291dHB1dCI6ICJ0aGUgcmVzdWx0IG9mIG11bHRpcGxp
|
||||
Y2F0aW9uIiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNl
|
||||
LCAiYWdlbnRfcm9sZSI6ICJXcml0ZXIiLCAiYWdlbnRfa2V5IjogImRhYjUyMWViZDMxYWUxMmZl
|
||||
ZTE4OWEzOGQzMDkwZDkzIiwgImNvbnRleHQiOiBudWxsLCAidG9vbHNfbmFtZXMiOiBbIm11bHRp
|
||||
cGxjYXRpb25fdG9vbCJdfSwgeyJrZXkiOiAiM2QwYmRlZTMxMjdhZjk5MGIzNjZjMTJkZGJkNGE4
|
||||
YTYiLCAiaWQiOiAiMDdkYmU0MzAtZDMxNC00MjgwLWEwODUtOGQ0MTQyZjNjZTFlIiwgImRlc2Ny
|
||||
aXB0aW9uIjogIldoYXQgaXMgMyB0aW1lcyAxPyBSZXR1cm4gb25seSB0aGUgbnVtYmVyIGFmdGVy
|
||||
IHVzaW5nIHRoZSBtdWx0aXBsaWNhdGlvbiB0b29sLiIsICJleHBlY3RlZF9vdXRwdXQiOiAidGhl
|
||||
IHJlc3VsdCBvZiBtdWx0aXBsaWNhdGlvbiIsICJhc3luY19leGVjdXRpb24/IjogZmFsc2UsICJo
|
||||
dW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAiV3JpdGVyIiwgImFnZW50X2tleSI6
|
||||
ICJkYWI1MjFlYmQzMWFlMTJmZWUxODlhMzhkMzA5MGQ5MyIsICJjb250ZXh0IjogbnVsbCwgInRv
|
||||
b2xzX25hbWVzIjogWyJtdWx0aXBsY2F0aW9uX3Rvb2wiXX0sIHsia2V5IjogIjMwZjMyODYzYTJl
|
||||
Yjc5OGQxMDk2YzkwNzAyODA5ODMwIiwgImlkIjogImFlYjJmMjk1LTI3NDUtNGYwMi05MjQxLWU3
|
||||
NTk2MjVjOWQyMCIsICJkZXNjcmlwdGlvbiI6ICJXaGF0IGlzIDIgdGltZXMgNj8gUmV0dXJuIG9u
|
||||
bHkgdGhlIG51bWJlciBhZnRlciB1c2luZyB0aGUgbXVsdGlwbGljYXRpb24gdG9vbC4iLCAiZXhw
|
||||
ZWN0ZWRfb3V0cHV0IjogInRoZSByZXN1bHQgb2YgbXVsdGlwbGljYXRpb24iLCAiYXN5bmNfZXhl
|
||||
Y3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9yb2xlIjogIldy
|
||||
aXRlciIsICJhZ2VudF9rZXkiOiAiZGFiNTIxZWJkMzFhZTEyZmVlMTg5YTM4ZDMwOTBkOTMiLCAi
|
||||
Y29udGV4dCI6IG51bGwsICJ0b29sc19uYW1lcyI6IFsibXVsdGlwbGNhdGlvbl90b29sIl19LCB7
|
||||
ImtleSI6ICIzZDBiZGVlMzEyN2FmOTkwYjM2NmMxMmRkYmQ0YThhNiIsICJpZCI6ICI5MGE0N2Fm
|
||||
Ny1jZjc5LTQ3NjYtOWJjNS02Nzg3MWMwOTFiOTYiLCAiZGVzY3JpcHRpb24iOiAiV2hhdCBpcyAz
|
||||
IHRpbWVzIDE/IFJldHVybiBvbmx5IHRoZSBudW1iZXIgYWZ0ZXIgdXNpbmcgdGhlIG11bHRpcGxp
|
||||
Y2F0aW9uIHRvb2wuIiwgImV4cGVjdGVkX291dHB1dCI6ICJ0aGUgcmVzdWx0IG9mIG11bHRpcGxp
|
||||
Y2F0aW9uIiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNl
|
||||
LCAiYWdlbnRfcm9sZSI6ICJXcml0ZXIiLCAiYWdlbnRfa2V5IjogImRhYjUyMWViZDMxYWUxMmZl
|
||||
ZTE4OWEzOGQzMDkwZDkzIiwgImNvbnRleHQiOiBudWxsLCAidG9vbHNfbmFtZXMiOiBbIm11bHRp
|
||||
cGxjYXRpb25fdG9vbCJdfV1KKgoIcGxhdGZvcm0SHgocbWFjT1MtMTQuMS4xLWFybTY0LWFybS02
|
||||
NGJpdEocChBwbGF0Zm9ybV9yZWxlYXNlEggKBjIzLjEuMEobCg9wbGF0Zm9ybV9zeXN0ZW0SCAoG
|
||||
RGFyd2luSnsKEHBsYXRmb3JtX3ZlcnNpb24SZwplRGFyd2luIEtlcm5lbCBWZXJzaW9uIDIzLjEu
|
||||
MDogTW9uIE9jdCAgOSAyMToyNzoyNCBQRFQgMjAyMzsgcm9vdDp4bnUtMTAwMDIuNDEuOX42L1JF
|
||||
TEVBU0VfQVJNNjRfVDYwMDBKCgoEY3B1cxICGAp6AhgBhQEAAQAAEo4CChDMsDVWCtNnTZd78P6M
|
||||
F0qHEghu/cLCLfIljioMVGFzayBDcmVhdGVkMAE5ALHzo7XF4hdBMCb0o7XF4hdKLgoIY3Jld19r
|
||||
ZXkSIgogYTBhYzk1MzU0ZDMyOWJhN2Y2OTQ4M2FkZmUwYzdkMjhKMQoHY3Jld19pZBImCiQ5Mzgz
|
||||
YzU2Yy1lNzQ3LTQwYmItOTlhYi01NGE2NGRkY2Q3YTlKLgoIdGFza19rZXkSIgogMzBmMzI4NjNh
|
||||
MmViNzk4ZDEwOTZjOTA3MDI4MDk4MzBKMQoHdGFza19pZBImCiQxNjhlOWNmNy1hYWJjLTRkMGUt
|
||||
YTg1OS01ODEyZGM4MDg4NTZ6AhgBhQEAAQAAEpUBChB1ZPMBfoWizT2O65qegWcGEgjmR3EI+Dhz
|
||||
KSoKVG9vbCBVc2FnZTABOUCLN6W1xeIXQWBWOKW1xeIXShoKDmNyZXdhaV92ZXJzaW9uEggKBjAu
|
||||
MzYuMEohCgl0b29sX25hbWUSFAoSbXVsdGlwbGNhdGlvbl90b29sSg4KCGF0dGVtcHRzEgIYAXoC
|
||||
GAGFAQABAAASkAIKEEukGnCGulTfJ1/e50UIF5ASCBeMmMmX2ss5Kg5UYXNrIEV4ZWN1dGlvbjAB
|
||||
OShR9KO1xeIXQQBL+KW1xeIXSi4KCGNyZXdfa2V5EiIKIGEwYWM5NTM1NGQzMjliYTdmNjk0ODNh
|
||||
ZGZlMGM3ZDI4SjEKB2NyZXdfaWQSJgokOTM4M2M1NmMtZTc0Ny00MGJiLTk5YWItNTRhNjRkZGNk
|
||||
N2E5Si4KCHRhc2tfa2V5EiIKIDMwZjMyODYzYTJlYjc5OGQxMDk2YzkwNzAyODA5ODMwSjEKB3Rh
|
||||
c2tfaWQSJgokMTY4ZTljZjctYWFiYy00ZDBlLWE4NTktNTgxMmRjODA4ODU2egIYAYUBAAEAABKO
|
||||
AgoQeq27u45vVnfO3QW8y5TkKhII8pwpZBclUSUqDFRhc2sgQ3JlYXRlZDABOXCRBaa1xeIXQeAl
|
||||
Bqa1xeIXSi4KCGNyZXdfa2V5EiIKIGEwYWM5NTM1NGQzMjliYTdmNjk0ODNhZGZlMGM3ZDI4SjEK
|
||||
B2NyZXdfaWQSJgokOTM4M2M1NmMtZTc0Ny00MGJiLTk5YWItNTRhNjRkZGNkN2E5Si4KCHRhc2tf
|
||||
a2V5EiIKIDNkMGJkZWUzMTI3YWY5OTBiMzY2YzEyZGRiZDRhOGE2SjEKB3Rhc2tfaWQSJgokMDdk
|
||||
YmU0MzAtZDMxNC00MjgwLWEwODUtOGQ0MTQyZjNjZTFlegIYAYUBAAEAABKVAQoQDpoau444Nc2P
|
||||
TpqGSwuJUBII3odk2PVsECQqClRvb2wgVXNhZ2UwATlQXjmntcXiF0GwSDqntcXiF0oaCg5jcmV3
|
||||
YWlfdmVyc2lvbhIICgYwLjM2LjBKIQoJdG9vbF9uYW1lEhQKEm11bHRpcGxjYXRpb25fdG9vbEoO
|
||||
CghhdHRlbXB0cxICGAF6AhgBhQEAAQAAEpACChBW89qgKwxZoE48iGgYORjmEggn0gOg6T0j3SoO
|
||||
VGFzayBFeGVjdXRpb24wATnYUAamtcXiF0GwUfSntcXiF0ouCghjcmV3X2tleRIiCiBhMGFjOTUz
|
||||
NTRkMzI5YmE3ZjY5NDgzYWRmZTBjN2QyOEoxCgdjcmV3X2lkEiYKJDkzODNjNTZjLWU3NDctNDBi
|
||||
Yi05OWFiLTU0YTY0ZGRjZDdhOUouCgh0YXNrX2tleRIiCiAzZDBiZGVlMzEyN2FmOTkwYjM2NmMx
|
||||
MmRkYmQ0YThhNkoxCgd0YXNrX2lkEiYKJDA3ZGJlNDMwLWQzMTQtNDI4MC1hMDg1LThkNDE0MmYz
|
||||
Y2UxZXoCGAGFAQABAAASjgIKECX4kiD6RrdHOsL/u1WPaKISCEn8hmiuaOxzKgxUYXNrIENyZWF0
|
||||
ZWQwATngAQCotcXiF0GwhgCotcXiF0ouCghjcmV3X2tleRIiCiBhMGFjOTUzNTRkMzI5YmE3ZjY5
|
||||
NDgzYWRmZTBjN2QyOEoxCgdjcmV3X2lkEiYKJDkzODNjNTZjLWU3NDctNDBiYi05OWFiLTU0YTY0
|
||||
ZGRjZDdhOUouCgh0YXNrX2tleRIiCiAzMGYzMjg2M2EyZWI3OThkMTA5NmM5MDcwMjgwOTgzMEox
|
||||
Cgd0YXNrX2lkEiYKJGFlYjJmMjk1LTI3NDUtNGYwMi05MjQxLWU3NTk2MjVjOWQyMHoCGAGFAQAB
|
||||
AAASlQEKEA/spc2u3GsQSPtfjOb6NJISCG3tEmcOqAoDKgpUb29sIFVzYWdlMAE58GZDqbXF4hdB
|
||||
IFlEqbXF4hdKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC4zNi4wSiEKCXRvb2xfbmFtZRIUChJtdWx0
|
||||
aXBsY2F0aW9uX3Rvb2xKDgoIYXR0ZW1wdHMSAhgBegIYAYUBAAEAABKQAgoQsO+zsd47DClQTmS7
|
||||
ZfZYLxII2UxCduX9osEqDlRhc2sgRXhlY3V0aW9uMAE5qLEAqLXF4hdByLEBqrXF4hdKLgoIY3Jl
|
||||
d19rZXkSIgogYTBhYzk1MzU0ZDMyOWJhN2Y2OTQ4M2FkZmUwYzdkMjhKMQoHY3Jld19pZBImCiQ5
|
||||
MzgzYzU2Yy1lNzQ3LTQwYmItOTlhYi01NGE2NGRkY2Q3YTlKLgoIdGFza19rZXkSIgogMzBmMzI4
|
||||
NjNhMmViNzk4ZDEwOTZjOTA3MDI4MDk4MzBKMQoHdGFza19pZBImCiRhZWIyZjI5NS0yNzQ1LTRm
|
||||
MDItOTI0MS1lNzU5NjI1YzlkMjB6AhgBhQEAAQAAEo4CChD55L/w1V+ezIjuajyG1hwUEggBdDur
|
||||
+CTqUCoMVGFzayBDcmVhdGVkMAE52AcPqrXF4hdBSJwPqrXF4hdKLgoIY3Jld19rZXkSIgogYTBh
|
||||
Yzk1MzU0ZDMyOWJhN2Y2OTQ4M2FkZmUwYzdkMjhKMQoHY3Jld19pZBImCiQ5MzgzYzU2Yy1lNzQ3
|
||||
LTQwYmItOTlhYi01NGE2NGRkY2Q3YTlKLgoIdGFza19rZXkSIgogM2QwYmRlZTMxMjdhZjk5MGIz
|
||||
NjZjMTJkZGJkNGE4YTZKMQoHdGFza19pZBImCiQ5MGE0N2FmNy1jZjc5LTQ3NjYtOWJjNS02Nzg3
|
||||
MWMwOTFiOTZ6AhgBhQEAAQAAEpUBChA+cdY4kcsaUDolyJw3c952EggtUbX8zXBaySoKVG9vbCBV
|
||||
c2FnZTABOaAHUKu1xeIXQcDSUKu1xeIXShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuMzYuMEohCgl0
|
||||
b29sX25hbWUSFAoSbXVsdGlwbGNhdGlvbl90b29sSg4KCGF0dGVtcHRzEgIYAXoCGAGFAQABAAAS
|
||||
kAIKEAvnVK0WhsX8u4xShcr/sooSCC+aS9IRpThCKg5UYXNrIEV4ZWN1dGlvbjABOUDHD6q1xeIX
|
||||
QVC9IKy1xeIXSi4KCGNyZXdfa2V5EiIKIGEwYWM5NTM1NGQzMjliYTdmNjk0ODNhZGZlMGM3ZDI4
|
||||
SjEKB2NyZXdfaWQSJgokOTM4M2M1NmMtZTc0Ny00MGJiLTk5YWItNTRhNjRkZGNkN2E5Si4KCHRh
|
||||
c2tfa2V5EiIKIDNkMGJkZWUzMTI3YWY5OTBiMzY2YzEyZGRiZDRhOGE2SjEKB3Rhc2tfaWQSJgok
|
||||
OTBhNDdhZjctY2Y3OS00NzY2LTliYzUtNjc4NzFjMDkxYjk2egIYAYUBAAEAABKrCwoQfae3w+r8
|
||||
n0qGJnp7DP6RtxIILhPziA5VzRwqDENyZXcgQ3JlYXRlZDABOZipkrW1xeIXQZDIlLW1xeIXShoK
|
||||
DmNyZXdhaV92ZXJzaW9uEggKBjAuMzYuMEoaCg5weXRob25fdmVyc2lvbhIICgYzLjExLjVKLgoI
|
||||
Y3Jld19rZXkSIgogYzk3YjVmZWI1ZDFiNjZiYjU5MDA2YWFhMDFhMjljZDZKMQoHY3Jld19pZBIm
|
||||
CiQ2M2Y2MGU1Yi1kMjZkLTQwZjMtYTQyMC0wNzQ3Y2MwOWM5YWRKHAoMY3Jld19wcm9jZXNzEgwK
|
||||
CnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkSAhABShoKFGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIY
|
||||
AUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgBStIDCgtjcmV3X2FnZW50cxLCAwq/A1t7Imtl
|
||||
eSI6ICIwN2Q5OWI2MzA0MTFkMzVmZDkwNDdhNTMyZDUzZGRhNyIsICJpZCI6ICJhMGJlYjc4ZS04
|
||||
ZGUzLTQ5YjEtYWRkZS1mODg3NWMzNjM3ZGYiLCAicm9sZSI6ICJSZXNlYXJjaGVyIiwgImdvYWwi
|
||||
OiAiWW91IHJlc2VhcmNoIGFib3V0IG1hdGguIiwgImJhY2tzdG9yeSI6ICJZb3UncmUgYW4gZXhw
|
||||
ZXJ0IGluIHJlc2VhcmNoIGFuZCB5b3UgbG92ZSB0byBsZWFybiBuZXcgdGhpbmdzLiIsICJ2ZXJi
|
||||
b3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyNSwgIm1heF9ycG0iOiBudWxsLCAiaTE4biI6IG51
|
||||
bGwsICJsbG0iOiAie1wibmFtZVwiOiBudWxsLCBcIm1vZGVsX25hbWVcIjogXCJncHQtNG9cIiwg
|
||||
XCJ0ZW1wZXJhdHVyZVwiOiAwLjcsIFwiY2xhc3NcIjogXCJDaGF0T3BlbkFJXCJ9IiwgImRlbGVn
|
||||
YXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgInRvb2xzX25hbWVzIjogW119XUqWAwoKY3Jld190YXNr
|
||||
cxKHAwqEA1t7ImtleSI6ICI2Mzk5NjUxN2YzZjNmMWM5NGQ2YmI2MTdhYTBiMWM0ZiIsICJpZCI6
|
||||
ICIwMmNiOWIyYS0yODIyLTQwNTYtYjQ5MC04YjA0YzA2MTg2M2IiLCAiZGVzY3JpcHRpb24iOiAi
|
||||
UmVzZWFyY2ggYSB0b3BpYyB0byB0ZWFjaCBhIGtpZCBhZ2VkIDYgYWJvdXQgbWF0aC4iLCAiZXhw
|
||||
ZWN0ZWRfb3V0cHV0IjogIkEgdG9waWMsIGV4cGxhbmF0aW9uLCBhbmdsZSwgYW5kIGV4YW1wbGVz
|
||||
LiIsICJhc3luY19leGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFn
|
||||
ZW50X3JvbGUiOiAiUmVzZWFyY2hlciIsICJhZ2VudF9rZXkiOiAiMDdkOTliNjMwNDExZDM1ZmQ5
|
||||
MDQ3YTUzMmQ1M2RkYTciLCAiY29udGV4dCI6IG51bGwsICJ0b29sc19uYW1lcyI6IFtdfV1KKgoI
|
||||
cGxhdGZvcm0SHgocbWFjT1MtMTQuMS4xLWFybTY0LWFybS02NGJpdEocChBwbGF0Zm9ybV9yZWxl
|
||||
YXNlEggKBjIzLjEuMEobCg9wbGF0Zm9ybV9zeXN0ZW0SCAoGRGFyd2luSnsKEHBsYXRmb3JtX3Zl
|
||||
cnNpb24SZwplRGFyd2luIEtlcm5lbCBWZXJzaW9uIDIzLjEuMDogTW9uIE9jdCAgOSAyMToyNzoy
|
||||
NCBQRFQgMjAyMzsgcm9vdDp4bnUtMTAwMDIuNDEuOX42L1JFTEVBU0VfQVJNNjRfVDYwMDBKCgoE
|
||||
Y3B1cxICGAp6AhgBhQEAAQAAEo4CChDwvE8C6FMSvgaW9DsUngzEEgi69DWPEIv7/ioMVGFzayBD
|
||||
cmVhdGVkMAE5QJOmtbXF4hdBSOWmtbXF4hdKLgoIY3Jld19rZXkSIgogYzk3YjVmZWI1ZDFiNjZi
|
||||
YjU5MDA2YWFhMDFhMjljZDZKMQoHY3Jld19pZBImCiQ2M2Y2MGU1Yi1kMjZkLTQwZjMtYTQyMC0w
|
||||
NzQ3Y2MwOWM5YWRKLgoIdGFza19rZXkSIgogNjM5OTY1MTdmM2YzZjFjOTRkNmJiNjE3YWEwYjFj
|
||||
NGZKMQoHdGFza19pZBImCiQwMmNiOWIyYS0yODIyLTQwNTYtYjQ5MC04YjA0YzA2MTg2M2J6AhgB
|
||||
hQEAAQAAEpACChA9ji0VC42jOLjDFsSGAZehEgi88WVi+J8WZyoOVGFzayBFeGVjdXRpb24wATlA
|
||||
EKe1tcXiF0GwOXS9tcXiF0ouCghjcmV3X2tleRIiCiBjOTdiNWZlYjVkMWI2NmJiNTkwMDZhYWEw
|
||||
MWEyOWNkNkoxCgdjcmV3X2lkEiYKJDYzZjYwZTViLWQyNmQtNDBmMy1hNDIwLTA3NDdjYzA5Yzlh
|
||||
ZEouCgh0YXNrX2tleRIiCiA2Mzk5NjUxN2YzZjNmMWM5NGQ2YmI2MTdhYTBiMWM0ZkoxCgd0YXNr
|
||||
X2lkEiYKJDAyY2I5YjJhLTI4MjItNDA1Ni1iNDkwLThiMDRjMDYxODYzYnoCGAGFAQABAAASqwsK
|
||||
EOSKFi2MNd2ArhJhwSRFLU8SCLUBjfAc1xVOKgxDcmV3IENyZWF0ZWQwATlAcNi/tcXiF0G4zdq/
|
||||
tcXiF0oaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjM2LjBKGgoOcHl0aG9uX3ZlcnNpb24SCAoGMy4x
|
||||
MS41Si4KCGNyZXdfa2V5EiIKIGM5N2I1ZmViNWQxYjY2YmI1OTAwNmFhYTAxYTI5Y2Q2SjEKB2Ny
|
||||
ZXdfaWQSJgokNmFlNzhhZjEtNDE5Ny00ODU2LWE1OTItYWEzZGNmMTI5OGJhShwKDGNyZXdfcHJv
|
||||
Y2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJlcl9vZl90
|
||||
YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrSAwoLY3Jld19hZ2VudHMSwgMK
|
||||
vwNbeyJrZXkiOiAiMDdkOTliNjMwNDExZDM1ZmQ5MDQ3YTUzMmQ1M2RkYTciLCAiaWQiOiAiYWUz
|
||||
ZjEwYmYtNThlMy00NjNjLWI4YTUtMDZjNTAxYTVlNWY0IiwgInJvbGUiOiAiUmVzZWFyY2hlciIs
|
||||
ICJnb2FsIjogIllvdSByZXNlYXJjaCBhYm91dCBtYXRoLiIsICJiYWNrc3RvcnkiOiAiWW91J3Jl
|
||||
IGFuIGV4cGVydCBpbiByZXNlYXJjaCBhbmQgeW91IGxvdmUgdG8gbGVhcm4gbmV3IHRoaW5ncy4i
|
||||
LCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjUsICJtYXhfcnBtIjogbnVsbCwgImkx
|
||||
OG4iOiBudWxsLCAibGxtIjogIntcIm5hbWVcIjogbnVsbCwgXCJtb2RlbF9uYW1lXCI6IFwiZ3B0
|
||||
LTRvXCIsIFwidGVtcGVyYXR1cmVcIjogMC43LCBcImNsYXNzXCI6IFwiQ2hhdE9wZW5BSVwifSIs
|
||||
ICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJ0b29sc19uYW1lcyI6IFtdfV1KlgMKCmNy
|
||||
ZXdfdGFza3MShwMKhANbeyJrZXkiOiAiNjM5OTY1MTdmM2YzZjFjOTRkNmJiNjE3YWEwYjFjNGYi
|
||||
LCAiaWQiOiAiNTQ4NzY5YWUtMmFjZS00NzIwLTlhYWEtZWY3YmVjZGRmMjAyIiwgImRlc2NyaXB0
|
||||
aW9uIjogIlJlc2VhcmNoIGEgdG9waWMgdG8gdGVhY2ggYSBraWQgYWdlZCA2IGFib3V0IG1hdGgu
|
||||
IiwgImV4cGVjdGVkX291dHB1dCI6ICJBIHRvcGljLCBleHBsYW5hdGlvbiwgYW5nbGUsIGFuZCBl
|
||||
eGFtcGxlcy4iLCAiYXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFs
|
||||
c2UsICJhZ2VudF9yb2xlIjogIlJlc2VhcmNoZXIiLCAiYWdlbnRfa2V5IjogIjA3ZDk5YjYzMDQx
|
||||
MWQzNWZkOTA0N2E1MzJkNTNkZGE3IiwgImNvbnRleHQiOiBudWxsLCAidG9vbHNfbmFtZXMiOiBb
|
||||
XX1dSioKCHBsYXRmb3JtEh4KHG1hY09TLTE0LjEuMS1hcm02NC1hcm0tNjRiaXRKHAoQcGxhdGZv
|
||||
cm1fcmVsZWFzZRIICgYyMy4xLjBKGwoPcGxhdGZvcm1fc3lzdGVtEggKBkRhcndpbkp7ChBwbGF0
|
||||
Zm9ybV92ZXJzaW9uEmcKZURhcndpbiBLZXJuZWwgVmVyc2lvbiAyMy4xLjA6IE1vbiBPY3QgIDkg
|
||||
MjE6Mjc6MjQgUERUIDIwMjM7IHJvb3Q6eG51LTEwMDAyLjQxLjl+Ni9SRUxFQVNFX0FSTTY0X1Q2
|
||||
MDAwSgoKBGNwdXMSAhgKegIYAYUBAAEAABKOAgoQJwZSCcuSu3diAuOYiVdE2BIIeF1BeIAKnP4q
|
||||
DFRhc2sgQ3JlYXRlZDABOYhX77+1xeIXQcCh77+1xeIXSi4KCGNyZXdfa2V5EiIKIGM5N2I1ZmVi
|
||||
NWQxYjY2YmI1OTAwNmFhYTAxYTI5Y2Q2SjEKB2NyZXdfaWQSJgokNmFlNzhhZjEtNDE5Ny00ODU2
|
||||
LWE1OTItYWEzZGNmMTI5OGJhSi4KCHRhc2tfa2V5EiIKIDYzOTk2NTE3ZjNmM2YxYzk0ZDZiYjYx
|
||||
N2FhMGIxYzRmSjEKB3Rhc2tfaWQSJgokNTQ4NzY5YWUtMmFjZS00NzIwLTlhYWEtZWY3YmVjZGRm
|
||||
MjAyegIYAYUBAAEAABKQAgoQxBgL6L3Ce74Cu4q6j0ErDRIIEnXenwnk/A4qDlRhc2sgRXhlY3V0
|
||||
aW9uMAE5uMzvv7XF4hdBAEPaxrXF4hdKLgoIY3Jld19rZXkSIgogYzk3YjVmZWI1ZDFiNjZiYjU5
|
||||
MDA2YWFhMDFhMjljZDZKMQoHY3Jld19pZBImCiQ2YWU3OGFmMS00MTk3LTQ4NTYtYTU5Mi1hYTNk
|
||||
Y2YxMjk4YmFKLgoIdGFza19rZXkSIgogNjM5OTY1MTdmM2YzZjFjOTRkNmJiNjE3YWEwYjFjNGZK
|
||||
MQoHdGFza19pZBImCiQ1NDg3NjlhZS0yYWNlLTQ3MjAtOWFhYS1lZjdiZWNkZGYyMDJ6AhgBhQEA
|
||||
AQAAEo0MChB2PHWFIMgXT4sbnL1Fk9tqEgj1iM6d8aLAFyoMQ3JldyBDcmVhdGVkMAE5SKovx7XF
|
||||
4hdBwAcyx7XF4hdKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC4zNi4wShoKDnB5dGhvbl92ZXJzaW9u
|
||||
EggKBjMuMTEuNUouCghjcmV3X2tleRIiCiA4YzI3NTJmNDllNWI5ZDJiNjhjYjM1Y2FjOGZjYzg2
|
||||
ZEoxCgdjcmV3X2lkEiYKJDA2MTdhZjU1LWEwNjQtNDEwMi05YjQ0LThhMThiZWU0NTg3OEocCgxj
|
||||
cmV3X3Byb2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtjcmV3X21lbW9yeRICEABKGgoUY3Jld19udW1i
|
||||
ZXJfb2ZfdGFza3MSAhgBShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxICGAFK/gQKC2NyZXdfYWdl
|
||||
bnRzEu4ECusEW3sia2V5IjogIjhiZDIxMzliNTk3NTE4MTUwNmU0MWZkOWM0NTYzZDc1IiwgImlk
|
||||
IjogIjc4YmM1N2I4LWIwZTgtNDZlNy04OTIzLTQ2ZDJlMWQ4MjQwNyIsICJyb2xlIjogIlJlc2Vh
|
||||
cmNoZXIiLCAiZ29hbCI6ICJNYWtlIHRoZSBiZXN0IHJlc2VhcmNoIGFuZCBhbmFseXNpcyBvbiBj
|
||||
b250ZW50IGFib3V0IEFJIGFuZCBBSSBhZ2VudHMiLCAiYmFja3N0b3J5IjogIllvdSdyZSBhbiBl
|
||||
eHBlcnQgcmVzZWFyY2hlciwgc3BlY2lhbGl6ZWQgaW4gdGVjaG5vbG9neSwgc29mdHdhcmUgZW5n
|
||||
aW5lZXJpbmcsIEFJIGFuZCBzdGFydHVwcy4gWW91IHdvcmsgYXMgYSBmcmVlbGFuY2VyIGFuZCBp
|
||||
cyBub3cgd29ya2luZyBvbiBkb2luZyByZXNlYXJjaCBhbmQgYW5hbHlzaXMgZm9yIGEgbmV3IGN1
|
||||
c3RvbWVyLiIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyNSwgIm1heF9ycG0iOiBu
|
||||
dWxsLCAiaTE4biI6IG51bGwsICJsbG0iOiAie1wibmFtZVwiOiBudWxsLCBcIm1vZGVsX25hbWVc
|
||||
IjogXCJncHQtNG9cIiwgXCJ0ZW1wZXJhdHVyZVwiOiAwLjcsIFwiY2xhc3NcIjogXCJDaGF0T3Bl
|
||||
bkFJXCJ9IiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgInRvb2xzX25hbWVzIjogW119
|
||||
XUrMAgoKY3Jld190YXNrcxK9Agq6Alt7ImtleSI6ICIwZDY4NWEyMTk5NGQ5NDkwOTdiYzVhNTZk
|
||||
NzM3ZTZkMSIsICJpZCI6ICI0M2JjZTUwNy0yZGJmLTRiMDMtYTIyMy0zYzMxMmU1MTI4YWQiLCAi
|
||||
ZGVzY3JpcHRpb24iOiAiU2F5IEhpIiwgImV4cGVjdGVkX291dHB1dCI6ICJUaGUgd29yZDogSGki
|
||||
LCAiYXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2Vu
|
||||
dF9yb2xlIjogIlJlc2VhcmNoZXIiLCAiYWdlbnRfa2V5IjogIjhiZDIxMzliNTk3NTE4MTUwNmU0
|
||||
MWZkOWM0NTYzZDc1IiwgImNvbnRleHQiOiBudWxsLCAidG9vbHNfbmFtZXMiOiBbXX1dSioKCHBs
|
||||
YXRmb3JtEh4KHG1hY09TLTE0LjEuMS1hcm02NC1hcm0tNjRiaXRKHAoQcGxhdGZvcm1fcmVsZWFz
|
||||
ZRIICgYyMy4xLjBKGwoPcGxhdGZvcm1fc3lzdGVtEggKBkRhcndpbkp7ChBwbGF0Zm9ybV92ZXJz
|
||||
aW9uEmcKZURhcndpbiBLZXJuZWwgVmVyc2lvbiAyMy4xLjA6IE1vbiBPY3QgIDkgMjE6Mjc6MjQg
|
||||
UERUIDIwMjM7IHJvb3Q6eG51LTEwMDAyLjQxLjl+Ni9SRUxFQVNFX0FSTTY0X1Q2MDAwSgoKBGNw
|
||||
dXMSAhgKegIYAYUBAAEAABKOAgoQgFFdbbcq9b6XpdCgV4ygHxII5FvLDHBJWfYqDFRhc2sgQ3Jl
|
||||
YXRlZDABOcB3Sce1xeIXQfDsSce1xeIXSi4KCGNyZXdfa2V5EiIKIDhjMjc1MmY0OWU1YjlkMmI2
|
||||
OGNiMzVjYWM4ZmNjODZkSjEKB2NyZXdfaWQSJgokMDYxN2FmNTUtYTA2NC00MTAyLTliNDQtOGEx
|
||||
OGJlZTQ1ODc4Si4KCHRhc2tfa2V5EiIKIDBkNjg1YTIxOTk0ZDk0OTA5N2JjNWE1NmQ3MzdlNmQx
|
||||
SjEKB3Rhc2tfaWQSJgokNDNiY2U1MDctMmRiZi00YjAzLWEyMjMtM2MzMTJlNTEyOGFkegIYAYUB
|
||||
AAEAABKQAgoQrD1woM4vvML78Ycv2kKJPBIIQiPC5tnfBsEqDlRhc2sgRXhlY3V0aW9uMAE5uB9K
|
||||
x7XF4hdB0DoqyLXF4hdKLgoIY3Jld19rZXkSIgogOGMyNzUyZjQ5ZTViOWQyYjY4Y2IzNWNhYzhm
|
||||
Y2M4NmRKMQoHY3Jld19pZBImCiQwNjE3YWY1NS1hMDY0LTQxMDItOWI0NC04YTE4YmVlNDU4NzhK
|
||||
LgoIdGFza19rZXkSIgogMGQ2ODVhMjE5OTRkOTQ5MDk3YmM1YTU2ZDczN2U2ZDFKMQoHdGFza19p
|
||||
ZBImCiQ0M2JjZTUwNy0yZGJmLTRiMDMtYTIyMy0zYzMxMmU1MTI4YWR6AhgBhQEAAQAAEskSChDy
|
||||
v1twhKVTS2/hcmcIXG8LEginut5ahEsb9yoMQ3JldyBDcmVhdGVkMAE5eMNWyrXF4hdBUBFZyrXF
|
||||
4hdKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC4zNi4wShoKDnB5dGhvbl92ZXJzaW9uEggKBjMuMTEu
|
||||
NUouCghjcmV3X2tleRIiCiBlM2ZkYTBmMzExMGZlODBiMTg5NDdjMDE0NzE0MzBhNEoxCgdjcmV3
|
||||
X2lkEiYKJGJiZmUxOTdkLWFmM2QtNDUwYy04NzlhLWNkOWQyODQyYzk5NUoeCgxjcmV3X3Byb2Nl
|
||||
c3MSDgoMaGllcmFyY2hpY2FsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJlcl9vZl90
|
||||
YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAkrFCQoLY3Jld19hZ2VudHMStQkK
|
||||
sglbeyJrZXkiOiAiOGJkMjEzOWI1OTc1MTgxNTA2ZTQxZmQ5YzQ1NjNkNzUiLCAiaWQiOiAiNzhi
|
||||
YzU3YjgtYjBlOC00NmU3LTg5MjMtNDZkMmUxZDgyNDA3IiwgInJvbGUiOiAiUmVzZWFyY2hlciIs
|
||||
ICJnb2FsIjogIk1ha2UgdGhlIGJlc3QgcmVzZWFyY2ggYW5kIGFuYWx5c2lzIG9uIGNvbnRlbnQg
|
||||
YWJvdXQgQUkgYW5kIEFJIGFnZW50cyIsICJiYWNrc3RvcnkiOiAiWW91J3JlIGFuIGV4cGVydCBy
|
||||
ZXNlYXJjaGVyLCBzcGVjaWFsaXplZCBpbiB0ZWNobm9sb2d5LCBzb2Z0d2FyZSBlbmdpbmVlcmlu
|
||||
ZywgQUkgYW5kIHN0YXJ0dXBzLiBZb3Ugd29yayBhcyBhIGZyZWVsYW5jZXIgYW5kIGlzIG5vdyB3
|
||||
b3JraW5nIG9uIGRvaW5nIHJlc2VhcmNoIGFuZCBhbmFseXNpcyBmb3IgYSBuZXcgY3VzdG9tZXIu
|
||||
IiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDI1LCAibWF4X3JwbSI6IG51bGwsICJp
|
||||
MThuIjogbnVsbCwgImxsbSI6ICJ7XCJuYW1lXCI6IG51bGwsIFwibW9kZWxfbmFtZVwiOiBcImdw
|
||||
dC00b1wiLCBcInRlbXBlcmF0dXJlXCI6IDAuNywgXCJjbGFzc1wiOiBcIkNoYXRPcGVuQUlcIn0i
|
||||
LCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAidG9vbHNfbmFtZXMiOiBbXX0sIHsia2V5
|
||||
IjogIjlhNTAxNWVmNDg5NWRjNjI3OGQ1NDgxOGJhNDQ2YWY3IiwgImlkIjogIjk2YzIxOTk1LWFl
|
||||
ZDItNGJjNC1iYjY4LTdiOTA3ZTYzYjQyNSIsICJyb2xlIjogIlNlbmlvciBXcml0ZXIiLCAiZ29h
|
||||
bCI6ICJXcml0ZSB0aGUgYmVzdCBjb250ZW50IGFib3V0IEFJIGFuZCBBSSBhZ2VudHMuIiwgImJh
|
||||
Y2tzdG9yeSI6ICJZb3UncmUgYSBzZW5pb3Igd3JpdGVyLCBzcGVjaWFsaXplZCBpbiB0ZWNobm9s
|
||||
b2d5LCBzb2Z0d2FyZSBlbmdpbmVlcmluZywgQUkgYW5kIHN0YXJ0dXBzLiBZb3Ugd29yayBhcyBh
|
||||
IGZyZWVsYW5jZXIgYW5kIGFyZSBub3cgd29ya2luZyBvbiB3cml0aW5nIGNvbnRlbnQgZm9yIGEg
|
||||
bmV3IGN1c3RvbWVyLiIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyNSwgIm1heF9y
|
||||
cG0iOiBudWxsLCAiaTE4biI6IG51bGwsICJsbG0iOiAie1wibmFtZVwiOiBudWxsLCBcIm1vZGVs
|
||||
X25hbWVcIjogXCJncHQtNG9cIiwgXCJ0ZW1wZXJhdHVyZVwiOiAwLjcsIFwiY2xhc3NcIjogXCJD
|
||||
aGF0T3BlbkFJXCJ9IiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgInRvb2xzX25hbWVz
|
||||
IjogW119XUq/BAoKY3Jld190YXNrcxKwBAqtBFt7ImtleSI6ICI1ZmE2NWMwNmE5ZTMxZjJjNjk1
|
||||
NDMyNjY4YWNkNjJkZCIsICJpZCI6ICJjNTFlMzZjZC1iMzc3LTRiMjMtOTY1ZC0xMjE4ZjAxN2Rl
|
||||
NTkiLCAiZGVzY3JpcHRpb24iOiAiQ29tZSB1cCB3aXRoIGEgbGlzdCBvZiA1IGludGVyZXN0aW5n
|
||||
IGlkZWFzIHRvIGV4cGxvcmUgZm9yIGFuIGFydGljbGUsIHRoZW4gd3JpdGUgb25lIGFtYXppbmcg
|
||||
cGFyYWdyYXBoIGhpZ2hsaWdodCBmb3IgZWFjaCBpZGVhIHRoYXQgc2hvd2Nhc2VzIGhvdyBnb29k
|
||||
IGFuIGFydGljbGUgYWJvdXQgdGhpcyB0b3BpYyBjb3VsZCBiZS4gUmV0dXJuIHRoZSBsaXN0IG9m
|
||||
IGlkZWFzIHdpdGggdGhlaXIgcGFyYWdyYXBoIGFuZCB5b3VyIG5vdGVzLiIsICJleHBlY3RlZF9v
|
||||
dXRwdXQiOiAiNSBidWxsZXQgcG9pbnRzIHdpdGggYSBwYXJhZ3JhcGggZm9yIGVhY2ggaWRlYS4i
|
||||
LCAiYXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2Vu
|
||||
dF9yb2xlIjogIk5vbmUiLCAiYWdlbnRfa2V5IjogbnVsbCwgImNvbnRleHQiOiBudWxsLCAidG9v
|
||||
bHNfbmFtZXMiOiBbXX1dSioKCHBsYXRmb3JtEh4KHG1hY09TLTE0LjEuMS1hcm02NC1hcm0tNjRi
|
||||
aXRKHAoQcGxhdGZvcm1fcmVsZWFzZRIICgYyMy4xLjBKGwoPcGxhdGZvcm1fc3lzdGVtEggKBkRh
|
||||
cndpbkp7ChBwbGF0Zm9ybV92ZXJzaW9uEmcKZURhcndpbiBLZXJuZWwgVmVyc2lvbiAyMy4xLjA6
|
||||
IE1vbiBPY3QgIDkgMjE6Mjc6MjQgUERUIDIwMjM7IHJvb3Q6eG51LTEwMDAyLjQxLjl+Ni9SRUxF
|
||||
QVNFX0FSTTY0X1Q2MDAwSgoKBGNwdXMSAhgKegIYAYUBAAEAABLJEgoQC4ERVCPi0URQcsRKT+/y
|
||||
GxIInSinsu8yhJsqDENyZXcgQ3JlYXRlZDABOcAcwM61xeIXQaiRws61xeIXShoKDmNyZXdhaV92
|
||||
ZXJzaW9uEggKBjAuMzYuMEoaCg5weXRob25fdmVyc2lvbhIICgYzLjExLjVKLgoIY3Jld19rZXkS
|
||||
IgogZTNmZGEwZjMxMTBmZTgwYjE4OTQ3YzAxNDcxNDMwYTRKMQoHY3Jld19pZBImCiQxMTUxYTA2
|
||||
Zi02YjdhLTQzZGYtOWZjNi05MzJmYTYzY2RhZjRKHgoMY3Jld19wcm9jZXNzEg4KDGhpZXJhcmNo
|
||||
aWNhbEoRCgtjcmV3X21lbW9yeRICEABKGgoUY3Jld19udW1iZXJfb2ZfdGFza3MSAhgBShsKFWNy
|
||||
ZXdfbnVtYmVyX29mX2FnZW50cxICGAJKxQkKC2NyZXdfYWdlbnRzErUJCrIJW3sia2V5IjogIjhi
|
||||
ZDIxMzliNTk3NTE4MTUwNmU0MWZkOWM0NTYzZDc1IiwgImlkIjogIjc4YmM1N2I4LWIwZTgtNDZl
|
||||
Ny04OTIzLTQ2ZDJlMWQ4MjQwNyIsICJyb2xlIjogIlJlc2VhcmNoZXIiLCAiZ29hbCI6ICJNYWtl
|
||||
IHRoZSBiZXN0IHJlc2VhcmNoIGFuZCBhbmFseXNpcyBvbiBjb250ZW50IGFib3V0IEFJIGFuZCBB
|
||||
SSBhZ2VudHMiLCAiYmFja3N0b3J5IjogIllvdSdyZSBhbiBleHBlcnQgcmVzZWFyY2hlciwgc3Bl
|
||||
Y2lhbGl6ZWQgaW4gdGVjaG5vbG9neSwgc29mdHdhcmUgZW5naW5lZXJpbmcsIEFJIGFuZCBzdGFy
|
||||
dHVwcy4gWW91IHdvcmsgYXMgYSBmcmVlbGFuY2VyIGFuZCBpcyBub3cgd29ya2luZyBvbiBkb2lu
|
||||
ZyByZXNlYXJjaCBhbmQgYW5hbHlzaXMgZm9yIGEgbmV3IGN1c3RvbWVyLiIsICJ2ZXJib3NlPyI6
|
||||
IGZhbHNlLCAibWF4X2l0ZXIiOiAyNSwgIm1heF9ycG0iOiBudWxsLCAiaTE4biI6IG51bGwsICJs
|
||||
bG0iOiAie1wibmFtZVwiOiBudWxsLCBcIm1vZGVsX25hbWVcIjogXCJncHQtNG9cIiwgXCJ0ZW1w
|
||||
ZXJhdHVyZVwiOiAwLjcsIFwiY2xhc3NcIjogXCJDaGF0T3BlbkFJXCJ9IiwgImRlbGVnYXRpb25f
|
||||
ZW5hYmxlZD8iOiBmYWxzZSwgInRvb2xzX25hbWVzIjogW119LCB7ImtleSI6ICI5YTUwMTVlZjQ4
|
||||
OTVkYzYyNzhkNTQ4MThiYTQ0NmFmNyIsICJpZCI6ICI5NmMyMTk5NS1hZWQyLTRiYzQtYmI2OC03
|
||||
YjkwN2U2M2I0MjUiLCAicm9sZSI6ICJTZW5pb3IgV3JpdGVyIiwgImdvYWwiOiAiV3JpdGUgdGhl
|
||||
IGJlc3QgY29udGVudCBhYm91dCBBSSBhbmQgQUkgYWdlbnRzLiIsICJiYWNrc3RvcnkiOiAiWW91
|
||||
J3JlIGEgc2VuaW9yIHdyaXRlciwgc3BlY2lhbGl6ZWQgaW4gdGVjaG5vbG9neSwgc29mdHdhcmUg
|
||||
ZW5naW5lZXJpbmcsIEFJIGFuZCBzdGFydHVwcy4gWW91IHdvcmsgYXMgYSBmcmVlbGFuY2VyIGFu
|
||||
ZCBhcmUgbm93IHdvcmtpbmcgb24gd3JpdGluZyBjb250ZW50IGZvciBhIG5ldyBjdXN0b21lci4i
|
||||
LCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjUsICJtYXhfcnBtIjogbnVsbCwgImkx
|
||||
OG4iOiBudWxsLCAibGxtIjogIntcIm5hbWVcIjogbnVsbCwgXCJtb2RlbF9uYW1lXCI6IFwiZ3B0
|
||||
LTRvXCIsIFwidGVtcGVyYXR1cmVcIjogMC43LCBcImNsYXNzXCI6IFwiQ2hhdE9wZW5BSVwifSIs
|
||||
ICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJ0b29sc19uYW1lcyI6IFtdfV1KvwQKCmNy
|
||||
ZXdfdGFza3MSsAQKrQRbeyJrZXkiOiAiNWZhNjVjMDZhOWUzMWYyYzY5NTQzMjY2OGFjZDYyZGQi
|
||||
LCAiaWQiOiAiMDIzOGY1NWUtZTMwYy00MDIwLWE0ZmQtNWY2ZmUzNjE1NjA4IiwgImRlc2NyaXB0
|
||||
aW9uIjogIkNvbWUgdXAgd2l0aCBhIGxpc3Qgb2YgNSBpbnRlcmVzdGluZyBpZGVhcyB0byBleHBs
|
||||
b3JlIGZvciBhbiBhcnRpY2xlLCB0aGVuIHdyaXRlIG9uZSBhbWF6aW5nIHBhcmFncmFwaCBoaWdo
|
||||
bGlnaHQgZm9yIGVhY2ggaWRlYSB0aGF0IHNob3djYXNlcyBob3cgZ29vZCBhbiBhcnRpY2xlIGFi
|
||||
b3V0IHRoaXMgdG9waWMgY291bGQgYmUuIFJldHVybiB0aGUgbGlzdCBvZiBpZGVhcyB3aXRoIHRo
|
||||
ZWlyIHBhcmFncmFwaCBhbmQgeW91ciBub3Rlcy4iLCAiZXhwZWN0ZWRfb3V0cHV0IjogIjUgYnVs
|
||||
bGV0IHBvaW50cyB3aXRoIGEgcGFyYWdyYXBoIGZvciBlYWNoIGlkZWEuIiwgImFzeW5jX2V4ZWN1
|
||||
dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJOb25l
|
||||
IiwgImFnZW50X2tleSI6IG51bGwsICJjb250ZXh0IjogbnVsbCwgInRvb2xzX25hbWVzIjogW119
|
||||
XUoqCghwbGF0Zm9ybRIeChxtYWNPUy0xNC4xLjEtYXJtNjQtYXJtLTY0Yml0ShwKEHBsYXRmb3Jt
|
||||
X3JlbGVhc2USCAoGMjMuMS4wShsKD3BsYXRmb3JtX3N5c3RlbRIICgZEYXJ3aW5KewoQcGxhdGZv
|
||||
cm1fdmVyc2lvbhJnCmVEYXJ3aW4gS2VybmVsIFZlcnNpb24gMjMuMS4wOiBNb24gT2N0ICA5IDIx
|
||||
OjI3OjI0IFBEVCAyMDIzOyByb290OnhudS0xMDAwMi40MS45fjYvUkVMRUFTRV9BUk02NF9UNjAw
|
||||
MEoKCgRjcHVzEgIYCnoCGAGFAQABAAASwRUKEK+2FWN+LUsj3/10yDBx5MMSCPaor0csAVI6KgxD
|
||||
cmV3IENyZWF0ZWQwATlwEcXPtcXiF0FQscfPtcXiF0oaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjM2
|
||||
LjBKGgoOcHl0aG9uX3ZlcnNpb24SCAoGMy4xMS41Si4KCGNyZXdfa2V5EiIKIGQzODQ2YzlkMjc2
|
||||
ZThlNmU0M2UzMWY2MTc2MzU3YjRmSjEKB2NyZXdfaWQSJgokYzE0MGJlNTgtOTJjZS00YzQyLWJk
|
||||
YjQtOThjNTlmMGUzYzAxShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVt
|
||||
b3J5EgIQAEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGAJKGwoVY3Jld19udW1iZXJfb2ZfYWdl
|
||||
bnRzEgIYAkrFCQoLY3Jld19hZ2VudHMStQkKsglbeyJrZXkiOiAiOGJkMjEzOWI1OTc1MTgxNTA2
|
||||
ZTQxZmQ5YzQ1NjNkNzUiLCAiaWQiOiAiNzhiYzU3YjgtYjBlOC00NmU3LTg5MjMtNDZkMmUxZDgy
|
||||
NDA3IiwgInJvbGUiOiAiUmVzZWFyY2hlciIsICJnb2FsIjogIk1ha2UgdGhlIGJlc3QgcmVzZWFy
|
||||
Y2ggYW5kIGFuYWx5c2lzIG9uIGNvbnRlbnQgYWJvdXQgQUkgYW5kIEFJIGFnZW50cyIsICJiYWNr
|
||||
c3RvcnkiOiAiWW91J3JlIGFuIGV4cGVydCByZXNlYXJjaGVyLCBzcGVjaWFsaXplZCBpbiB0ZWNo
|
||||
bm9sb2d5LCBzb2Z0d2FyZSBlbmdpbmVlcmluZywgQUkgYW5kIHN0YXJ0dXBzLiBZb3Ugd29yayBh
|
||||
cyBhIGZyZWVsYW5jZXIgYW5kIGlzIG5vdyB3b3JraW5nIG9uIGRvaW5nIHJlc2VhcmNoIGFuZCBh
|
||||
bmFseXNpcyBmb3IgYSBuZXcgY3VzdG9tZXIuIiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRl
|
||||
ciI6IDI1LCAibWF4X3JwbSI6IG51bGwsICJpMThuIjogbnVsbCwgImxsbSI6ICJ7XCJuYW1lXCI6
|
||||
IG51bGwsIFwibW9kZWxfbmFtZVwiOiBcImdwdC00b1wiLCBcInRlbXBlcmF0dXJlXCI6IDAuNywg
|
||||
XCJjbGFzc1wiOiBcIkNoYXRPcGVuQUlcIn0iLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNl
|
||||
LCAidG9vbHNfbmFtZXMiOiBbXX0sIHsia2V5IjogIjlhNTAxNWVmNDg5NWRjNjI3OGQ1NDgxOGJh
|
||||
NDQ2YWY3IiwgImlkIjogIjk2YzIxOTk1LWFlZDItNGJjNC1iYjY4LTdiOTA3ZTYzYjQyNSIsICJy
|
||||
b2xlIjogIlNlbmlvciBXcml0ZXIiLCAiZ29hbCI6ICJXcml0ZSB0aGUgYmVzdCBjb250ZW50IGFi
|
||||
b3V0IEFJIGFuZCBBSSBhZ2VudHMuIiwgImJhY2tzdG9yeSI6ICJZb3UncmUgYSBzZW5pb3Igd3Jp
|
||||
dGVyLCBzcGVjaWFsaXplZCBpbiB0ZWNobm9sb2d5LCBzb2Z0d2FyZSBlbmdpbmVlcmluZywgQUkg
|
||||
YW5kIHN0YXJ0dXBzLiBZb3Ugd29yayBhcyBhIGZyZWVsYW5jZXIgYW5kIGFyZSBub3cgd29ya2lu
|
||||
ZyBvbiB3cml0aW5nIGNvbnRlbnQgZm9yIGEgbmV3IGN1c3RvbWVyLiIsICJ2ZXJib3NlPyI6IGZh
|
||||
bHNlLCAibWF4X2l0ZXIiOiAyNSwgIm1heF9ycG0iOiBudWxsLCAiaTE4biI6IG51bGwsICJsbG0i
|
||||
OiAie1wibmFtZVwiOiBudWxsLCBcIm1vZGVsX25hbWVcIjogXCJncHQtNG9cIiwgXCJ0ZW1wZXJh
|
||||
dHVyZVwiOiAwLjcsIFwiY2xhc3NcIjogXCJDaGF0T3BlbkFJXCJ9IiwgImRlbGVnYXRpb25fZW5h
|
||||
YmxlZD8iOiBmYWxzZSwgInRvb2xzX25hbWVzIjogW119XUq5BwoKY3Jld190YXNrcxKqBwqnB1t7
|
||||
ImtleSI6ICJlOWU2YjcyYWFjMzI2NDU5ZGQ3MDY4ZjBiMTcxN2MxYyIsICJpZCI6ICI5NWE1NzQz
|
||||
Yy1lMjRmLTQ4ODItYmQ3Mi02ZmZlZjViYTMzNTYiLCAiZGVzY3JpcHRpb24iOiAiR2VuZXJhdGUg
|
||||
YSBsaXN0IG9mIDUgaW50ZXJlc3RpbmcgaWRlYXMgdG8gZXhwbG9yZSBmb3IgYW4gYXJ0aWNsZSwg
|
||||
d2hlcmUgZWFjaCBidWxsZXRwb2ludCBpcyB1bmRlciAxNSB3b3Jkcy4iLCAiZXhwZWN0ZWRfb3V0
|
||||
cHV0IjogIkJ1bGxldCBwb2ludCBsaXN0IG9mIDUgaW1wb3J0YW50IGV2ZW50cy4gTm8gYWRkaXRp
|
||||
b25hbCBjb21tZW50YXJ5LiIsICJhc3luY19leGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1
|
||||
dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAiUmVzZWFyY2hlciIsICJhZ2VudF9rZXkiOiAiOGJk
|
||||
MjEzOWI1OTc1MTgxNTA2ZTQxZmQ5YzQ1NjNkNzUiLCAiY29udGV4dCI6IG51bGwsICJ0b29sc19u
|
||||
YW1lcyI6IFtdfSwgeyJrZXkiOiAiZWVlZTdlNzNkNWRmNjZkNDhkMmQ4MDdiYWZmODc0ZjMiLCAi
|
||||
aWQiOiAiNzA4MGY4M2YtNmQ1Zi00MzM0LTgwZTctODI3NzEzNmQ4ZDdkIiwgImRlc2NyaXB0aW9u
|
||||
IjogIldyaXRlIGEgc2VudGVuY2UgYWJvdXQgdGhlIGV2ZW50cyIsICJleHBlY3RlZF9vdXRwdXQi
|
||||
OiAiQSBzZW50ZW5jZSBhYm91dCB0aGUgZXZlbnRzIiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBmYWxz
|
||||
ZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJTZW5pb3IgV3JpdGVyIiwg
|
||||
ImFnZW50X2tleSI6ICI5YTUwMTVlZjQ4OTVkYzYyNzhkNTQ4MThiYTQ0NmFmNyIsICJjb250ZXh0
|
||||
IjogWyJHZW5lcmF0ZSBhIGxpc3Qgb2YgNSBpbnRlcmVzdGluZyBpZGVhcyB0byBleHBsb3JlIGZv
|
||||
ciBhbiBhcnRpY2xlLCB3aGVyZSBlYWNoIGJ1bGxldHBvaW50IGlzIHVuZGVyIDE1IHdvcmRzLiJd
|
||||
LCAidG9vbHNfbmFtZXMiOiBbXX1dSioKCHBsYXRmb3JtEh4KHG1hY09TLTE0LjEuMS1hcm02NC1h
|
||||
cm0tNjRiaXRKHAoQcGxhdGZvcm1fcmVsZWFzZRIICgYyMy4xLjBKGwoPcGxhdGZvcm1fc3lzdGVt
|
||||
EggKBkRhcndpbkp7ChBwbGF0Zm9ybV92ZXJzaW9uEmcKZURhcndpbiBLZXJuZWwgVmVyc2lvbiAy
|
||||
My4xLjA6IE1vbiBPY3QgIDkgMjE6Mjc6MjQgUERUIDIwMjM7IHJvb3Q6eG51LTEwMDAyLjQxLjl+
|
||||
Ni9SRUxFQVNFX0FSTTY0X1Q2MDAwSgoKBGNwdXMSAhgKegIYAYUBAAEAABKxCwoQrufF6FYNBLX1
|
||||
X9l1YHzEsBIIg+LU+V/XPr0qDENyZXcgQ3JlYXRlZDABOYhBV9K1xeIXQcB/WdK1xeIXShoKDmNy
|
||||
ZXdhaV92ZXJzaW9uEggKBjAuMzYuMEoaCg5weXRob25fdmVyc2lvbhIICgYzLjExLjVKLgoIY3Jl
|
||||
d19rZXkSIgogNjczOGFkNWI4Y2IzZTZmMWMxYzkzNTBiOTZjMmU2NzhKMQoHY3Jld19pZBImCiQw
|
||||
ZDFjYjk0Yy1kMjgyLTQwYWUtYWVlYy0yN2JjNzc1NGZmOThKHAoMY3Jld19wcm9jZXNzEgwKCnNl
|
||||
cXVlbnRpYWxKEQoLY3Jld19tZW1vcnkSAhAAShoKFGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUob
|
||||
ChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgBSuEDCgtjcmV3X2FnZW50cxLRAwrOA1t7ImtleSI6
|
||||
ICI1MTJhNmRjMzc5ZjY2YjIxZWVhYjI0ZTYzNDgzNmY3MiIsICJpZCI6ICJjOTMwNzU2OS05OTRl
|
||||
LTRkMTItYWI5OS01NzlhYjZhNDMyMDkiLCAicm9sZSI6ICJDb250ZW50IFdyaXRlciIsICJnb2Fs
|
||||
IjogIldyaXRlIGVuZ2FnaW5nIGNvbnRlbnQgb24gdmFyaW91cyB0b3BpY3MuIiwgImJhY2tzdG9y
|
||||
eSI6ICJZb3UgaGF2ZSBhIGJhY2tncm91bmQgaW4gam91cm5hbGlzbSBhbmQgY3JlYXRpdmUgd3Jp
|
||||
dGluZy4iLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjUsICJtYXhfcnBtIjogbnVs
|
||||
bCwgImkxOG4iOiBudWxsLCAibGxtIjogIntcIm5hbWVcIjogbnVsbCwgXCJtb2RlbF9uYW1lXCI6
|
||||
IFwiZ3B0LTRvXCIsIFwidGVtcGVyYXR1cmVcIjogMC43LCBcImNsYXNzXCI6IFwiQ2hhdE9wZW5B
|
||||
SVwifSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogdHJ1ZSwgInRvb2xzX25hbWVzIjogW119XUqN
|
||||
AwoKY3Jld190YXNrcxL+Agr7Alt7ImtleSI6ICIzNDc3MDc2YmUzYWY3MTMwNDYyZWRhYTJlYjhh
|
||||
MDQ4ZSIsICJpZCI6ICI4NDMxNmNhOS05ZDNmLTRkZjctODQ4OC0zMDBmNDMxYWE1MDgiLCAiZGVz
|
||||
Y3JpcHRpb24iOiAiV3JpdGUgYSBkZXRhaWxlZCBhcnRpY2xlIGFib3V0IEFJIGluIGhlYWx0aGNh
|
||||
cmUuIiwgImV4cGVjdGVkX291dHB1dCI6ICJBIDEgcGFyYWdyYXBoIGFydGljbGUgYWJvdXQgQUku
|
||||
IiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdl
|
||||
bnRfcm9sZSI6ICJDb250ZW50IFdyaXRlciIsICJhZ2VudF9rZXkiOiAiNTEyYTZkYzM3OWY2NmIy
|
||||
MWVlYWIyNGU2MzQ4MzZmNzIiLCAiY29udGV4dCI6IG51bGwsICJ0b29sc19uYW1lcyI6IFtdfV1K
|
||||
KgoIcGxhdGZvcm0SHgocbWFjT1MtMTQuMS4xLWFybTY0LWFybS02NGJpdEocChBwbGF0Zm9ybV9y
|
||||
ZWxlYXNlEggKBjIzLjEuMEobCg9wbGF0Zm9ybV9zeXN0ZW0SCAoGRGFyd2luSnsKEHBsYXRmb3Jt
|
||||
X3ZlcnNpb24SZwplRGFyd2luIEtlcm5lbCBWZXJzaW9uIDIzLjEuMDogTW9uIE9jdCAgOSAyMToy
|
||||
NzoyNCBQRFQgMjAyMzsgcm9vdDp4bnUtMTAwMDIuNDEuOX42L1JFTEVBU0VfQVJNNjRfVDYwMDBK
|
||||
CgoEY3B1cxICGAp6AhgBhQEAAQAA
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate, br
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '23733'
|
||||
Content-Type:
|
||||
- application/x-protobuf
|
||||
User-Agent:
|
||||
- OTel-OTLP-Exporter-Python/1.25.0
|
||||
method: POST
|
||||
uri: https://telemetry.crewai.com:4319/v1/traces
|
||||
response:
|
||||
body:
|
||||
string: "\n\0"
|
||||
headers:
|
||||
Content-Length:
|
||||
- '2'
|
||||
Content-Type:
|
||||
- application/x-protobuf
|
||||
Date:
|
||||
- Tue, 16 Jul 2024 18:43:12 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,159 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: '{"messages": [{"content": "You are test_agent. Test Description\nYour personal
|
||||
goal is: Test GoalTo give my best complete final answer to the task use the
|
||||
exact following format:\n\nThought: I now can give a great answer\nFinal Answer:
|
||||
my best complete final answer to the task.\nYour final answer must be the great
|
||||
and the most complete as possible, it must be outcome described.\n\nI MUST use
|
||||
these formats, my job depends on it!\nCurrent Task: Test Task\n\nThis is the
|
||||
expect criteria for your final answer: Say Hi \n you MUST return the actual
|
||||
complete content as the final answer, not a summary.\n\nThis is the context
|
||||
you''re working with:\ncontext raw output\n\nBegin! This is VERY important to
|
||||
you, use the tools available and give your best Final Answer, your job depends
|
||||
on it!\n\nThought:\n", "role": "user"}], "model": "gpt-4o", "logprobs": false,
|
||||
"n": 1, "stop": ["\nObservation"], "stream": true, "temperature": 0.7}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '929'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.openai.com
|
||||
user-agent:
|
||||
- OpenAI/Python 1.36.0
|
||||
x-stainless-arch:
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 1.36.0
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.11.7
|
||||
method: POST
|
||||
uri: https://api.openai.com/v1/chat/completions
|
||||
response:
|
||||
body:
|
||||
string: 'data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"Thought"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":":"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
I"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
now"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
can"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
give"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
a"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
great"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
answer"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"\n"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"Final"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
Answer"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":":"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{"content":"
|
||||
Hi"},"logprobs":null,"finish_reason":null}]}
|
||||
|
||||
|
||||
data: {"id":"chatcmpl-9n6wPAClsh4tUGoLYKLh3VoX1vlAx","object":"chat.completion.chunk","created":1721491781,"model":"gpt-4o-2024-05-13","system_fingerprint":"fp_c4e5b6fa31","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}]}
|
||||
|
||||
|
||||
data: [DONE]
|
||||
|
||||
|
||||
'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8a643791a80e8c96-EWR
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- text/event-stream; charset=utf-8
|
||||
Date:
|
||||
- Sat, 20 Jul 2024 16:09:41 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- __cf_bm=cam5sECdaTzbttLIOaiuvh9flDIAXp_FLPODnDEOn6k-1721491781-1.0.1.1-hyFl43P7HIWZsGueyWuDeO579sZ41as2mvrM.cQS1E8KSLG2ZZ0DxDGbVvHYRO0eflTUJohgZu6CGltvjQfMtQ;
|
||||
path=/; expires=Sat, 20-Jul-24 16:39:41 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=nmlgS.bqXAu0rZ.OlHPfXrIrdnVgrBSW3e0UuU3N5ng-1721491781661-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
openai-organization:
|
||||
- crewai-iuxna1
|
||||
openai-processing-ms:
|
||||
- '126'
|
||||
openai-version:
|
||||
- '2020-10-01'
|
||||
strict-transport-security:
|
||||
- max-age=15552000; includeSubDomains; preload
|
||||
x-ratelimit-limit-requests:
|
||||
- '10000'
|
||||
x-ratelimit-limit-tokens:
|
||||
- '30000000'
|
||||
x-ratelimit-remaining-requests:
|
||||
- '9999'
|
||||
x-ratelimit-remaining-tokens:
|
||||
- '29999794'
|
||||
x-ratelimit-reset-requests:
|
||||
- 6ms
|
||||
x-ratelimit-reset-tokens:
|
||||
- 0s
|
||||
x-request-id:
|
||||
- req_31484eeb0af939af4e0d9c47441ba2db
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -3,7 +3,7 @@ from unittest import mock
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
from crewai.cli.cli import reset_memories, test, train, version
|
||||
from crewai.cli.cli import train, version
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -41,82 +41,6 @@ def test_train_invalid_string_iterations(train_crew, runner):
|
||||
)
|
||||
|
||||
|
||||
@mock.patch("crewai.cli.reset_memories_command.ShortTermMemory")
|
||||
@mock.patch("crewai.cli.reset_memories_command.EntityMemory")
|
||||
@mock.patch("crewai.cli.reset_memories_command.LongTermMemory")
|
||||
@mock.patch("crewai.cli.reset_memories_command.TaskOutputStorageHandler")
|
||||
def test_reset_all_memories(
|
||||
MockTaskOutputStorageHandler,
|
||||
MockLongTermMemory,
|
||||
MockEntityMemory,
|
||||
MockShortTermMemory,
|
||||
runner,
|
||||
):
|
||||
result = runner.invoke(reset_memories, ["--all"])
|
||||
MockShortTermMemory().reset.assert_called_once()
|
||||
MockEntityMemory().reset.assert_called_once()
|
||||
MockLongTermMemory().reset.assert_called_once()
|
||||
MockTaskOutputStorageHandler().reset.assert_called_once()
|
||||
|
||||
assert result.output == "All memories have been reset.\n"
|
||||
|
||||
|
||||
@mock.patch("crewai.cli.reset_memories_command.ShortTermMemory")
|
||||
def test_reset_short_term_memories(MockShortTermMemory, runner):
|
||||
result = runner.invoke(reset_memories, ["-s"])
|
||||
MockShortTermMemory().reset.assert_called_once()
|
||||
assert result.output == "Short term memory has been reset.\n"
|
||||
|
||||
|
||||
@mock.patch("crewai.cli.reset_memories_command.EntityMemory")
|
||||
def test_reset_entity_memories(MockEntityMemory, runner):
|
||||
result = runner.invoke(reset_memories, ["-e"])
|
||||
MockEntityMemory().reset.assert_called_once()
|
||||
assert result.output == "Entity memory has been reset.\n"
|
||||
|
||||
|
||||
@mock.patch("crewai.cli.reset_memories_command.LongTermMemory")
|
||||
def test_reset_long_term_memories(MockLongTermMemory, runner):
|
||||
result = runner.invoke(reset_memories, ["-l"])
|
||||
MockLongTermMemory().reset.assert_called_once()
|
||||
assert result.output == "Long term memory has been reset.\n"
|
||||
|
||||
|
||||
@mock.patch("crewai.cli.reset_memories_command.TaskOutputStorageHandler")
|
||||
def test_reset_kickoff_outputs(MockTaskOutputStorageHandler, runner):
|
||||
result = runner.invoke(reset_memories, ["-k"])
|
||||
MockTaskOutputStorageHandler().reset.assert_called_once()
|
||||
assert result.output == "Latest Kickoff outputs stored has been reset.\n"
|
||||
|
||||
|
||||
@mock.patch("crewai.cli.reset_memories_command.ShortTermMemory")
|
||||
@mock.patch("crewai.cli.reset_memories_command.LongTermMemory")
|
||||
def test_reset_multiple_memory_flags(MockShortTermMemory, MockLongTermMemory, runner):
|
||||
result = runner.invoke(
|
||||
reset_memories,
|
||||
[
|
||||
"-s",
|
||||
"-l",
|
||||
],
|
||||
)
|
||||
MockShortTermMemory().reset.assert_called_once()
|
||||
MockLongTermMemory().reset.assert_called_once()
|
||||
assert (
|
||||
result.output
|
||||
== "Long term memory has been reset.\nShort term memory has been reset.\n"
|
||||
)
|
||||
|
||||
|
||||
def test_reset_no_memory_flags(runner):
|
||||
result = runner.invoke(
|
||||
reset_memories,
|
||||
)
|
||||
assert (
|
||||
result.output
|
||||
== "Please specify at least one memory type to reset using the appropriate flags.\n"
|
||||
)
|
||||
|
||||
|
||||
def test_version_command(runner):
|
||||
result = runner.invoke(version)
|
||||
|
||||
@@ -133,33 +57,3 @@ def test_version_command_with_tools(runner):
|
||||
"crewai tools version:" in result.output
|
||||
or "crewai tools not installed" in result.output
|
||||
)
|
||||
|
||||
|
||||
@mock.patch("crewai.cli.cli.test_crew")
|
||||
def test_test_default_iterations(test_crew, runner):
|
||||
result = runner.invoke(test)
|
||||
|
||||
test_crew.assert_called_once_with(3, "gpt-4o-mini")
|
||||
assert result.exit_code == 0
|
||||
assert "Testing the crew for 3 iterations with model gpt-4o-mini" in result.output
|
||||
|
||||
|
||||
@mock.patch("crewai.cli.cli.test_crew")
|
||||
def test_test_custom_iterations(test_crew, runner):
|
||||
result = runner.invoke(test, ["--n_iterations", "5", "--model", "gpt-4o"])
|
||||
|
||||
test_crew.assert_called_once_with(5, "gpt-4o")
|
||||
assert result.exit_code == 0
|
||||
assert "Testing the crew for 5 iterations with model gpt-4o" in result.output
|
||||
|
||||
|
||||
@mock.patch("crewai.cli.cli.test_crew")
|
||||
def test_test_invalid_string_iterations(test_crew, runner):
|
||||
result = runner.invoke(test, ["--n_iterations", "invalid"])
|
||||
|
||||
test_crew.assert_not_called()
|
||||
assert result.exit_code == 2
|
||||
assert (
|
||||
"Usage: test [OPTIONS]\nTry 'test --help' for help.\n\nError: Invalid value for '-n' / '--n_iterations': 'invalid' is not a valid integer.\n"
|
||||
in result.output
|
||||
)
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
import subprocess
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
from crewai.cli import test_crew
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"n_iterations,model",
|
||||
[
|
||||
(1, "gpt-4o"),
|
||||
(5, "gpt-3.5-turbo"),
|
||||
(10, "gpt-4"),
|
||||
],
|
||||
)
|
||||
@mock.patch("crewai.cli.test_crew.subprocess.run")
|
||||
def test_crew_success(mock_subprocess_run, n_iterations, model):
|
||||
"""Test the crew function for successful execution."""
|
||||
mock_subprocess_run.return_value = subprocess.CompletedProcess(
|
||||
args=f"poetry run test {n_iterations} {model}", returncode=0
|
||||
)
|
||||
result = test_crew.test_crew(n_iterations, model)
|
||||
|
||||
mock_subprocess_run.assert_called_once_with(
|
||||
["poetry", "run", "test", str(n_iterations), model],
|
||||
capture_output=False,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
assert result is None
|
||||
|
||||
|
||||
@mock.patch("crewai.cli.test_crew.click")
|
||||
def test_test_crew_zero_iterations(click):
|
||||
test_crew.test_crew(0, "gpt-4o")
|
||||
click.echo.assert_called_once_with(
|
||||
"An unexpected error occurred: The number of iterations must be a positive integer.",
|
||||
err=True,
|
||||
)
|
||||
|
||||
|
||||
@mock.patch("crewai.cli.test_crew.click")
|
||||
def test_test_crew_negative_iterations(click):
|
||||
test_crew.test_crew(-2, "gpt-4o")
|
||||
click.echo.assert_called_once_with(
|
||||
"An unexpected error occurred: The number of iterations must be a positive integer.",
|
||||
err=True,
|
||||
)
|
||||
|
||||
|
||||
@mock.patch("crewai.cli.test_crew.click")
|
||||
@mock.patch("crewai.cli.test_crew.subprocess.run")
|
||||
def test_test_crew_called_process_error(mock_subprocess_run, click):
|
||||
n_iterations = 5
|
||||
mock_subprocess_run.side_effect = subprocess.CalledProcessError(
|
||||
returncode=1,
|
||||
cmd=["poetry", "run", "test", str(n_iterations), "gpt-4o"],
|
||||
output="Error",
|
||||
stderr="Some error occurred",
|
||||
)
|
||||
test_crew.test_crew(n_iterations, "gpt-4o")
|
||||
|
||||
mock_subprocess_run.assert_called_once_with(
|
||||
["poetry", "run", "test", "5", "gpt-4o"],
|
||||
capture_output=False,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
click.echo.assert_has_calls(
|
||||
[
|
||||
mock.call.echo(
|
||||
"An error occurred while testing the crew: Command '['poetry', 'run', 'test', '5', 'gpt-4o']' returned non-zero exit status 1.",
|
||||
err=True,
|
||||
),
|
||||
mock.call.echo("Error", err=True),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@mock.patch("crewai.cli.test_crew.click")
|
||||
@mock.patch("crewai.cli.test_crew.subprocess.run")
|
||||
def test_test_crew_unexpected_exception(mock_subprocess_run, click):
|
||||
# Arrange
|
||||
n_iterations = 5
|
||||
mock_subprocess_run.side_effect = Exception("Unexpected error")
|
||||
test_crew.test_crew(n_iterations, "gpt-4o")
|
||||
|
||||
mock_subprocess_run.assert_called_once_with(
|
||||
["poetry", "run", "test", "5", "gpt-4o"],
|
||||
capture_output=False,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
click.echo.assert_called_once_with(
|
||||
"An unexpected error occurred: Unexpected error", err=True
|
||||
)
|
||||
@@ -1,10 +1,9 @@
|
||||
"""Test Agent creation and execution basic functionality."""
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from concurrent.futures import Future
|
||||
from unittest import mock
|
||||
from unittest.mock import MagicMock, patch
|
||||
from unittest.mock import patch
|
||||
|
||||
import pydantic_core
|
||||
import pytest
|
||||
@@ -16,7 +15,6 @@ from crewai.crews.crew_output import CrewOutput
|
||||
from crewai.memory.contextual.contextual_memory import ContextualMemory
|
||||
from crewai.process import Process
|
||||
from crewai.task import Task
|
||||
from crewai.tasks.conditional_task import ConditionalTask
|
||||
from crewai.tasks.output_format import OutputFormat
|
||||
from crewai.tasks.task_output import TaskOutput
|
||||
from crewai.utilities import Logger, RPMController
|
||||
@@ -287,7 +285,7 @@ def test_hierarchical_process():
|
||||
crew = Crew(
|
||||
agents=[researcher, writer],
|
||||
process=Process.hierarchical,
|
||||
manager_llm=ChatOpenAI(temperature=0, model="gpt-4o"),
|
||||
manager_llm=ChatOpenAI(temperature=0, model="gpt-4"),
|
||||
tasks=[task],
|
||||
)
|
||||
|
||||
@@ -313,82 +311,6 @@ def test_manager_llm_requirement_for_hierarchical_process():
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_manager_agent_delegating_to_assigned_task_agent():
|
||||
"""
|
||||
Test that the manager agent delegates to the assigned task agent.
|
||||
"""
|
||||
from langchain_openai import ChatOpenAI
|
||||
|
||||
task = Task(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article, then write one amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
agent=researcher,
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[researcher, writer],
|
||||
process=Process.hierarchical,
|
||||
manager_llm=ChatOpenAI(temperature=0, model="gpt-4o"),
|
||||
tasks=[task],
|
||||
)
|
||||
|
||||
crew.kickoff()
|
||||
|
||||
# Check if the manager agent has the correct tools
|
||||
assert crew.manager_agent is not None
|
||||
assert crew.manager_agent.tools is not None
|
||||
|
||||
assert len(crew.manager_agent.tools) == 2
|
||||
assert (
|
||||
"Delegate a specific task to one of the following coworkers: Researcher\n"
|
||||
in crew.manager_agent.tools[0].description
|
||||
)
|
||||
assert (
|
||||
"Ask a specific question to one of the following coworkers: Researcher\n"
|
||||
in crew.manager_agent.tools[1].description
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_manager_agent_delegating_to_all_agents():
|
||||
"""
|
||||
Test that the manager agent delegates to all agents when none are specified.
|
||||
"""
|
||||
from langchain_openai import ChatOpenAI
|
||||
|
||||
task = Task(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article, then write one amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[researcher, writer],
|
||||
process=Process.hierarchical,
|
||||
manager_llm=ChatOpenAI(temperature=0, model="gpt-4o"),
|
||||
tasks=[task],
|
||||
)
|
||||
|
||||
crew.kickoff()
|
||||
|
||||
assert crew.manager_agent is not None
|
||||
assert crew.manager_agent.tools is not None
|
||||
|
||||
assert len(crew.manager_agent.tools) == 2
|
||||
print(
|
||||
"crew.manager_agent.tools[0].description",
|
||||
crew.manager_agent.tools[0].description,
|
||||
)
|
||||
assert (
|
||||
"Delegate a specific task to one of the following coworkers: Researcher, Senior Writer\n"
|
||||
in crew.manager_agent.tools[0].description
|
||||
)
|
||||
assert (
|
||||
"Ask a specific question to one of the following coworkers: Researcher, Senior Writer\n"
|
||||
in crew.manager_agent.tools[1].description
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_crew_with_delegating_agents():
|
||||
tasks = [
|
||||
@@ -994,7 +916,9 @@ async def test_kickoff_async_basic_functionality_and_output():
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
@pytest.mark.asyncio
|
||||
async def test_async_kickoff_for_each_async_basic_functionality_and_output():
|
||||
"""Tests the basic functionality and output of kickoff_for_each_async."""
|
||||
"""Tests the basic functionality and output of akickoff_for_each_async."""
|
||||
from unittest.mock import patch
|
||||
|
||||
inputs = [
|
||||
{"topic": "dog"},
|
||||
{"topic": "cat"},
|
||||
@@ -1020,13 +944,8 @@ async def test_async_kickoff_for_each_async_basic_functionality_and_output():
|
||||
agent=agent,
|
||||
)
|
||||
|
||||
async def mock_kickoff_async(**kwargs):
|
||||
input_data = kwargs.get("inputs")
|
||||
index = [input_["topic"] for input_ in inputs].index(input_data["topic"])
|
||||
return expected_outputs[index]
|
||||
|
||||
with patch.object(
|
||||
Crew, "kickoff_async", side_effect=mock_kickoff_async
|
||||
Crew, "kickoff_async", side_effect=expected_outputs
|
||||
) as mock_kickoff_async:
|
||||
crew = Crew(agents=[agent], tasks=[task])
|
||||
|
||||
@@ -1435,7 +1354,6 @@ def test_crew_inputs_interpolate_both_agents_and_tasks_diff():
|
||||
interpolate_task_inputs.assert_called()
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_crew_does_not_interpolate_without_inputs():
|
||||
from unittest.mock import patch
|
||||
|
||||
@@ -1918,13 +1836,13 @@ def test_replay_feature():
|
||||
)
|
||||
|
||||
crew.kickoff()
|
||||
crew.replay(str(write.id))
|
||||
crew.replay_from_task(str(write.id))
|
||||
# Ensure context was passed correctly
|
||||
assert mock_execute_task.call_count == 3
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_crew_replay_error():
|
||||
def test_crew_replay_from_task_error():
|
||||
task = Task(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
@@ -1937,7 +1855,7 @@ def test_crew_replay_error():
|
||||
)
|
||||
|
||||
with pytest.raises(TypeError) as e:
|
||||
crew.replay() # type: ignore purposefully throwing err
|
||||
crew.replay_from_task() # type: ignore purposefully throwing err
|
||||
assert "task_id is required" in str(e)
|
||||
|
||||
|
||||
@@ -2072,14 +1990,13 @@ def test_replay_task_with_context():
|
||||
with patch.object(Task, "execute_sync") as mock_replay_task:
|
||||
mock_replay_task.return_value = mock_task_output4
|
||||
|
||||
replayed_output = crew.replay(str(task4.id))
|
||||
replayed_output = crew.replay_from_task(str(task4.id))
|
||||
assert replayed_output.raw == "Presentation on AI advancements..."
|
||||
|
||||
db_handler.reset()
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_replay_with_context():
|
||||
def test_replay_from_task_with_context():
|
||||
agent = Agent(role="test_agent", backstory="Test Description", goal="Test Goal")
|
||||
task1 = Task(
|
||||
description="Context Task", expected_output="Say Task Output", agent=agent
|
||||
@@ -2131,7 +2048,7 @@ def test_replay_with_context():
|
||||
},
|
||||
],
|
||||
):
|
||||
crew.replay(str(task2.id))
|
||||
crew.replay_from_task(str(task2.id))
|
||||
|
||||
assert crew.tasks[1].context[0].output.raw == "context raw output"
|
||||
|
||||
@@ -2193,10 +2110,9 @@ def test_replay_with_invalid_task_id():
|
||||
ValueError,
|
||||
match="Task with id bf5b09c9-69bd-4eb8-be12-f9e5bae31c2d not found in the crew's tasks.",
|
||||
):
|
||||
crew.replay("bf5b09c9-69bd-4eb8-be12-f9e5bae31c2d")
|
||||
crew.replay_from_task("bf5b09c9-69bd-4eb8-be12-f9e5bae31c2d")
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
@patch.object(Crew, "_interpolate_inputs")
|
||||
def test_replay_interpolates_inputs_properly(mock_interpolate_inputs):
|
||||
agent = Agent(role="test_agent", backstory="Test Description", goal="Test Goal")
|
||||
@@ -2252,13 +2168,13 @@ def test_replay_interpolates_inputs_properly(mock_interpolate_inputs):
|
||||
},
|
||||
],
|
||||
):
|
||||
crew.replay(str(task2.id))
|
||||
crew.replay_from_task(str(task2.id))
|
||||
assert crew._inputs == {"name": "John"}
|
||||
assert mock_interpolate_inputs.call_count == 2
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_replay_setup_context():
|
||||
def test_replay_from_task_setup_context():
|
||||
agent = Agent(role="test_agent", backstory="Test Description", goal="Test Goal")
|
||||
task1 = Task(description="Context Task", expected_output="Say {name}", agent=agent)
|
||||
task2 = Task(
|
||||
@@ -2307,7 +2223,7 @@ def test_replay_setup_context():
|
||||
},
|
||||
],
|
||||
):
|
||||
crew.replay(str(task2.id))
|
||||
crew.replay_from_task(str(task2.id))
|
||||
|
||||
# Check if the first task's output was set correctly
|
||||
assert crew.tasks[0].output is not None
|
||||
@@ -2318,216 +2234,3 @@ def test_replay_setup_context():
|
||||
assert crew.tasks[0].output.output_format == OutputFormat.RAW
|
||||
|
||||
assert crew.tasks[1].prompt_context == "context raw output"
|
||||
|
||||
|
||||
def test_key():
|
||||
tasks = [
|
||||
Task(
|
||||
description="Give me a list of 5 interesting ideas to explore for na article, what makes them unique and interesting.",
|
||||
expected_output="Bullet point list of 5 important events.",
|
||||
agent=researcher,
|
||||
),
|
||||
Task(
|
||||
description="Write a 1 amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
expected_output="A 4 paragraph article about AI.",
|
||||
agent=writer,
|
||||
),
|
||||
]
|
||||
crew = Crew(
|
||||
agents=[researcher, writer],
|
||||
process=Process.sequential,
|
||||
tasks=tasks,
|
||||
)
|
||||
hash = hashlib.md5(
|
||||
f"{researcher.key}|{writer.key}|{tasks[0].key}|{tasks[1].key}".encode()
|
||||
).hexdigest()
|
||||
|
||||
assert crew.key == hash
|
||||
|
||||
|
||||
def test_conditional_task_requirement_breaks_when_singular_conditional_task():
|
||||
def condition_fn(output) -> bool:
|
||||
return output.raw.startswith("Andrew Ng has!!")
|
||||
|
||||
task = ConditionalTask(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article, then write one amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
condition=condition_fn,
|
||||
)
|
||||
|
||||
with pytest.raises(pydantic_core._pydantic_core.ValidationError):
|
||||
Crew(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task],
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_conditional_task_last_task_when_conditional_is_true():
|
||||
def condition_fn(output) -> bool:
|
||||
return True
|
||||
|
||||
task1 = Task(
|
||||
description="Say Hi",
|
||||
expected_output="Hi",
|
||||
agent=researcher,
|
||||
)
|
||||
task2 = ConditionalTask(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article, then write one amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
condition=condition_fn,
|
||||
agent=writer,
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2],
|
||||
)
|
||||
result = crew.kickoff()
|
||||
assert result.raw.startswith(
|
||||
"1. **The Rise of AI Agents in Customer Service: Revolutionizing Customer Interactions**"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_conditional_task_last_task_when_conditional_is_false():
|
||||
def condition_fn(output) -> bool:
|
||||
return False
|
||||
|
||||
task1 = Task(
|
||||
description="Say Hi",
|
||||
expected_output="Hi",
|
||||
agent=researcher,
|
||||
)
|
||||
task2 = ConditionalTask(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article, then write one amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
condition=condition_fn,
|
||||
agent=writer,
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2],
|
||||
)
|
||||
result = crew.kickoff()
|
||||
print(result.raw)
|
||||
assert result.raw == "Hi"
|
||||
|
||||
|
||||
def test_conditional_task_requirement_breaks_when_task_async():
|
||||
def my_condition(context):
|
||||
return context.get("some_value") > 10
|
||||
|
||||
task = ConditionalTask(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article, then write one amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
execute_async=True,
|
||||
condition=my_condition,
|
||||
agent=researcher,
|
||||
)
|
||||
task2 = Task(
|
||||
description="Say Hi",
|
||||
expected_output="Hi",
|
||||
agent=writer,
|
||||
)
|
||||
|
||||
with pytest.raises(pydantic_core._pydantic_core.ValidationError):
|
||||
Crew(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task, task2],
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_conditional_should_skip():
|
||||
task1 = Task(description="Return hello", expected_output="say hi", agent=researcher)
|
||||
|
||||
condition_mock = MagicMock(return_value=False)
|
||||
task2 = ConditionalTask(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article, then write one amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
condition=condition_mock,
|
||||
agent=writer,
|
||||
)
|
||||
crew_met = Crew(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2],
|
||||
)
|
||||
with patch.object(Task, "execute_sync") as mock_execute_sync:
|
||||
mock_execute_sync.return_value = TaskOutput(
|
||||
description="Task 1 description",
|
||||
raw="Task 1 output",
|
||||
agent="Researcher",
|
||||
)
|
||||
|
||||
result = crew_met.kickoff()
|
||||
assert mock_execute_sync.call_count == 1
|
||||
|
||||
assert condition_mock.call_count == 1
|
||||
assert condition_mock() is False
|
||||
|
||||
assert task2.output is None
|
||||
assert result.raw.startswith("Task 1 output")
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_conditional_should_execute():
|
||||
task1 = Task(description="Return hello", expected_output="say hi", agent=researcher)
|
||||
|
||||
condition_mock = MagicMock(
|
||||
return_value=True
|
||||
) # should execute this conditional task
|
||||
task2 = ConditionalTask(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article, then write one amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
condition=condition_mock,
|
||||
agent=writer,
|
||||
)
|
||||
crew_met = Crew(
|
||||
agents=[researcher, writer],
|
||||
tasks=[task1, task2],
|
||||
)
|
||||
with patch.object(Task, "execute_sync") as mock_execute_sync:
|
||||
mock_execute_sync.return_value = TaskOutput(
|
||||
description="Task 1 description",
|
||||
raw="Task 1 output",
|
||||
agent="Researcher",
|
||||
)
|
||||
|
||||
crew_met.kickoff()
|
||||
|
||||
assert condition_mock.call_count == 1
|
||||
assert condition_mock() is True
|
||||
assert mock_execute_sync.call_count == 2
|
||||
|
||||
|
||||
@mock.patch("crewai.crew.CrewEvaluator")
|
||||
@mock.patch("crewai.crew.Crew.kickoff")
|
||||
def test_crew_testing_function(mock_kickoff, crew_evaluator):
|
||||
task = Task(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article, then write one amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
agent=researcher,
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[researcher],
|
||||
tasks=[task],
|
||||
)
|
||||
n_iterations = 2
|
||||
crew.test(n_iterations, openai_model_name="gpt-4o-mini", inputs={"topic": "AI"})
|
||||
|
||||
assert len(mock_kickoff.mock_calls) == n_iterations
|
||||
mock_kickoff.assert_has_calls(
|
||||
[mock.call(inputs={"topic": "AI"}), mock.call(inputs={"topic": "AI"})]
|
||||
)
|
||||
|
||||
crew_evaluator.assert_has_calls(
|
||||
[
|
||||
mock.call(crew, "gpt-4o-mini"),
|
||||
mock.call().set_iteration(1),
|
||||
mock.call().set_iteration(2),
|
||||
mock.call().print_crew_evaluation_result(),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"""Test Agent creation and execution basic functionality."""
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
@@ -9,7 +8,6 @@ from pydantic import BaseModel
|
||||
from pydantic_core import ValidationError
|
||||
|
||||
from crewai import Agent, Crew, Process, Task
|
||||
from crewai.tasks.conditional_task import ConditionalTask
|
||||
from crewai.tasks.task_output import TaskOutput
|
||||
from crewai.utilities.converter import Converter
|
||||
|
||||
@@ -319,7 +317,6 @@ def test_output_json_hierarchical():
|
||||
assert result.to_dict() == {"score": 4}
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_json_property_without_output_json():
|
||||
class ScoreOutput(BaseModel):
|
||||
score: int
|
||||
@@ -400,8 +397,8 @@ def test_output_json_dict_hierarchical():
|
||||
manager_llm=ChatOpenAI(model="gpt-4o"),
|
||||
)
|
||||
result = crew.kickoff()
|
||||
assert {"score": 5} == result.json_dict
|
||||
assert result.to_dict() == {"score": 5}
|
||||
assert {"score": 4} == result.json_dict
|
||||
assert result.to_dict() == {"score": 4}
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
@@ -698,19 +695,6 @@ def test_task_definition_based_on_dict():
|
||||
assert task.agent is None
|
||||
|
||||
|
||||
def test_conditional_task_definition_based_on_dict():
|
||||
config = {
|
||||
"description": "Give me an integer score between 1-5 for the following title: 'The impact of AI in the future of work', check examples to based your evaluation.",
|
||||
"expected_output": "The score of the title.",
|
||||
}
|
||||
|
||||
task = ConditionalTask(config=config, condition=lambda x: True)
|
||||
|
||||
assert task.description == config["description"]
|
||||
assert task.expected_output == config["expected_output"]
|
||||
assert task.agent is None
|
||||
|
||||
|
||||
def test_interpolate_inputs():
|
||||
task = Task(
|
||||
description="Give me a list of 5 interesting ideas about {topic} to explore for an article, what makes them unique and interesting.",
|
||||
@@ -807,22 +791,3 @@ def test_task_output_str_with_none():
|
||||
)
|
||||
|
||||
assert str(task_output) == ""
|
||||
|
||||
|
||||
def test_key():
|
||||
original_description = "Give me a list of 5 interesting ideas about {topic} to explore for an article, what makes them unique and interesting."
|
||||
original_expected_output = "Bullet point list of 5 interesting ideas about {topic}."
|
||||
task = Task(
|
||||
description=original_description,
|
||||
expected_output=original_expected_output,
|
||||
)
|
||||
hash = hashlib.md5(
|
||||
f"{original_description}|{original_expected_output}".encode()
|
||||
).hexdigest()
|
||||
|
||||
assert task.key == hash, "The key should be the hash of the description."
|
||||
|
||||
task.interpolate_inputs(inputs={"topic": "AI"})
|
||||
assert (
|
||||
task.key == hash
|
||||
), "The key should be the hash of the non-interpolated description."
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
from crewai.agent import Agent
|
||||
from crewai.crew import Crew
|
||||
from crewai.task import Task
|
||||
from crewai.tasks.task_output import TaskOutput
|
||||
from crewai.utilities.evaluators.crew_evaluator_handler import (
|
||||
CrewEvaluator,
|
||||
TaskEvaluationPydanticOutput,
|
||||
)
|
||||
|
||||
|
||||
class TestCrewEvaluator:
|
||||
@pytest.fixture
|
||||
def crew_planner(self):
|
||||
agent = Agent(role="Agent 1", goal="Goal 1", backstory="Backstory 1")
|
||||
task = Task(
|
||||
description="Task 1",
|
||||
expected_output="Output 1",
|
||||
agent=agent,
|
||||
)
|
||||
crew = Crew(agents=[agent], tasks=[task])
|
||||
|
||||
return CrewEvaluator(crew, openai_model_name="gpt-4o-mini")
|
||||
|
||||
def test_setup_for_evaluating(self, crew_planner):
|
||||
crew_planner._setup_for_evaluating()
|
||||
assert crew_planner.crew.tasks[0].callback == crew_planner.evaluate
|
||||
|
||||
def test_set_iteration(self, crew_planner):
|
||||
crew_planner.set_iteration(1)
|
||||
assert crew_planner.iteration == 1
|
||||
|
||||
def test_evaluator_agent(self, crew_planner):
|
||||
agent = crew_planner._evaluator_agent()
|
||||
assert agent.role == "Task Execution Evaluator"
|
||||
assert (
|
||||
agent.goal
|
||||
== "Your goal is to evaluate the performance of the agents in the crew based on the tasks they have performed using score from 1 to 10 evaluating on completion, quality, and overall performance."
|
||||
)
|
||||
assert (
|
||||
agent.backstory
|
||||
== "Evaluator agent for crew evaluation with precise capabilities to evaluate the performance of the agents in the crew based on the tasks they have performed"
|
||||
)
|
||||
assert agent.verbose is False
|
||||
assert agent.llm.model_name == "gpt-4o-mini"
|
||||
|
||||
def test_evaluation_task(self, crew_planner):
|
||||
evaluator_agent = Agent(
|
||||
role="Evaluator Agent",
|
||||
goal="Evaluate the performance of the agents in the crew",
|
||||
backstory="Master in Evaluation",
|
||||
)
|
||||
task_to_evaluate = Task(
|
||||
description="Task 1",
|
||||
expected_output="Output 1",
|
||||
agent=Agent(role="Agent 1", goal="Goal 1", backstory="Backstory 1"),
|
||||
)
|
||||
task_output = "Task Output 1"
|
||||
task = crew_planner._evaluation_task(
|
||||
evaluator_agent, task_to_evaluate, task_output
|
||||
)
|
||||
|
||||
assert task.description.startswith(
|
||||
"Based on the task description and the expected output, compare and evaluate the performance of the agents in the crew based on the Task Output they have performed using score from 1 to 10 evaluating on completion, quality, and overall performance."
|
||||
)
|
||||
|
||||
assert task.agent == evaluator_agent
|
||||
assert (
|
||||
task.description
|
||||
== "Based on the task description and the expected output, compare and evaluate "
|
||||
"the performance of the agents in the crew based on the Task Output they have "
|
||||
"performed using score from 1 to 10 evaluating on completion, quality, and overall "
|
||||
"performance.task_description: Task 1 task_expected_output: Output 1 "
|
||||
"agent: Agent 1 agent_goal: Goal 1 Task Output: Task Output 1"
|
||||
)
|
||||
|
||||
@mock.patch("crewai.utilities.evaluators.crew_evaluator_handler.Console")
|
||||
@mock.patch("crewai.utilities.evaluators.crew_evaluator_handler.Table")
|
||||
def test_print_crew_evaluation_result(self, table, console, crew_planner):
|
||||
crew_planner.tasks_scores = {
|
||||
1: [10, 9, 8],
|
||||
2: [9, 8, 7],
|
||||
}
|
||||
|
||||
crew_planner.print_crew_evaluation_result()
|
||||
|
||||
table.assert_has_calls(
|
||||
[
|
||||
mock.call(title="Tasks Scores \n (1-10 Higher is better)"),
|
||||
mock.call().add_column("Tasks/Crew"),
|
||||
mock.call().add_column("Run 1"),
|
||||
mock.call().add_column("Run 2"),
|
||||
mock.call().add_column("Avg. Total"),
|
||||
mock.call().add_row("Task 1", "10", "9", "9.5"),
|
||||
mock.call().add_row("Task 2", "9", "8", "8.5"),
|
||||
mock.call().add_row("Task 3", "8", "7", "7.5"),
|
||||
mock.call().add_row("Crew", "9.0", "8.0", "8.5"),
|
||||
]
|
||||
)
|
||||
console.assert_has_calls([mock.call(), mock.call().print(table())])
|
||||
|
||||
def test_evaluate(self, crew_planner):
|
||||
task_output = TaskOutput(
|
||||
description="Task 1", agent=str(crew_planner.crew.agents[0])
|
||||
)
|
||||
|
||||
with mock.patch.object(Task, "execute_sync") as execute:
|
||||
execute().pydantic = TaskEvaluationPydanticOutput(quality=9.5)
|
||||
crew_planner.evaluate(task_output)
|
||||
assert crew_planner.tasks_scores[0] == [9.5]
|
||||
@@ -1,74 +0,0 @@
|
||||
from unittest.mock import patch
|
||||
from crewai.tasks.task_output import TaskOutput
|
||||
|
||||
import pytest
|
||||
|
||||
from crewai.agent import Agent
|
||||
from crewai.task import Task
|
||||
from crewai.utilities.planning_handler import CrewPlanner, PlannerTaskPydanticOutput
|
||||
|
||||
|
||||
class TestCrewPlanner:
|
||||
@pytest.fixture
|
||||
def crew_planner(self):
|
||||
tasks = [
|
||||
Task(
|
||||
description="Task 1",
|
||||
expected_output="Output 1",
|
||||
agent=Agent(role="Agent 1", goal="Goal 1", backstory="Backstory 1"),
|
||||
),
|
||||
Task(
|
||||
description="Task 2",
|
||||
expected_output="Output 2",
|
||||
agent=Agent(role="Agent 2", goal="Goal 2", backstory="Backstory 2"),
|
||||
),
|
||||
Task(
|
||||
description="Task 3",
|
||||
expected_output="Output 3",
|
||||
agent=Agent(role="Agent 3", goal="Goal 3", backstory="Backstory 3"),
|
||||
),
|
||||
]
|
||||
return CrewPlanner(tasks)
|
||||
|
||||
def test_handle_crew_planning(self, crew_planner):
|
||||
with patch.object(Task, "execute_sync") as execute:
|
||||
execute.return_value = TaskOutput(
|
||||
description="Description",
|
||||
agent="agent",
|
||||
pydantic=PlannerTaskPydanticOutput(
|
||||
list_of_plans_per_task=["Plan 1", "Plan 2", "Plan 3"]
|
||||
),
|
||||
)
|
||||
result = crew_planner._handle_crew_planning()
|
||||
|
||||
assert isinstance(result, PlannerTaskPydanticOutput)
|
||||
assert len(result.list_of_plans_per_task) == len(crew_planner.tasks)
|
||||
execute.assert_called_once()
|
||||
|
||||
def test_create_planning_agent(self, crew_planner):
|
||||
agent = crew_planner._create_planning_agent()
|
||||
assert isinstance(agent, Agent)
|
||||
assert agent.role == "Task Execution Planner"
|
||||
|
||||
def test_create_planner_task(self, crew_planner):
|
||||
planning_agent = Agent(
|
||||
role="Planning Agent",
|
||||
goal="Plan Step by Step Plan",
|
||||
backstory="Master in Planning",
|
||||
)
|
||||
tasks_summary = "Summary of tasks"
|
||||
task = crew_planner._create_planner_task(planning_agent, tasks_summary)
|
||||
|
||||
assert isinstance(task, Task)
|
||||
assert task.description.startswith("Based on these tasks summary")
|
||||
assert task.agent == planning_agent
|
||||
assert (
|
||||
task.expected_output
|
||||
== "Step by step plan on how the agents can execute their tasks using the available tools with mastery"
|
||||
)
|
||||
|
||||
def test_create_tasks_summary(self, crew_planner):
|
||||
tasks_summary = crew_planner._create_tasks_summary()
|
||||
assert isinstance(tasks_summary, str)
|
||||
assert tasks_summary.startswith("\n Task Number 1 - Task 1")
|
||||
assert tasks_summary.endswith('"agent_tools": []\n ')
|
||||
Reference in New Issue
Block a user