mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-08 15:48:29 +00:00
Compare commits
14 Commits
devin/1739
...
devin/1739
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97449a5f80 | ||
|
|
17ff29bc8e | ||
|
|
b7f5064f31 | ||
|
|
c10665c897 | ||
|
|
0fd72fc5d9 | ||
|
|
8195aaedea | ||
|
|
3ffe98bf39 | ||
|
|
e65a6b523a | ||
|
|
d842529b13 | ||
|
|
a304c9573b | ||
|
|
f8a5df9d5a | ||
|
|
3dd79fed82 | ||
|
|
b7d8fadfad | ||
|
|
537aac0785 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -21,4 +21,5 @@ crew_tasks_output.json
|
||||
.mypy_cache
|
||||
.ruff_cache
|
||||
.venv
|
||||
agentops.log
|
||||
agentops.log
|
||||
tests/cassettes/
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
# FAISS Search Tool
|
||||
|
||||
The FAISS Search Tool enables efficient vector similarity search using Facebook AI Similarity Search (FAISS).
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
from typing import List, Dict, Any
|
||||
from crewai import Agent
|
||||
from crewai.tools import FAISSSearchTool
|
||||
|
||||
# Initialize tool
|
||||
search_tool = FAISSSearchTool(
|
||||
index_type: str = "L2", # or "IP" for inner product
|
||||
dimension: int = 384, # Match your embedder's dimension
|
||||
embedder_config: Dict[str, Any] = {
|
||||
"provider": "fastembed",
|
||||
"model": "BAAI/bge-small-en-v1.5"
|
||||
}
|
||||
)
|
||||
|
||||
# Add documents (with error handling)
|
||||
try:
|
||||
search_tool.add_texts([
|
||||
"Document 1 content",
|
||||
"Document 2 content",
|
||||
# ...
|
||||
])
|
||||
except ValueError as e:
|
||||
print(f"Failed to add documents: {e}")
|
||||
|
||||
# Add large document sets efficiently
|
||||
try:
|
||||
search_tool.add_texts_batch(
|
||||
texts=["Doc 1", "Doc 2", ...], # Large list of documents
|
||||
batch_size=1000 # Process in batches to manage memory
|
||||
)
|
||||
except ValueError as e:
|
||||
print(f"Failed to add documents in batch: {e}")
|
||||
|
||||
# Search with error handling
|
||||
try:
|
||||
results = search_tool.run(
|
||||
query="search query",
|
||||
k=3, # Number of results
|
||||
score_threshold=0.6 # Minimum similarity score
|
||||
)
|
||||
for result in results:
|
||||
print(f"Text: {result['text']}, Score: {result['score']}")
|
||||
except ValueError as e:
|
||||
print(f"Search failed: {e}")
|
||||
|
||||
# Create agent with tool
|
||||
agent = Agent(
|
||||
role="researcher",
|
||||
goal="Find relevant information",
|
||||
tools=[search_tool]
|
||||
)
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| index_type | str | FAISS index type ("L2" or "IP") |
|
||||
| dimension | int | Embedding dimension |
|
||||
| embedder_config | dict | Embedder configuration |
|
||||
|
||||
## Parameters
|
||||
|
||||
### index_type
|
||||
- `"L2"`: Euclidean distance (default)
|
||||
- `"IP"`: Inner product similarity
|
||||
|
||||
### dimension
|
||||
Default is 384, which matches the BAAI/bge-small-en-v1.5 model. Adjust this to match your chosen embedder model's output dimension.
|
||||
|
||||
### embedder_config
|
||||
Configuration for the embedding model. Supports all CrewAI embedder providers:
|
||||
- fastembed (default)
|
||||
- openai
|
||||
- google
|
||||
- ollama
|
||||
|
||||
## Error Handling
|
||||
|
||||
The tool includes comprehensive error handling:
|
||||
|
||||
```python
|
||||
# Invalid index type
|
||||
try:
|
||||
tool = FAISSSearchTool(index_type="INVALID")
|
||||
except ValueError as e:
|
||||
print(f"Invalid index type: {e}")
|
||||
|
||||
# Empty query
|
||||
try:
|
||||
results = tool.run(query="")
|
||||
except ValueError as e:
|
||||
print(f"Invalid query: {e}") # "Query cannot be empty"
|
||||
|
||||
# Invalid k value
|
||||
try:
|
||||
results = tool.run(query="test", k=0)
|
||||
except ValueError as e:
|
||||
print(f"Invalid k: {e}") # "k must be positive"
|
||||
|
||||
# Invalid score threshold
|
||||
try:
|
||||
results = tool.run(query="test", score_threshold=1.5)
|
||||
except ValueError as e:
|
||||
print(f"Invalid threshold: {e}") # "score_threshold must be between 0 and 1"
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Memory Management
|
||||
For large document sets, use batch processing to manage memory efficiently:
|
||||
```python
|
||||
# Process documents in batches
|
||||
tool.add_texts_batch(texts=large_document_list, batch_size=1000)
|
||||
```
|
||||
|
||||
### Index Management
|
||||
Monitor and manage index size:
|
||||
```python
|
||||
# Check index size
|
||||
print(f"Current index size: {tool.index_size}")
|
||||
|
||||
# Check if index is empty
|
||||
if tool.is_empty:
|
||||
print("Index is empty")
|
||||
|
||||
# Clear index if needed
|
||||
tool.clear_index()
|
||||
```
|
||||
|
||||
### Performance Metrics
|
||||
The tool is optimized for performance:
|
||||
- Search operations typically complete within 1 second for indices up to 1000 documents
|
||||
- Batch processing helps manage memory for large document sets
|
||||
- Input sanitization ensures query safety without significant overhead
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "crewai"
|
||||
version = "0.102.0"
|
||||
version = "0.100.1"
|
||||
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."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10,<3.13"
|
||||
@@ -37,7 +37,6 @@ dependencies = [
|
||||
"tomli>=2.0.2",
|
||||
"blinker>=1.9.0",
|
||||
"json5>=0.10.0",
|
||||
"faiss-cpu>=1.7.4,<2.0.0",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
@@ -46,7 +45,7 @@ Documentation = "https://docs.crewai.com"
|
||||
Repository = "https://github.com/crewAIInc/crewAI"
|
||||
|
||||
[project.optional-dependencies]
|
||||
tools = ["crewai-tools>=0.36.0"]
|
||||
tools = ["crewai-tools>=0.32.1"]
|
||||
embeddings = [
|
||||
"tiktoken~=0.7.0"
|
||||
]
|
||||
|
||||
@@ -14,7 +14,7 @@ warnings.filterwarnings(
|
||||
category=UserWarning,
|
||||
module="pydantic.main",
|
||||
)
|
||||
__version__ = "0.102.0"
|
||||
__version__ = "0.100.1"
|
||||
__all__ = [
|
||||
"Agent",
|
||||
"Crew",
|
||||
|
||||
@@ -21,6 +21,9 @@ from crewai.utilities.constants import MAX_LLM_RETRY, TRAINING_DATA_FILE
|
||||
from crewai.utilities.exceptions.context_window_exceeding_exception import (
|
||||
LLMContextLengthExceededException,
|
||||
)
|
||||
from crewai.utilities.exceptions.feedback_processing_exception import (
|
||||
FeedbackProcessingError,
|
||||
)
|
||||
from crewai.utilities.logger import Logger
|
||||
from crewai.utilities.training_handler import CrewTrainingHandler
|
||||
|
||||
@@ -487,17 +490,40 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
|
||||
return CrewAgentParser(agent=self.agent).parse(answer)
|
||||
|
||||
def _format_msg(self, prompt: str, role: str = "user") -> Dict[str, str]:
|
||||
"""Format a message with role and content.
|
||||
|
||||
Args:
|
||||
prompt (str): The message content
|
||||
role (str): The message role (default: "user")
|
||||
|
||||
Returns:
|
||||
Dict[str, str]: Formatted message with role and content
|
||||
|
||||
Raises:
|
||||
FeedbackProcessingError: If prompt is empty or exceeds max length
|
||||
"""
|
||||
if not prompt or not prompt.strip():
|
||||
raise FeedbackProcessingError("Feedback message cannot be empty")
|
||||
if len(prompt) > 8192: # Standard context window size
|
||||
raise FeedbackProcessingError("Feedback message exceeds maximum length")
|
||||
|
||||
prompt = prompt.rstrip()
|
||||
return {"role": role, "content": prompt}
|
||||
|
||||
def _handle_human_feedback(self, formatted_answer: AgentFinish) -> AgentFinish:
|
||||
"""Handle human feedback with different flows for training vs regular use.
|
||||
|
||||
This method processes human feedback by either handling it as training data
|
||||
or as regular feedback requiring potential multiple iterations.
|
||||
|
||||
Args:
|
||||
formatted_answer: The initial AgentFinish result to get feedback on
|
||||
formatted_answer (AgentFinish): The initial AgentFinish result to get feedback on
|
||||
|
||||
Returns:
|
||||
AgentFinish: The final answer after processing feedback
|
||||
|
||||
Raises:
|
||||
FeedbackProcessingError: If feedback processing fails
|
||||
"""
|
||||
human_feedback = self._ask_human_input(formatted_answer.output)
|
||||
|
||||
@@ -511,44 +537,97 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
|
||||
return bool(self.crew and self.crew._train)
|
||||
|
||||
def _handle_training_feedback(
|
||||
self, initial_answer: AgentFinish, feedback: str
|
||||
self,
|
||||
initial_answer: AgentFinish,
|
||||
feedback: str,
|
||||
) -> AgentFinish:
|
||||
"""Process feedback for training scenarios with single iteration."""
|
||||
self._printer.print(
|
||||
content="\nProcessing training feedback.\n",
|
||||
color="yellow",
|
||||
)
|
||||
self._handle_crew_training_output(initial_answer, feedback)
|
||||
self.messages.append(
|
||||
self._format_msg(
|
||||
self._i18n.slice("feedback_instructions").format(feedback=feedback)
|
||||
"""Process feedback for training scenarios with single iteration.
|
||||
|
||||
Args:
|
||||
initial_answer (AgentFinish): The initial answer to improve
|
||||
feedback (str): The feedback to process
|
||||
|
||||
Returns:
|
||||
AgentFinish: The improved answer after processing feedback
|
||||
|
||||
Raises:
|
||||
FeedbackProcessingError: If feedback processing fails
|
||||
"""
|
||||
try:
|
||||
self._printer.print(
|
||||
content="\nProcessing training feedback.\n",
|
||||
color="yellow",
|
||||
)
|
||||
)
|
||||
improved_answer = self._invoke_loop()
|
||||
self._handle_crew_training_output(improved_answer)
|
||||
self.ask_for_human_input = False
|
||||
return improved_answer
|
||||
self._handle_crew_training_output(initial_answer, feedback)
|
||||
improved_answer = self._process_feedback_iteration(feedback)
|
||||
self._handle_crew_training_output(improved_answer)
|
||||
self.ask_for_human_input = False
|
||||
return improved_answer
|
||||
except Exception as e:
|
||||
error_msg = f"Failed to process training feedback: {str(e)}"
|
||||
self._printer.print(
|
||||
content=error_msg,
|
||||
color="red"
|
||||
)
|
||||
raise FeedbackProcessingError(error_msg, original_error=e)
|
||||
|
||||
def _handle_regular_feedback(
|
||||
self, current_answer: AgentFinish, initial_feedback: str
|
||||
self,
|
||||
current_answer: AgentFinish,
|
||||
initial_feedback: str,
|
||||
) -> AgentFinish:
|
||||
"""Process feedback for regular use with potential multiple iterations."""
|
||||
feedback = initial_feedback
|
||||
answer = current_answer
|
||||
"""Process feedback for regular use with potential multiple iterations.
|
||||
|
||||
while self.ask_for_human_input:
|
||||
response = self._get_llm_feedback_response(feedback)
|
||||
This method handles the iterative feedback process where the agent continues
|
||||
to improve its answer based on user feedback until no more changes are needed.
|
||||
|
||||
if not self._feedback_requires_changes(response):
|
||||
self.ask_for_human_input = False
|
||||
else:
|
||||
answer = self._process_feedback_iteration(feedback)
|
||||
feedback = self._ask_human_input(answer.output)
|
||||
Args:
|
||||
current_answer (AgentFinish): The current answer from the agent
|
||||
initial_feedback (str): The initial feedback from the user
|
||||
|
||||
return answer
|
||||
Returns:
|
||||
AgentFinish: The final answer after processing all feedback iterations
|
||||
|
||||
Raises:
|
||||
FeedbackProcessingError: If feedback processing or validation fails
|
||||
"""
|
||||
try:
|
||||
feedback = initial_feedback
|
||||
answer = current_answer
|
||||
|
||||
while self.ask_for_human_input:
|
||||
# Add feedback message with user role using standard formatter
|
||||
feedback_msg = self._i18n.slice("feedback_message").format(feedback=feedback)
|
||||
self.messages.append(self._format_msg(feedback_msg, role="user"))
|
||||
|
||||
response = self._get_llm_feedback_response(feedback)
|
||||
if not self._feedback_requires_changes(response):
|
||||
self.ask_for_human_input = False
|
||||
else:
|
||||
answer = self._process_feedback_iteration(feedback)
|
||||
feedback = self._ask_human_input(answer.output)
|
||||
|
||||
return answer
|
||||
except Exception as e:
|
||||
error_msg = f"Failed to process feedback: {str(e)}"
|
||||
self._printer.print(
|
||||
content=error_msg,
|
||||
color="red"
|
||||
)
|
||||
raise FeedbackProcessingError(error_msg, original_error=e)
|
||||
|
||||
def _get_llm_feedback_response(self, feedback: str) -> Optional[str]:
|
||||
"""Get LLM classification of whether feedback requires changes."""
|
||||
"""Get LLM classification of whether feedback requires changes.
|
||||
|
||||
Args:
|
||||
feedback (str): The feedback to classify
|
||||
|
||||
Returns:
|
||||
Optional[str]: The LLM's response indicating if changes are needed
|
||||
|
||||
Raises:
|
||||
FeedbackProcessingError: If LLM call fails after max retries
|
||||
"""
|
||||
prompt = self._i18n.slice("human_feedback_classification").format(
|
||||
feedback=feedback
|
||||
)
|
||||
@@ -561,21 +640,45 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
|
||||
except Exception as error:
|
||||
self._log_feedback_error(retry, error)
|
||||
|
||||
error_msg = f"Failed to get LLM feedback response after {MAX_LLM_RETRY} retries"
|
||||
self._log_max_retries_exceeded()
|
||||
return None
|
||||
raise FeedbackProcessingError(error_msg)
|
||||
|
||||
def _feedback_requires_changes(self, response: Optional[str]) -> bool:
|
||||
"""Determine if feedback response indicates need for changes."""
|
||||
"""Determine if feedback response indicates need for changes.
|
||||
|
||||
Args:
|
||||
response (Optional[str]): The LLM's response to feedback classification
|
||||
|
||||
Returns:
|
||||
bool: True if feedback requires changes, False otherwise
|
||||
"""
|
||||
return response == "true" if response else False
|
||||
|
||||
def _process_feedback_iteration(self, feedback: str) -> AgentFinish:
|
||||
"""Process a single feedback iteration."""
|
||||
self.messages.append(
|
||||
self._format_msg(
|
||||
self._i18n.slice("feedback_instructions").format(feedback=feedback)
|
||||
"""Process a single feedback iteration.
|
||||
|
||||
Args:
|
||||
feedback (str): The feedback to process from the user
|
||||
|
||||
Returns:
|
||||
AgentFinish: The processed agent response after incorporating feedback
|
||||
"""
|
||||
try:
|
||||
# Add feedback instructions with user role
|
||||
self.messages.append(
|
||||
self._format_msg(
|
||||
self._i18n.slice("feedback_instructions").format(feedback=feedback),
|
||||
role="user"
|
||||
)
|
||||
)
|
||||
)
|
||||
return self._invoke_loop()
|
||||
return self._invoke_loop()
|
||||
except Exception as e:
|
||||
self._printer.print(
|
||||
content=f"Error processing feedback iteration: {str(e)}",
|
||||
color="red"
|
||||
)
|
||||
raise
|
||||
|
||||
def _log_feedback_error(self, retry_count: int, error: Exception) -> None:
|
||||
"""Log feedback processing errors."""
|
||||
|
||||
@@ -5,7 +5,7 @@ description = "{{name}} using crewAI"
|
||||
authors = [{ name = "Your Name", email = "you@example.com" }]
|
||||
requires-python = ">=3.10,<3.13"
|
||||
dependencies = [
|
||||
"crewai[tools]>=0.102.0,<1.0.0"
|
||||
"crewai[tools]>=0.100.1,<1.0.0"
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
||||
@@ -5,7 +5,7 @@ description = "{{name}} using crewAI"
|
||||
authors = [{ name = "Your Name", email = "you@example.com" }]
|
||||
requires-python = ">=3.10,<3.13"
|
||||
dependencies = [
|
||||
"crewai[tools]>=0.102.0,<1.0.0",
|
||||
"crewai[tools]>=0.100.1,<1.0.0",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
||||
@@ -5,7 +5,7 @@ description = "Power up your crews with {{folder_name}}"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10,<3.13"
|
||||
dependencies = [
|
||||
"crewai[tools]>=0.102.0"
|
||||
"crewai[tools]>=0.100.1"
|
||||
]
|
||||
|
||||
[tool.crewai]
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import asyncio
|
||||
import copy
|
||||
import inspect
|
||||
import logging
|
||||
from typing import (
|
||||
@@ -395,6 +394,7 @@ class FlowMeta(type):
|
||||
or hasattr(attr_value, "__trigger_methods__")
|
||||
or hasattr(attr_value, "__is_router__")
|
||||
):
|
||||
|
||||
# Register start methods
|
||||
if hasattr(attr_value, "__is_start_method__"):
|
||||
start_methods.append(attr_name)
|
||||
@@ -569,9 +569,6 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
f"Initial state must be dict or BaseModel, got {type(self.initial_state)}"
|
||||
)
|
||||
|
||||
def _copy_state(self) -> T:
|
||||
return copy.deepcopy(self._state)
|
||||
|
||||
@property
|
||||
def state(self) -> T:
|
||||
return self._state
|
||||
@@ -743,7 +740,6 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
event=FlowStartedEvent(
|
||||
type="flow_started",
|
||||
flow_name=self.__class__.__name__,
|
||||
inputs=inputs,
|
||||
),
|
||||
)
|
||||
self._log_flow_event(
|
||||
@@ -807,18 +803,6 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
async def _execute_method(
|
||||
self, method_name: str, method: Callable, *args: Any, **kwargs: Any
|
||||
) -> Any:
|
||||
dumped_params = {f"_{i}": arg for i, arg in enumerate(args)} | (kwargs or {})
|
||||
self.event_emitter.send(
|
||||
self,
|
||||
event=MethodExecutionStartedEvent(
|
||||
type="method_execution_started",
|
||||
method_name=method_name,
|
||||
flow_name=self.__class__.__name__,
|
||||
params=dumped_params,
|
||||
state=self._copy_state(),
|
||||
),
|
||||
)
|
||||
|
||||
result = (
|
||||
await method(*args, **kwargs)
|
||||
if asyncio.iscoroutinefunction(method)
|
||||
@@ -828,18 +812,6 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
self._method_execution_counts[method_name] = (
|
||||
self._method_execution_counts.get(method_name, 0) + 1
|
||||
)
|
||||
|
||||
self.event_emitter.send(
|
||||
self,
|
||||
event=MethodExecutionFinishedEvent(
|
||||
type="method_execution_finished",
|
||||
method_name=method_name,
|
||||
flow_name=self.__class__.__name__,
|
||||
state=self._copy_state(),
|
||||
result=result,
|
||||
),
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
async def _execute_listeners(self, trigger_method: str, result: Any) -> None:
|
||||
@@ -978,6 +950,16 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
"""
|
||||
try:
|
||||
method = self._methods[listener_name]
|
||||
|
||||
self.event_emitter.send(
|
||||
self,
|
||||
event=MethodExecutionStartedEvent(
|
||||
type="method_execution_started",
|
||||
method_name=listener_name,
|
||||
flow_name=self.__class__.__name__,
|
||||
),
|
||||
)
|
||||
|
||||
sig = inspect.signature(method)
|
||||
params = list(sig.parameters.values())
|
||||
method_params = [p for p in params if p.name != "self"]
|
||||
@@ -989,6 +971,15 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
else:
|
||||
listener_result = await self._execute_method(listener_name, method)
|
||||
|
||||
self.event_emitter.send(
|
||||
self,
|
||||
event=MethodExecutionFinishedEvent(
|
||||
type="method_execution_finished",
|
||||
method_name=listener_name,
|
||||
flow_name=self.__class__.__name__,
|
||||
),
|
||||
)
|
||||
|
||||
# Execute listeners (and possibly routers) of this listener
|
||||
await self._execute_listeners(listener_name, listener_result)
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, Optional, Union
|
||||
|
||||
from pydantic import BaseModel
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -17,21 +15,17 @@ class Event:
|
||||
|
||||
@dataclass
|
||||
class FlowStartedEvent(Event):
|
||||
inputs: Optional[Dict[str, Any]] = None
|
||||
pass
|
||||
|
||||
|
||||
@dataclass
|
||||
class MethodExecutionStartedEvent(Event):
|
||||
method_name: str
|
||||
state: Union[Dict[str, Any], BaseModel]
|
||||
params: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class MethodExecutionFinishedEvent(Event):
|
||||
method_name: str
|
||||
state: Union[Dict[str, Any], BaseModel]
|
||||
result: Any = None
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
from .base_tool import BaseTool, tool
|
||||
from .faiss_search_tool import FAISSSearchTool
|
||||
|
||||
__all__ = ["BaseTool", "tool", "FAISSSearchTool"]
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
import logging
|
||||
import re
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
import faiss
|
||||
import numpy as np
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from crewai.tools import BaseTool
|
||||
from crewai.utilities import EmbeddingConfigurator
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class FAISSSearchTool(BaseTool):
|
||||
"""FAISS vector similarity search tool for efficient document search."""
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
name: str = "FAISS Search Tool"
|
||||
description: str = "Search through documents using FAISS vector similarity search"
|
||||
embedder_config: Optional[Dict[str, Any]] = Field(default=None)
|
||||
dimension: int = Field(default=384) # Default for BAAI/bge-small-en-v1.5
|
||||
texts: List[str] = Field(default_factory=list)
|
||||
index_type: str = Field(default="L2")
|
||||
index: Any = Field(default=None) # FAISS index instance
|
||||
embedder: Any = Field(default=None) # Embedder instance
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
index_type: str = "L2",
|
||||
dimension: int = 384,
|
||||
embedder_config: Optional[Dict[str, Any]] = None,
|
||||
):
|
||||
"""Initialize FAISS search tool.
|
||||
|
||||
Args:
|
||||
index_type: Type of FAISS index ("L2" or "IP")
|
||||
dimension: Embedding dimension
|
||||
embedder_config: Configuration for the embedder
|
||||
"""
|
||||
super().__init__()
|
||||
self.dimension = dimension
|
||||
self.embedder_config = embedder_config
|
||||
self.index_type = index_type
|
||||
self.index = self._create_index(index_type)
|
||||
self._initialize_embedder()
|
||||
|
||||
def _create_index(self, index_type: str) -> faiss.Index:
|
||||
"""Create FAISS index of specified type.
|
||||
|
||||
Args:
|
||||
index_type: Type of index ("L2" or "IP")
|
||||
|
||||
Returns:
|
||||
FAISS index instance
|
||||
|
||||
Raises:
|
||||
ValueError: If index_type is not supported
|
||||
"""
|
||||
if index_type == "L2":
|
||||
return faiss.IndexFlatL2(self.dimension)
|
||||
elif index_type == "IP":
|
||||
return faiss.IndexFlatIP(self.dimension)
|
||||
else:
|
||||
raise ValueError(f"Unsupported index type: {index_type}")
|
||||
|
||||
def _initialize_embedder(self):
|
||||
"""Initialize the embedder using the provided configuration."""
|
||||
from crewai.knowledge.embedder.fastembed import FastEmbed
|
||||
self.embedder = FastEmbed()
|
||||
|
||||
def _sanitize_query(self, query: str) -> str:
|
||||
"""Remove potentially harmful characters from query.
|
||||
|
||||
Args:
|
||||
query: Input query string
|
||||
|
||||
Returns:
|
||||
Sanitized query string
|
||||
"""
|
||||
return re.sub(r'[^\w\s]', '', query)
|
||||
|
||||
def _run(
|
||||
self,
|
||||
query: str,
|
||||
k: int = 3,
|
||||
score_threshold: float = 0.6
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Search for similar texts using FAISS.
|
||||
|
||||
Args:
|
||||
query: Search query
|
||||
k: Number of results to return
|
||||
score_threshold: Minimum similarity score threshold
|
||||
|
||||
Returns:
|
||||
List of dictionaries containing matched texts and scores
|
||||
|
||||
Raises:
|
||||
ValueError: If input parameters are invalid
|
||||
"""
|
||||
if not query.strip():
|
||||
raise ValueError("Query cannot be empty")
|
||||
if k < 1:
|
||||
raise ValueError("k must be positive")
|
||||
if not 0 <= score_threshold <= 1:
|
||||
raise ValueError("score_threshold must be between 0 and 1")
|
||||
|
||||
logger.debug(f"Searching for query: {query} with k={k}")
|
||||
query = self._sanitize_query(query)
|
||||
query_embedding = self.embedder.embed_text(query)
|
||||
|
||||
D, I = self.index.search(
|
||||
np.array([query_embedding], dtype=np.float32),
|
||||
k
|
||||
)
|
||||
|
||||
results = []
|
||||
for i, (dist, idx) in enumerate(zip(D[0], I[0])):
|
||||
if idx < len(self.texts):
|
||||
score = 1.0 / (1.0 + dist) # Convert distance to similarity score
|
||||
if score >= score_threshold:
|
||||
results.append({
|
||||
"text": self.texts[idx],
|
||||
"score": score
|
||||
})
|
||||
return results
|
||||
|
||||
def add_texts(self, texts: List[str]) -> None:
|
||||
"""Add texts to the search index.
|
||||
|
||||
Args:
|
||||
texts: List of texts to add
|
||||
|
||||
Raises:
|
||||
ValueError: If embedding or indexing fails
|
||||
"""
|
||||
try:
|
||||
embeddings = self.embedder.embed_texts(texts)
|
||||
self.index.add(np.array(embeddings, dtype=np.float32))
|
||||
self.texts.extend(texts)
|
||||
except Exception as e:
|
||||
raise ValueError(f"Failed to add texts: {str(e)}")
|
||||
|
||||
def add_texts_batch(self, texts: List[str], batch_size: int = 1000) -> None:
|
||||
"""Add texts in batches to prevent memory issues.
|
||||
|
||||
Args:
|
||||
texts: List of texts to add
|
||||
batch_size: Size of each batch
|
||||
|
||||
Raises:
|
||||
ValueError: If batch_size is invalid
|
||||
"""
|
||||
if batch_size < 1:
|
||||
raise ValueError("batch_size must be positive")
|
||||
|
||||
for i in range(0, len(texts), batch_size):
|
||||
batch = texts[i:i + batch_size]
|
||||
self.add_texts(batch)
|
||||
|
||||
def clear_index(self) -> None:
|
||||
"""Clear the index and stored texts."""
|
||||
self.index = self._create_index(self.index_type)
|
||||
self.texts = []
|
||||
|
||||
@property
|
||||
def index_size(self) -> int:
|
||||
"""Return number of vectors in index."""
|
||||
return len(self.texts)
|
||||
|
||||
@property
|
||||
def is_empty(self) -> bool:
|
||||
"""Check if index is empty."""
|
||||
return len(self.texts) == 0
|
||||
5
src/crewai/utilities/exceptions/__init__.py
Normal file
5
src/crewai/utilities/exceptions/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""Exceptions module for CrewAI."""
|
||||
|
||||
from .feedback_processing_exception import FeedbackProcessingError
|
||||
|
||||
__all__ = ["FeedbackProcessingError"]
|
||||
@@ -0,0 +1,8 @@
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class FeedbackProcessingError(Exception):
|
||||
"""Exception raised when feedback processing fails."""
|
||||
def __init__(self, message: str, original_error: Optional[Exception] = None):
|
||||
self.original_error = original_error
|
||||
super().__init__(message)
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import os
|
||||
from unittest import mock
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -19,6 +19,9 @@ from crewai.tools.tool_usage import ToolUsage
|
||||
from crewai.tools.tool_usage_events import ToolUsageFinished
|
||||
from crewai.utilities import RPMController
|
||||
from crewai.utilities.events import Emitter
|
||||
from crewai.utilities.exceptions.feedback_processing_exception import (
|
||||
FeedbackProcessingError,
|
||||
)
|
||||
|
||||
|
||||
def test_agent_llm_creation_with_env_vars():
|
||||
@@ -1001,6 +1004,53 @@ def test_agent_human_input():
|
||||
assert mock_human_input.call_count == 2 # Should have asked for feedback twice
|
||||
assert output.strip().lower() == "hello" # Final output should be 'Hello'
|
||||
|
||||
# Verify message format for human feedback
|
||||
messages = agent.agent_executor.messages
|
||||
feedback_messages = [m for m in messages if "Feedback:" in m.get("content", "")]
|
||||
assert len(feedback_messages) == 2 # Two feedback messages
|
||||
for msg in feedback_messages:
|
||||
assert msg["role"] == "user" # All feedback messages should have user role
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_executor():
|
||||
"""Create a mock executor for testing."""
|
||||
agent = Agent(
|
||||
role="test role",
|
||||
goal="test goal",
|
||||
backstory="test backstory"
|
||||
)
|
||||
task = Task(
|
||||
description="Test task",
|
||||
expected_output="Test output",
|
||||
human_input=True,
|
||||
agent=agent
|
||||
)
|
||||
executor = CrewAgentExecutor(
|
||||
agent=agent,
|
||||
task=task,
|
||||
llm=agent.llm,
|
||||
crew=None,
|
||||
prompt="",
|
||||
max_iter=1,
|
||||
tools=[],
|
||||
tools_names=[],
|
||||
stop_words=[],
|
||||
tools_description="",
|
||||
tools_handler=None
|
||||
)
|
||||
return executor
|
||||
|
||||
def test_empty_feedback_handling(mock_executor):
|
||||
"""Test that empty feedback is properly handled."""
|
||||
with pytest.raises(FeedbackProcessingError):
|
||||
mock_executor._format_msg("")
|
||||
|
||||
def test_long_feedback_handling(mock_executor):
|
||||
"""Test that very long feedback is properly handled."""
|
||||
very_long_feedback = "x" * 10000
|
||||
with pytest.raises(FeedbackProcessingError):
|
||||
mock_executor._format_msg(very_long_feedback)
|
||||
|
||||
def test_interpolate_inputs():
|
||||
agent = Agent(
|
||||
|
||||
307
tests/cassettes/test_empty_feedback_handling.yaml
Normal file
307
tests/cassettes/test_empty_feedback_handling.yaml
Normal file
@@ -0,0 +1,307 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: !!binary |
|
||||
CrV6CiQKIgoMc2VydmljZS5uYW1lEhIKEGNyZXdBSS10ZWxlbWV0cnkSjHoKEgoQY3Jld2FpLnRl
|
||||
bGVtZXRyeRKwBwoQdpCOuOkexoT4NZTCVljP1BIIfEulX5blckkqDENyZXcgQ3JlYXRlZDABOUQI
|
||||
kgemhyMYQfVkoQemhyMYShsKDmNyZXdhaV92ZXJzaW9uEgkKBzAuMTAwLjFKGgoOcHl0aG9uX3Zl
|
||||
cnNpb24SCAoGMy4xMi43Si4KCGNyZXdfa2V5EiIKIGQ1NTExM2JlNGFhNDFiYTY0M2QzMjYwNDJi
|
||||
MmYwM2YxSjEKB2NyZXdfaWQSJgokMmQxNThmMjctOWExOC00OTg0LTk0OTktYjZhMzc1NTc2YTU4
|
||||
ShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3
|
||||
X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrMAgoLY3Jl
|
||||
d19hZ2VudHMSvAIKuQJbeyJrZXkiOiAiZTE0OGU1MzIwMjkzNDk5ZjhjZWJlYTgyNmU3MjU4MmIi
|
||||
LCAiaWQiOiAiNmVhZDNhYzYtMGRmMS00YTY0LTgwM2ItZTE2MWFmMDZiZTgxIiwgInJvbGUiOiAi
|
||||
dGVzdCByb2xlIiwgInZlcmJvc2U/IjogdHJ1ZSwgIm1heF9pdGVyIjogNCwgIm1heF9ycG0iOiAx
|
||||
MCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAiZ3B0LTRvLW1pbmkiLCAiZGVs
|
||||
ZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9leGVjdXRpb24/IjogZmFsc2Us
|
||||
ICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBbXX1dSpACCgpjcmV3X3Rhc2tz
|
||||
EoECCv4BW3sia2V5IjogIjRhMzFiODUxMzNhM2EyOTRjNjg1M2RhNzU3ZDRiYWU3IiwgImlkIjog
|
||||
ImQzNTU0M2UzLWIwMTAtNGNhYS04NzI5LTYzYjkxZTI2OTY2MiIsICJhc3luY19leGVjdXRpb24/
|
||||
IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAidGVzdCByb2xl
|
||||
IiwgImFnZW50X2tleSI6ICJlMTQ4ZTUzMjAyOTM0OTlmOGNlYmVhODI2ZTcyNTgyYiIsICJ0b29s
|
||||
c19uYW1lcyI6IFsiZ2V0X2ZpbmFsX2Fuc3dlciJdfV16AhgBhQEAAQAAEo4CChAegf7PNU+P5e79
|
||||
MNur6PVkEghMT+0stJYWYCoMVGFzayBDcmVhdGVkMAE51eexB6aHIxhBZ9ayB6aHIxhKLgoIY3Jl
|
||||
d19rZXkSIgogZDU1MTEzYmU0YWE0MWJhNjQzZDMyNjA0MmIyZjAzZjFKMQoHY3Jld19pZBImCiQy
|
||||
ZDE1OGYyNy05YTE4LTQ5ODQtOTQ5OS1iNmEzNzU1NzZhNThKLgoIdGFza19rZXkSIgogNGEzMWI4
|
||||
NTEzM2EzYTI5NGM2ODUzZGE3NTdkNGJhZTdKMQoHdGFza19pZBImCiRkMzU1NDNlMy1iMDEwLTRj
|
||||
YWEtODcyOS02M2I5MWUyNjk2NjJ6AhgBhQEAAQAAEpQBChCFfsLseVYHybPhCFlrXiZ5EggL0Wm/
|
||||
Us0FrioKVG9vbCBVc2FnZTABOeEoMAimhyMYQT2MPgimhyMYShsKDmNyZXdhaV92ZXJzaW9uEgkK
|
||||
BzAuMTAwLjFKHwoJdG9vbF9uYW1lEhIKEGdldF9maW5hbF9hbnN3ZXJKDgoIYXR0ZW1wdHMSAhgB
|
||||
egIYAYUBAAEAABKdAQoQFOiE21qjZmK2nnmrBQB/ohIIs0uE2IV3DCoqE1Rvb2wgUmVwZWF0ZWQg
|
||||
VXNhZ2UwATkwrcIIpocjGEGHi9AIpocjGEobCg5jcmV3YWlfdmVyc2lvbhIJCgcwLjEwMC4xSh8K
|
||||
CXRvb2xfbmFtZRISChBnZXRfZmluYWxfYW5zd2VySg4KCGF0dGVtcHRzEgIYAXoCGAGFAQABAAAS
|
||||
nQEKELIZVIO+Smd1JULqNEumKHoSCDH9vnKQrFuxKhNUb29sIFJlcGVhdGVkIFVzYWdlMAE5Xktd
|
||||
CaaHIxhBU1B0CaaHIxhKGwoOY3Jld2FpX3ZlcnNpb24SCQoHMC4xMDAuMUofCgl0b29sX25hbWUS
|
||||
EgoQZ2V0X2ZpbmFsX2Fuc3dlckoOCghhdHRlbXB0cxICGAF6AhgBhQEAAQAAEp0BChBLm/Rev7ii
|
||||
1RmsETsVKbiHEgi88x3U6BT3PioTVG9vbCBSZXBlYXRlZCBVc2FnZTABOXVXDQqmhyMYQRYUHAqm
|
||||
hyMYShsKDmNyZXdhaV92ZXJzaW9uEgkKBzAuMTAwLjFKHwoJdG9vbF9uYW1lEhIKEGdldF9maW5h
|
||||
bF9hbnN3ZXJKDgoIYXR0ZW1wdHMSAhgBegIYAYUBAAEAABLZCwoQCbZhwqrhbqnALZ4Hz/X4AxII
|
||||
vcjAPkNUb5kqDENyZXcgQ3JlYXRlZDABOQMbpwumhyMYQUvYtgumhyMYShsKDmNyZXdhaV92ZXJz
|
||||
aW9uEgkKBzAuMTAwLjFKGgoOcHl0aG9uX3ZlcnNpb24SCAoGMy4xMi43Si4KCGNyZXdfa2V5EiIK
|
||||
IDY2MmM2ZGVjOTYwOTU3ZjA0Y2JlNjQyNzFiYjE2NzNlSjEKB2NyZXdfaWQSJgokNjMwMjBhNzAt
|
||||
YmViMS00Mzc4LTkxZDgtYWJiMzI4ZGNhYTZlShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFs
|
||||
ShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGAJKGwoVY3Jld19u
|
||||
dW1iZXJfb2ZfYWdlbnRzEgIYAkqIBQoLY3Jld19hZ2VudHMS+AQK9QRbeyJrZXkiOiAiZTE0OGU1
|
||||
MzIwMjkzNDk5ZjhjZWJlYTgyNmU3MjU4MmIiLCAiaWQiOiAiMDhmOGQzODEtMWFhNC00MDI3LWFl
|
||||
MjctZmMyMTE0ZjE3ZWY4IiwgInJvbGUiOiAidGVzdCByb2xlIiwgInZlcmJvc2U/IjogdHJ1ZSwg
|
||||
Im1heF9pdGVyIjogMiwgIm1heF9ycG0iOiAxMCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIs
|
||||
ICJsbG0iOiAiZ3B0LTRvLW1pbmkiLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxs
|
||||
b3dfY29kZV9leGVjdXRpb24/IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNf
|
||||
bmFtZXMiOiBbXX0sIHsia2V5IjogImU3ZThlZWE4ODZiY2I4ZjEwNDVhYmVlY2YxNDI1ZGI3Iiwg
|
||||
ImlkIjogIjIyM2IxYjYwLTNkMzYtNGNkZS1iNWUzLTNhOWJmNGJlODU0MiIsICJyb2xlIjogInRl
|
||||
c3Qgcm9sZTIiLCAidmVyYm9zZT8iOiB0cnVlLCAibWF4X2l0ZXIiOiA1LCAibWF4X3JwbSI6IG51
|
||||
bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdwdC00by1taW5pIiwgImRl
|
||||
bGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhlY3V0aW9uPyI6IGZhbHNl
|
||||
LCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119XUr9AwoKY3Jld190YXNr
|
||||
cxLuAwrrA1t7ImtleSI6ICIzMjJkZGFlM2JjODBjMWQ0NWI4NWZhNzc1NmRiODY2NSIsICJpZCI6
|
||||
ICI5YmI3OTE1OC05NzFkLTQxNGQtYTY2Ny05NWJjNzAxNWVjMjkiLCAiYXN5bmNfZXhlY3V0aW9u
|
||||
PyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9yb2xlIjogInRlc3Qgcm9s
|
||||
ZSIsICJhZ2VudF9rZXkiOiAiZTE0OGU1MzIwMjkzNDk5ZjhjZWJlYTgyNmU3MjU4MmIiLCAidG9v
|
||||
bHNfbmFtZXMiOiBbXX0sIHsia2V5IjogImQ1YzQ1MjNlNGNhMzQ0NGRlMzViZjYzMGI1MmY3YWRj
|
||||
IiwgImlkIjogImY1MjE3NDRjLTAzMDItNDI0MC05NDhjLTNjOWNiM2FjZTI2YyIsICJhc3luY19l
|
||||
eGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAi
|
||||
dGVzdCByb2xlMiIsICJhZ2VudF9rZXkiOiAiZTdlOGVlYTg4NmJjYjhmMTA0NWFiZWVjZjE0MjVk
|
||||
YjciLCAidG9vbHNfbmFtZXMiOiBbImdldF9maW5hbF9hbnN3ZXIiXX1degIYAYUBAAEAABKOAgoQ
|
||||
7y/W8t37iRoWm0uvUYIMUhIIS62FJ0+mHJAqDFRhc2sgQ3JlYXRlZDABOd1azAumhyMYQfBfzQum
|
||||
hyMYSi4KCGNyZXdfa2V5EiIKIDY2MmM2ZGVjOTYwOTU3ZjA0Y2JlNjQyNzFiYjE2NzNlSjEKB2Ny
|
||||
ZXdfaWQSJgokNjMwMjBhNzAtYmViMS00Mzc4LTkxZDgtYWJiMzI4ZGNhYTZlSi4KCHRhc2tfa2V5
|
||||
EiIKIDMyMmRkYWUzYmM4MGMxZDQ1Yjg1ZmE3NzU2ZGI4NjY1SjEKB3Rhc2tfaWQSJgokOWJiNzkx
|
||||
NTgtOTcxZC00MTRkLWE2NjctOTViYzcwMTVlYzI5egIYAYUBAAEAABKOAgoQ+BQWq7+d9rQAlNhl
|
||||
Pl/8zxII1JpKXFy7LYAqDFRhc2sgQ3JlYXRlZDABOT9FTgymhyMYQcxYTwymhyMYSi4KCGNyZXdf
|
||||
a2V5EiIKIDY2MmM2ZGVjOTYwOTU3ZjA0Y2JlNjQyNzFiYjE2NzNlSjEKB2NyZXdfaWQSJgokNjMw
|
||||
MjBhNzAtYmViMS00Mzc4LTkxZDgtYWJiMzI4ZGNhYTZlSi4KCHRhc2tfa2V5EiIKIGQ1YzQ1MjNl
|
||||
NGNhMzQ0NGRlMzViZjYzMGI1MmY3YWRjSjEKB3Rhc2tfaWQSJgokZjUyMTc0NGMtMDMwMi00MjQw
|
||||
LTk0OGMtM2M5Y2IzYWNlMjZjegIYAYUBAAEAABKUAQoQV34P2QyEIPkc/ibS8FHiNhIIrkMe+DzL
|
||||
MDUqClRvb2wgVXNhZ2UwATmIr9IMpocjGEHEyuAMpocjGEobCg5jcmV3YWlfdmVyc2lvbhIJCgcw
|
||||
LjEwMC4xSh8KCXRvb2xfbmFtZRISChBnZXRfZmluYWxfYW5zd2VySg4KCGF0dGVtcHRzEgIYAXoC
|
||||
GAGFAQABAAASsgcKEGkkxCNWp39iZUAo3mi2q28SCIV+msckPzvFKgxDcmV3IENyZWF0ZWQwATnn
|
||||
QukNpocjGEFCivYNpocjGEobCg5jcmV3YWlfdmVyc2lvbhIJCgcwLjEwMC4xShoKDnB5dGhvbl92
|
||||
ZXJzaW9uEggKBjMuMTIuN0ouCghjcmV3X2tleRIiCiA3M2FhYzI4NWU2NzQ2NjY3Zjc1MTQ3Njcw
|
||||
MDAzNDExMEoxCgdjcmV3X2lkEiYKJDM4Y2YzMGI4LTVkZTktNDBjOC04YTE0LTNkN2M2ODg2NTI1
|
||||
NkocCgxjcmV3X3Byb2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtjcmV3X21lbW9yeRICEABKGgoUY3Jl
|
||||
d19udW1iZXJfb2ZfdGFza3MSAhgBShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxICGAFKzgIKC2Ny
|
||||
ZXdfYWdlbnRzEr4CCrsCW3sia2V5IjogImUxNDhlNTMyMDI5MzQ5OWY4Y2ViZWE4MjZlNzI1ODJi
|
||||
IiwgImlkIjogImVkMjlhYWFiLTIxMWEtNGU1Yi1iODMyLTZjMzhhMDkzZTVmYyIsICJyb2xlIjog
|
||||
InRlc3Qgcm9sZSIsICJ2ZXJib3NlPyI6IHRydWUsICJtYXhfaXRlciI6IDEsICJtYXhfcnBtIjog
|
||||
bnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAiZ3B0LTRvLW1pbmkiLCAi
|
||||
ZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9leGVjdXRpb24/IjogZmFs
|
||||
c2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBbXX1dSpACCgpjcmV3X3Rh
|
||||
c2tzEoECCv4BW3sia2V5IjogImY3YTlmN2JiMWFlZTRiNmVmMmM1MjZkMGE4YzJmMmFjIiwgImlk
|
||||
IjogIjc0ZWJlOTdmLTc1NDEtNDllYS05MGQ2LTk0MTkyM2FkMzhjYyIsICJhc3luY19leGVjdXRp
|
||||
b24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAidGVzdCBy
|
||||
b2xlIiwgImFnZW50X2tleSI6ICJlMTQ4ZTUzMjAyOTM0OTlmOGNlYmVhODI2ZTcyNTgyYiIsICJ0
|
||||
b29sc19uYW1lcyI6IFsiZ2V0X2ZpbmFsX2Fuc3dlciJdfV16AhgBhQEAAQAAEo4CChDoONvPxkry
|
||||
DEs+JOeCy8PREgjXCZBRp7vclCoMVGFzayBDcmVhdGVkMAE5BisFDqaHIxhBjvwFDqaHIxhKLgoI
|
||||
Y3Jld19rZXkSIgogNzNhYWMyODVlNjc0NjY2N2Y3NTE0NzY3MDAwMzQxMTBKMQoHY3Jld19pZBIm
|
||||
CiQzOGNmMzBiOC01ZGU5LTQwYzgtOGExNC0zZDdjNjg4NjUyNTZKLgoIdGFza19rZXkSIgogZjdh
|
||||
OWY3YmIxYWVlNGI2ZWYyYzUyNmQwYThjMmYyYWNKMQoHdGFza19pZBImCiQ3NGViZTk3Zi03NTQx
|
||||
LTQ5ZWEtOTBkNi05NDE5MjNhZDM4Y2N6AhgBhQEAAQAAEnoKEI0vUGKYu+8WE4fMmZTS22ISCO0J
|
||||
DOoPb7UuKhBUb29sIFVzYWdlIEVycm9yMAE5Tel7DqaHIxhB8YOZDqaHIxhKGwoOY3Jld2FpX3Zl
|
||||
cnNpb24SCQoHMC4xMDAuMUoPCgNsbG0SCAoGZ3B0LTRvegIYAYUBAAEAABKyBwoQMvqS/DMlHmIr
|
||||
4XWzZfwN+BIImIMB8+nKOO0qDENyZXcgQ3JlYXRlZDABOTNO6w+mhyMYQeUq+Q+mhyMYShsKDmNy
|
||||
ZXdhaV92ZXJzaW9uEgkKBzAuMTAwLjFKGgoOcHl0aG9uX3ZlcnNpb24SCAoGMy4xMi43Si4KCGNy
|
||||
ZXdfa2V5EiIKIGQ1NTExM2JlNGFhNDFiYTY0M2QzMjYwNDJiMmYwM2YxSjEKB2NyZXdfaWQSJgok
|
||||
MDY4YTJkNjEtOTAzYS00MzZiLTg4MDItNDIxZTZiNmE3MGJjShwKDGNyZXdfcHJvY2VzcxIMCgpz
|
||||
ZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGAFK
|
||||
GwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrOAgoLY3Jld19hZ2VudHMSvgIKuwJbeyJrZXki
|
||||
OiAiZTE0OGU1MzIwMjkzNDk5ZjhjZWJlYTgyNmU3MjU4MmIiLCAiaWQiOiAiOTM2ZWE4ODYtZjU3
|
||||
ZS00MjgxLTk0ZGQtZjJlMjVlYjJhMTNkIiwgInJvbGUiOiAidGVzdCByb2xlIiwgInZlcmJvc2U/
|
||||
IjogdHJ1ZSwgIm1heF9pdGVyIjogNiwgIm1heF9ycG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGlu
|
||||
Z19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8tbWluaSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/Ijog
|
||||
ZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8iOiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6
|
||||
IDIsICJ0b29sc19uYW1lcyI6IFtdfV1KkAIKCmNyZXdfdGFza3MSgQIK/gFbeyJrZXkiOiAiNGEz
|
||||
MWI4NTEzM2EzYTI5NGM2ODUzZGE3NTdkNGJhZTciLCAiaWQiOiAiNjdlOGU2OWUtMjE2Zi00NDMz
|
||||
LWJkZTktODUzMDkxYmQ2M2ZiIiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lu
|
||||
cHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJ0ZXN0IHJvbGUiLCAiYWdlbnRfa2V5IjogImUx
|
||||
NDhlNTMyMDI5MzQ5OWY4Y2ViZWE4MjZlNzI1ODJiIiwgInRvb2xzX25hbWVzIjogWyJnZXRfZmlu
|
||||
YWxfYW5zd2VyIl19XXoCGAGFAQABAAASjgIKEGaV58NpXTIH37392KbVZVgSCELTtfkQZY08KgxU
|
||||
YXNrIENyZWF0ZWQwATn9twYQpocjGEEOfgcQpocjGEouCghjcmV3X2tleRIiCiBkNTUxMTNiZTRh
|
||||
YTQxYmE2NDNkMzI2MDQyYjJmMDNmMUoxCgdjcmV3X2lkEiYKJDA2OGEyZDYxLTkwM2EtNDM2Yi04
|
||||
ODAyLTQyMWU2YjZhNzBiY0ouCgh0YXNrX2tleRIiCiA0YTMxYjg1MTMzYTNhMjk0YzY4NTNkYTc1
|
||||
N2Q0YmFlN0oxCgd0YXNrX2lkEiYKJDY3ZThlNjllLTIxNmYtNDQzMy1iZGU5LTg1MzA5MWJkNjNm
|
||||
YnoCGAGFAQABAAASlAEKEEh8AzAk2LS47mJPi2BhJPoSCHXE9RN6/ozHKgpUb29sIFVzYWdlMAE5
|
||||
9cp6EKaHIxhBR1aJEKaHIxhKGwoOY3Jld2FpX3ZlcnNpb24SCQoHMC4xMDAuMUofCgl0b29sX25h
|
||||
bWUSEgoQZ2V0X2ZpbmFsX2Fuc3dlckoOCghhdHRlbXB0cxICGAF6AhgBhQEAAQAAEp0BChCzd3ky
|
||||
pwukySIl175RWJzvEggrqq6SZW6W6ioTVG9vbCBSZXBlYXRlZCBVc2FnZTABORziHRGmhyMYQSTb
|
||||
KxGmhyMYShsKDmNyZXdhaV92ZXJzaW9uEgkKBzAuMTAwLjFKHwoJdG9vbF9uYW1lEhIKEGdldF9m
|
||||
aW5hbF9hbnN3ZXJKDgoIYXR0ZW1wdHMSAhgBegIYAYUBAAEAABKUAQoQUYj+smQA6GbrNV4GT9DH
|
||||
BhIIGsr/6DK5CMgqClRvb2wgVXNhZ2UwATlH37URpocjGEFtfs0RpocjGEobCg5jcmV3YWlfdmVy
|
||||
c2lvbhIJCgcwLjEwMC4xSh8KCXRvb2xfbmFtZRISChBnZXRfZmluYWxfYW5zd2VySg4KCGF0dGVt
|
||||
cHRzEgIYAXoCGAGFAQABAAASnQEKEDOBcAEbzyT+AMpoVKVLWugSCPK2SYZnBhipKhNUb29sIFJl
|
||||
cGVhdGVkIFVzYWdlMAE5hbMiE6aHIxhBmQgxE6aHIxhKGwoOY3Jld2FpX3ZlcnNpb24SCQoHMC4x
|
||||
MDAuMUofCgl0b29sX25hbWUSEgoQZ2V0X2ZpbmFsX2Fuc3dlckoOCghhdHRlbXB0cxICGAF6AhgB
|
||||
hQEAAQAAEpQBChB3FfYjXtxkIEzP4nC9KB/sEgghrwSEFvS8oSoKVG9vbCBVc2FnZTABOWnQ5xOm
|
||||
hyMYQWRg/hOmhyMYShsKDmNyZXdhaV92ZXJzaW9uEgkKBzAuMTAwLjFKHwoJdG9vbF9uYW1lEhIK
|
||||
EGdldF9maW5hbF9hbnN3ZXJKDgoIYXR0ZW1wdHMSAhgBegIYAYUBAAEAABK5DQoQXIROu558ieRP
|
||||
fHllAZD4CxIIEOqEEUcv8/kqDENyZXcgQ3JlYXRlZDABOW/9eRWmhyMYQdELiRWmhyMYShsKDmNy
|
||||
ZXdhaV92ZXJzaW9uEgkKBzAuMTAwLjFKGgoOcHl0aG9uX3ZlcnNpb24SCAoGMy4xMi43Si4KCGNy
|
||||
ZXdfa2V5EiIKIDExMWI4NzJkOGYwY2Y3MDNmMmVmZWYwNGNmM2FjNzk4SjEKB2NyZXdfaWQSJgok
|
||||
MzNmYTM5YmMtZjFlYy00ZmUwLWJlNmQtMTQ3ZTc0ZGQ1NGNjShwKDGNyZXdfcHJvY2VzcxIMCgpz
|
||||
ZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGANK
|
||||
GwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAkqOBQoLY3Jld19hZ2VudHMS/gQK+wRbeyJrZXki
|
||||
OiAiZTE0OGU1MzIwMjkzNDk5ZjhjZWJlYTgyNmU3MjU4MmIiLCAiaWQiOiAiOTYwMmQxZTItZjlh
|
||||
Yy00ZGIyLTkwOWEtODAwY2I3NWY5ZTE1IiwgInJvbGUiOiAidGVzdCByb2xlIiwgInZlcmJvc2U/
|
||||
IjogZmFsc2UsICJtYXhfaXRlciI6IDI1LCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxs
|
||||
aW5nX2xsbSI6ICIiLCAibGxtIjogImdwdC00by1taW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8i
|
||||
OiBmYWxzZSwgImFsbG93X2NvZGVfZXhlY3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0
|
||||
IjogMiwgInRvb2xzX25hbWVzIjogW119LCB7ImtleSI6ICJlN2U4ZWVhODg2YmNiOGYxMDQ1YWJl
|
||||
ZWNmMTQyNWRiNyIsICJpZCI6ICIwZGE4OWUyZi0zYTQwLTQ1YzktOWRmMS1mNzFhNGU2Y2QzYzUi
|
||||
LCAicm9sZSI6ICJ0ZXN0IHJvbGUyIiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDI1
|
||||
LCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdw
|
||||
dC00by1taW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhl
|
||||
Y3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119
|
||||
XUrXBQoKY3Jld190YXNrcxLIBQrFBVt7ImtleSI6ICIzMjJkZGFlM2JjODBjMWQ0NWI4NWZhNzc1
|
||||
NmRiODY2NSIsICJpZCI6ICI5OTg4NmI2My01Nzg4LTQ0NTItODRmOC0zYzY0MDczOTYwYzciLCAi
|
||||
YXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9y
|
||||
b2xlIjogInRlc3Qgcm9sZSIsICJhZ2VudF9rZXkiOiAiZTE0OGU1MzIwMjkzNDk5ZjhjZWJlYTgy
|
||||
NmU3MjU4MmIiLCAidG9vbHNfbmFtZXMiOiBbXX0sIHsia2V5IjogImNjNDg3NmY2ZTU4OGU3MTM0
|
||||
OWJiZDNhNjU4ODhjM2U5IiwgImlkIjogIjMzMjA4N2YyLTFjMTEtNDAwMS1hMTEyLWFmY2FiYmI5
|
||||
Njk1MyIsICJhc3luY19leGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwg
|
||||
ImFnZW50X3JvbGUiOiAidGVzdCByb2xlIiwgImFnZW50X2tleSI6ICJlMTQ4ZTUzMjAyOTM0OTlm
|
||||
OGNlYmVhODI2ZTcyNTgyYiIsICJ0b29sc19uYW1lcyI6IFtdfSwgeyJrZXkiOiAiZTBiMTNlMTBk
|
||||
N2ExNDZkY2M0YzQ4OGZjZjhkNzQ4YTAiLCAiaWQiOiAiY2U5NmRlN2QtZGExMC00Njk2LTlhNTkt
|
||||
YTg1MDhmZTY2NWMyIiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6
|
||||
IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJ0ZXN0IHJvbGUyIiwgImFnZW50X2tleSI6ICJlN2U4ZWVh
|
||||
ODg2YmNiOGYxMDQ1YWJlZWNmMTQyNWRiNyIsICJ0b29sc19uYW1lcyI6IFtdfV16AhgBhQEAAQAA
|
||||
Eo4CChDqXo3uZlXRf0tyERPYj7KwEghUu1XP/N+QEioMVGFzayBDcmVhdGVkMAE57i+dFaaHIxhB
|
||||
OCueFaaHIxhKLgoIY3Jld19rZXkSIgogMTExYjg3MmQ4ZjBjZjcwM2YyZWZlZjA0Y2YzYWM3OThK
|
||||
MQoHY3Jld19pZBImCiQzM2ZhMzliYy1mMWVjLTRmZTAtYmU2ZC0xNDdlNzRkZDU0Y2NKLgoIdGFz
|
||||
a19rZXkSIgogMzIyZGRhZTNiYzgwYzFkNDViODVmYTc3NTZkYjg2NjVKMQoHdGFza19pZBImCiQ5
|
||||
OTg4NmI2My01Nzg4LTQ0NTItODRmOC0zYzY0MDczOTYwYzd6AhgBhQEAAQAAEo4CChD2ppz92+1X
|
||||
nsFyeUidGflsEgjs++pdB/O4vCoMVGFzayBDcmVhdGVkMAE50rwbFqaHIxhBOt4cFqaHIxhKLgoI
|
||||
Y3Jld19rZXkSIgogMTExYjg3MmQ4ZjBjZjcwM2YyZWZlZjA0Y2YzYWM3OThKMQoHY3Jld19pZBIm
|
||||
CiQzM2ZhMzliYy1mMWVjLTRmZTAtYmU2ZC0xNDdlNzRkZDU0Y2NKLgoIdGFza19rZXkSIgogY2M0
|
||||
ODc2ZjZlNTg4ZTcxMzQ5YmJkM2E2NTg4OGMzZTlKMQoHdGFza19pZBImCiQzMzIwODdmMi0xYzEx
|
||||
LTQwMDEtYTExMi1hZmNhYmJiOTY5NTN6AhgBhQEAAQAAEo4CChBKTvTil7rKpq45TVdxFxqREggS
|
||||
zhu00X/2PSoMVGFzayBDcmVhdGVkMAE5iSuaFqaHIxhBHUebFqaHIxhKLgoIY3Jld19rZXkSIgog
|
||||
MTExYjg3MmQ4ZjBjZjcwM2YyZWZlZjA0Y2YzYWM3OThKMQoHY3Jld19pZBImCiQzM2ZhMzliYy1m
|
||||
MWVjLTRmZTAtYmU2ZC0xNDdlNzRkZDU0Y2NKLgoIdGFza19rZXkSIgogZTBiMTNlMTBkN2ExNDZk
|
||||
Y2M0YzQ4OGZjZjhkNzQ4YTBKMQoHdGFza19pZBImCiRjZTk2ZGU3ZC1kYTEwLTQ2OTYtOWE1OS1h
|
||||
ODUwOGZlNjY1YzJ6AhgBhQEAAQAAEsIHChAlrVT+CvbPT7TFNWhLq8emEggMSwlN59fjTioMQ3Jl
|
||||
dyBDcmVhdGVkMAE5QzavF6aHIxhBcmC9F6aHIxhKGwoOY3Jld2FpX3ZlcnNpb24SCQoHMC4xMDAu
|
||||
MUoaCg5weXRob25fdmVyc2lvbhIICgYzLjEyLjdKLgoIY3Jld19rZXkSIgogNDk0ZjM2NTcyMzdh
|
||||
ZDhhMzAzNWIyZjFiZWVjZGM2NzdKMQoHY3Jld19pZBImCiRhY2Q2MjVhZS00MzlkLTRhODEtYTA5
|
||||
My1kZWIxMGU0M2Q1NTRKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1v
|
||||
cnkSAhAAShoKFGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2Vu
|
||||
dHMSAhgBSuACCgtjcmV3X2FnZW50cxLQAgrNAlt7ImtleSI6ICJlMTQ4ZTUzMjAyOTM0OTlmOGNl
|
||||
YmVhODI2ZTcyNTgyYiIsICJpZCI6ICIyYjNjMGFmYS1jOTk2LTRhM2QtODM1NC1hNDkwY2U3OGIy
|
||||
OTQiLCAicm9sZSI6ICJ0ZXN0IHJvbGUiLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjog
|
||||
MjUsICJtYXhfcnBtIjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAi
|
||||
Z3B0LTRvLW1pbmkiLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9l
|
||||
eGVjdXRpb24/IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBb
|
||||
ImxlYXJuX2Fib3V0X2FpIl19XUqOAgoKY3Jld190YXNrcxL/AQr8AVt7ImtleSI6ICJmMjU5N2M3
|
||||
ODY3ZmJlMzI0ZGM2NWRjMDhkZmRiZmM2YyIsICJpZCI6ICI5M2U0MjdkMS04YmIxLTRlMDAtODZk
|
||||
Yy01ZDk2MmI1MmE1ZGQiLCAiYXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/
|
||||
IjogZmFsc2UsICJhZ2VudF9yb2xlIjogInRlc3Qgcm9sZSIsICJhZ2VudF9rZXkiOiAiZTE0OGU1
|
||||
MzIwMjkzNDk5ZjhjZWJlYTgyNmU3MjU4MmIiLCAidG9vbHNfbmFtZXMiOiBbImxlYXJuX2Fib3V0
|
||||
X2FpIl19XXoCGAGFAQABAAASjgIKEBir/i8Yuwo5eqCwrCXydXISCKC4mPrpqM5hKgxUYXNrIENy
|
||||
ZWF0ZWQwATk2q88XpocjGEHxetAXpocjGEouCghjcmV3X2tleRIiCiA0OTRmMzY1NzIzN2FkOGEz
|
||||
MDM1YjJmMWJlZWNkYzY3N0oxCgdjcmV3X2lkEiYKJGFjZDYyNWFlLTQzOWQtNGE4MS1hMDkzLWRl
|
||||
YjEwZTQzZDU1NEouCgh0YXNrX2tleRIiCiBmMjU5N2M3ODY3ZmJlMzI0ZGM2NWRjMDhkZmRiZmM2
|
||||
Y0oxCgd0YXNrX2lkEiYKJDkzZTQyN2QxLThiYjEtNGUwMC04NmRjLTVkOTYyYjUyYTVkZHoCGAGF
|
||||
AQABAAASkgEKEMZPEzWpSFQyx5JvYLLY+BESCOdcWyQw5t+1KgpUb29sIFVzYWdlMAE53AREGKaH
|
||||
IxhB1YJSGKaHIxhKGwoOY3Jld2FpX3ZlcnNpb24SCQoHMC4xMDAuMUodCgl0b29sX25hbWUSEAoO
|
||||
bGVhcm5fYWJvdXRfQUlKDgoIYXR0ZW1wdHMSAhgBegIYAYUBAAEAABLCBwoQomj0lr7AK5BqLSUX
|
||||
aDeRMBIIFHur5REs4QoqDENyZXcgQ3JlYXRlZDABOY7TUZumhyMYQZILZ5umhyMYShsKDmNyZXdh
|
||||
aV92ZXJzaW9uEgkKBzAuMTAwLjFKGgoOcHl0aG9uX3ZlcnNpb24SCAoGMy4xMi43Si4KCGNyZXdf
|
||||
a2V5EiIKIDQ5NGYzNjU3MjM3YWQ4YTMwMzViMmYxYmVlY2RjNjc3SjEKB2NyZXdfaWQSJgokMzMy
|
||||
YzE5OGUtZDYxYy00YjBiLThlZGUtYjc3ZTQ5MDExM2E4ShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1
|
||||
ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGAFKGwoV
|
||||
Y3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrgAgoLY3Jld19hZ2VudHMS0AIKzQJbeyJrZXkiOiAi
|
||||
ZTE0OGU1MzIwMjkzNDk5ZjhjZWJlYTgyNmU3MjU4MmIiLCAiaWQiOiAiYTNmMGQ3MGQtMTc3Mi00
|
||||
YjczLTk1MzAtMmM5Y2IwZDBiOTVhIiwgInJvbGUiOiAidGVzdCByb2xlIiwgInZlcmJvc2U/Ijog
|
||||
ZmFsc2UsICJtYXhfaXRlciI6IDIsICJtYXhfcnBtIjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdf
|
||||
bGxtIjogImdwdC00byIsICJsbG0iOiAiZ3B0LTRvIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBm
|
||||
YWxzZSwgImFsbG93X2NvZGVfZXhlY3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0Ijog
|
||||
MiwgInRvb2xzX25hbWVzIjogWyJsZWFybl9hYm91dF9haSJdfV1KjgIKCmNyZXdfdGFza3MS/wEK
|
||||
/AFbeyJrZXkiOiAiZjI1OTdjNzg2N2ZiZTMyNGRjNjVkYzA4ZGZkYmZjNmMiLCAiaWQiOiAiZDFi
|
||||
ZmI3NDktMmZiYy00ZGE2LTlhM2MtOTliMTJlNzUyYjQ0IiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBm
|
||||
YWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJ0ZXN0IHJvbGUiLCAi
|
||||
YWdlbnRfa2V5IjogImUxNDhlNTMyMDI5MzQ5OWY4Y2ViZWE4MjZlNzI1ODJiIiwgInRvb2xzX25h
|
||||
bWVzIjogWyJsZWFybl9hYm91dF9haSJdfV16AhgBhQEAAQAAEo4CChDjFahoUTbbMYvI8KwBF9Tr
|
||||
EggmfAwRdRRm5SoMVGFzayBDcmVhdGVkMAE5J+h8m6aHIxhBOeR9m6aHIxhKLgoIY3Jld19rZXkS
|
||||
IgogNDk0ZjM2NTcyMzdhZDhhMzAzNWIyZjFiZWVjZGM2NzdKMQoHY3Jld19pZBImCiQzMzJjMTk4
|
||||
ZS1kNjFjLTRiMGItOGVkZS1iNzdlNDkwMTEzYThKLgoIdGFza19rZXkSIgogZjI1OTdjNzg2N2Zi
|
||||
ZTMyNGRjNjVkYzA4ZGZkYmZjNmNKMQoHdGFza19pZBImCiRkMWJmYjc0OS0yZmJjLTRkYTYtOWEz
|
||||
Yy05OWIxMmU3NTJiNDR6AhgBhQEAAQAAEnoKED9v1dCouoYEnAdjpclmSm8SCL0zBBWtAqsyKhBU
|
||||
b29sIFVzYWdlIEVycm9yMAE5Wnx6n6aHIxhBvWGun6aHIxhKGwoOY3Jld2FpX3ZlcnNpb24SCQoH
|
||||
MC4xMDAuMUoPCgNsbG0SCAoGZ3B0LTRvegIYAYUBAAEAABJ6ChCENZSS4wMA5EFWIKBlfO6QEggA
|
||||
tZqec6JSdCoQVG9vbCBVc2FnZSBFcnJvcjABOfvbiaKmhyMYQYCamqKmhyMYShsKDmNyZXdhaV92
|
||||
ZXJzaW9uEgkKBzAuMTAwLjFKDwoDbGxtEggKBmdwdC00b3oCGAGFAQABAAASygcKEN1aqPyHcoWp
|
||||
eE1b1N1vJi0SCOEmnsEv+HMpKgxDcmV3IENyZWF0ZWQwATlLquClpocjGEFQBfKlpocjGEobCg5j
|
||||
cmV3YWlfdmVyc2lvbhIJCgcwLjEwMC4xShoKDnB5dGhvbl92ZXJzaW9uEggKBjMuMTIuN0ouCghj
|
||||
cmV3X2tleRIiCiA3ZTY2MDg5ODk4NTlhNjdlZWM4OGVlZjdmY2U4NTIyNUoxCgdjcmV3X2lkEiYK
|
||||
JDJkNGE4Y2RhLWZlOTgtNGZjZi1hNzcxLTNlNjhhNmE4NTJjN0ocCgxjcmV3X3Byb2Nlc3MSDAoK
|
||||
c2VxdWVudGlhbEoRCgtjcmV3X21lbW9yeRICEABKGgoUY3Jld19udW1iZXJfb2ZfdGFza3MSAhgB
|
||||
ShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxICGAFK5AIKC2NyZXdfYWdlbnRzEtQCCtECW3sia2V5
|
||||
IjogIjIyYWNkNjExZTQ0ZWY1ZmFjMDViNTMzZDc1ZTg4OTNiIiwgImlkIjogImEzYzZkMjMxLTcy
|
||||
OTctNDgyNC04NmQyLWU3NTZiZWU3ZGE1YSIsICJyb2xlIjogIkRhdGEgU2NpZW50aXN0IiwgInZl
|
||||
cmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDI1LCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlv
|
||||
bl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdwdC00by1taW5pIiwgImRlbGVnYXRpb25fZW5h
|
||||
YmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhlY3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5
|
||||
X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogWyJnZXQgZ3JlZXRpbmdzIl19XUqSAgoKY3Jld190
|
||||
YXNrcxKDAgqAAlt7ImtleSI6ICJhMjc3YjM0YjJjMTQ2ZjBjNTZjNWUxMzU2ZThmOGE1NyIsICJp
|
||||
ZCI6ICI5MWQ0ZWU3NS1mNDY0LTQ4YzEtYjJkZC0wYjZmZTMyYzAxMmIiLCAiYXN5bmNfZXhlY3V0
|
||||
aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9yb2xlIjogIkRhdGEg
|
||||
U2NpZW50aXN0IiwgImFnZW50X2tleSI6ICIyMmFjZDYxMWU0NGVmNWZhYzA1YjUzM2Q3NWU4ODkz
|
||||
YiIsICJ0b29sc19uYW1lcyI6IFsiZ2V0IGdyZWV0aW5ncyJdfV16AhgBhQEAAQAAEo4CChBUckKs
|
||||
B6Al8OagM3U/UHTpEghEvQvFRhWPqCoMVGFzayBDcmVhdGVkMAE57xcDpqaHIxhBuwoEpqaHIxhK
|
||||
LgoIY3Jld19rZXkSIgogN2U2NjA4OTg5ODU5YTY3ZWVjODhlZWY3ZmNlODUyMjVKMQoHY3Jld19p
|
||||
ZBImCiQyZDRhOGNkYS1mZTk4LTRmY2YtYTc3MS0zZTY4YTZhODUyYzdKLgoIdGFza19rZXkSIgog
|
||||
YTI3N2IzNGIyYzE0NmYwYzU2YzVlMTM1NmU4ZjhhNTdKMQoHdGFza19pZBImCiQ5MWQ0ZWU3NS1m
|
||||
NDY0LTQ4YzEtYjJkZC0wYjZmZTMyYzAxMmJ6AhgBhQEAAQAAEpEBChBElVMk3xFnvFvmGOoU1XfF
|
||||
EgjUz8AahspUaSoKVG9vbCBVc2FnZTABOWXFmaamhyMYQc4NqqamhyMYShsKDmNyZXdhaV92ZXJz
|
||||
aW9uEgkKBzAuMTAwLjFKHAoJdG9vbF9uYW1lEg8KDUdldCBHcmVldGluZ3NKDgoIYXR0ZW1wdHMS
|
||||
AhgBegIYAYUBAAEAABLWBwoQTaWq89khjN2C0KBrprtQwxIInOhi64SISYsqDENyZXcgQ3JlYXRl
|
||||
ZDABOSt3VqemhyMYQYs4Z6emhyMYShsKDmNyZXdhaV92ZXJzaW9uEgkKBzAuMTAwLjFKGgoOcHl0
|
||||
aG9uX3ZlcnNpb24SCAoGMy4xMi43Si4KCGNyZXdfa2V5EiIKIGMzMDc2MDA5MzI2NzYxNDQ0ZDU3
|
||||
YzcxZDFkYTNmMjdjSjEKB2NyZXdfaWQSJgokMThkMzYxNGMtOGYzMy00YmNjLTgyZjEtNTJjOGEz
|
||||
NDQ0YWJiShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoa
|
||||
ChRjcmV3X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrq
|
||||
AgoLY3Jld19hZ2VudHMS2gIK1wJbeyJrZXkiOiAiOThmM2IxZDQ3Y2U5NjljZjA1NzcyN2I3ODQx
|
||||
NDI1Y2QiLCAiaWQiOiAiNGE2NzUzNTEtYWYxZS00MzE0LWI1ZjItYzI2ZTQ1MmEwNzExIiwgInJv
|
||||
bGUiOiAiRnJpZW5kbHkgTmVpZ2hib3IiLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjog
|
||||
MjUsICJtYXhfcnBtIjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAi
|
||||
Z3B0LTRvLW1pbmkiLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9l
|
||||
eGVjdXRpb24/IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBb
|
||||
ImRlY2lkZSBncmVldGluZ3MiXX1dSpgCCgpjcmV3X3Rhc2tzEokCCoYCW3sia2V5IjogIjgwZDdi
|
||||
Y2Q0OTA5OTI5MDA4MzgzMmYwZTk4MzM4MGRmIiwgImlkIjogIjIxYWY3MGNmLTAwMjgtNDMzMy1i
|
||||
OTQ0LTNmZGRlMDk0Yzk1YiIsICJhc3luY19leGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1
|
||||
dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAiRnJpZW5kbHkgTmVpZ2hib3IiLCAiYWdlbnRfa2V5
|
||||
IjogIjk4ZjNiMWQ0N2NlOTY5Y2YwNTc3MjdiNzg0MTQyNWNkIiwgInRvb2xzX25hbWVzIjogWyJk
|
||||
ZWNpZGUgZ3JlZXRpbmdzIl19XXoCGAGFAQABAAASjgIKECu51qyePo8nKoICNJZ02pMSCCjCEeTQ
|
||||
OjkdKgxUYXNrIENyZWF0ZWQwATnBBninpocjGEE/9XinpocjGEouCghjcmV3X2tleRIiCiBjMzA3
|
||||
NjAwOTMyNjc2MTQ0NGQ1N2M3MWQxZGEzZjI3Y0oxCgdjcmV3X2lkEiYKJDE4ZDM2MTRjLThmMzMt
|
||||
NGJjYy04MmYxLTUyYzhhMzQ0NGFiYkouCgh0YXNrX2tleRIiCiA4MGQ3YmNkNDkwOTkyOTAwODM4
|
||||
MzJmMGU5ODMzODBkZkoxCgd0YXNrX2lkEiYKJDIxYWY3MGNmLTAwMjgtNDMzMy1iOTQ0LTNmZGRl
|
||||
MDk0Yzk1YnoCGAGFAQABAAASlAEKEP375HtPk4PSSyJYXfVClzMSCD4pN5nJzh+6KgpUb29sIFVz
|
||||
YWdlMAE5340IqKaHIxhBuEQZqKaHIxhKGwoOY3Jld2FpX3ZlcnNpb24SCQoHMC4xMDAuMUofCgl0
|
||||
b29sX25hbWUSEgoQRGVjaWRlIEdyZWV0aW5nc0oOCghhdHRlbXB0cxICGAF6AhgBhQEAAQAA
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '15672'
|
||||
Content-Type:
|
||||
- application/x-protobuf
|
||||
User-Agent:
|
||||
- OTel-OTLP-Exporter-Python/1.27.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:
|
||||
- Wed, 12 Feb 2025 17:57:13 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
87
tests/cassettes/test_long_feedback_handling.yaml
Normal file
87
tests/cassettes/test_long_feedback_handling.yaml
Normal file
@@ -0,0 +1,87 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: '{"messages": [{"role": "system", "content": "You are test role. test backstory\nYour
|
||||
personal goal is: test goal\nTo give my best complete final answer to the task
|
||||
respond using the exact following format:\n\nThought: I now can give a great
|
||||
answer\nFinal Answer: Your 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!"}, {"role": "user", "content": "\nCurrent Task: Test task\n\nThis
|
||||
is the expected criteria for your final answer: Test output\nyou 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:"}], "model": "gpt-4o-mini", "stop": ["\nObservation:"]}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '811'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.openai.com
|
||||
user-agent:
|
||||
- OpenAI/Python 1.61.0
|
||||
x-stainless-arch:
|
||||
- x64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- Linux
|
||||
x-stainless-package-version:
|
||||
- 1.61.0
|
||||
x-stainless-raw-response:
|
||||
- 'true'
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.12.7
|
||||
method: POST
|
||||
uri: https://api.openai.com/v1/chat/completions
|
||||
response:
|
||||
content: "{\n \"error\": {\n \"message\": \"Incorrect API key provided:
|
||||
sk-proj-********************************************************************************************************************************************************sLcA.
|
||||
You can find your API key at https://platform.openai.com/account/api-keys.\",\n
|
||||
\ \"type\": \"invalid_request_error\",\n \"param\": null,\n \"code\":
|
||||
\"invalid_api_key\"\n }\n}\n"
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 910f1c7ccc8127f2-SEA
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '414'
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Date:
|
||||
- Wed, 12 Feb 2025 19:51:04 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- __cf_bm=uoaTXzwc1Tflq58CAcpdIc5LJh9YYja0fjw1f6h9WAw-1739389864-1.0.1.1-Ka49kxdgi8wyYRkDXc.Os2ipvsC.ix_sMqVQlLOpR2S1GwoPVnJhFDI59yvwNeTdTgt.BGGvVafkitRFhUAikw;
|
||||
path=/; expires=Wed, 12-Feb-25 20:21:04 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=0mZZJhB4.6zG3zb_yZrfjjsFaLI9JTnoBgNzXw6chnU-1739389864561-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
strict-transport-security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
vary:
|
||||
- Origin
|
||||
x-request-id:
|
||||
- req_aad5d7ba9d16d23112bcbae8689a4630
|
||||
http_version: HTTP/1.1
|
||||
status_code: 401
|
||||
version: 1
|
||||
@@ -1,18 +1,11 @@
|
||||
"""Test Flow creation and execution basic functionality."""
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
from pydantic import BaseModel
|
||||
|
||||
from crewai.flow.flow import Flow, and_, listen, or_, router, start
|
||||
from crewai.flow.flow_events import (
|
||||
FlowFinishedEvent,
|
||||
FlowStartedEvent,
|
||||
MethodExecutionFinishedEvent,
|
||||
MethodExecutionStartedEvent,
|
||||
)
|
||||
|
||||
|
||||
def test_simple_sequential_flow():
|
||||
@@ -405,218 +398,3 @@ def test_router_with_multiple_conditions():
|
||||
|
||||
# final_step should run after router_and
|
||||
assert execution_order.index("log_final_step") > execution_order.index("router_and")
|
||||
|
||||
|
||||
def test_unstructured_flow_event_emission():
|
||||
"""Test that the correct events are emitted during unstructured flow
|
||||
execution with all fields validated."""
|
||||
|
||||
class PoemFlow(Flow):
|
||||
@start()
|
||||
def prepare_flower(self):
|
||||
self.state["flower"] = "roses"
|
||||
return "foo"
|
||||
|
||||
@start()
|
||||
def prepare_color(self):
|
||||
self.state["color"] = "red"
|
||||
return "bar"
|
||||
|
||||
@listen(prepare_color)
|
||||
def write_first_sentence(self):
|
||||
return f"{self.state['flower']} are {self.state['color']}"
|
||||
|
||||
@listen(write_first_sentence)
|
||||
def finish_poem(self, first_sentence):
|
||||
separator = self.state.get("separator", "\n")
|
||||
return separator.join([first_sentence, "violets are blue"])
|
||||
|
||||
@listen(finish_poem)
|
||||
def save_poem_to_database(self):
|
||||
# A method without args/kwargs to ensure events are sent correctly
|
||||
pass
|
||||
|
||||
event_log = []
|
||||
|
||||
def handle_event(_, event):
|
||||
event_log.append(event)
|
||||
|
||||
flow = PoemFlow()
|
||||
flow.event_emitter.connect(handle_event)
|
||||
flow.kickoff(inputs={"separator": ", "})
|
||||
|
||||
assert isinstance(event_log[0], FlowStartedEvent)
|
||||
assert event_log[0].flow_name == "PoemFlow"
|
||||
assert event_log[0].inputs == {"separator": ", "}
|
||||
assert isinstance(event_log[0].timestamp, datetime)
|
||||
|
||||
# Asserting for concurrent start method executions in a for loop as you
|
||||
# can't guarantee ordering in asynchronous executions
|
||||
for i in range(1, 5):
|
||||
event = event_log[i]
|
||||
assert isinstance(event.state, dict)
|
||||
assert isinstance(event.state["id"], str)
|
||||
|
||||
if event.method_name == "prepare_flower":
|
||||
if isinstance(event, MethodExecutionStartedEvent):
|
||||
assert event.params == {}
|
||||
assert event.state["separator"] == ", "
|
||||
elif isinstance(event, MethodExecutionFinishedEvent):
|
||||
assert event.result == "foo"
|
||||
assert event.state["flower"] == "roses"
|
||||
assert event.state["separator"] == ", "
|
||||
else:
|
||||
assert False, "Unexpected event type for prepare_flower"
|
||||
elif event.method_name == "prepare_color":
|
||||
if isinstance(event, MethodExecutionStartedEvent):
|
||||
assert event.params == {}
|
||||
assert event.state["separator"] == ", "
|
||||
elif isinstance(event, MethodExecutionFinishedEvent):
|
||||
assert event.result == "bar"
|
||||
assert event.state["color"] == "red"
|
||||
assert event.state["separator"] == ", "
|
||||
else:
|
||||
assert False, "Unexpected event type for prepare_color"
|
||||
else:
|
||||
assert False, f"Unexpected method {event.method_name} in prepare events"
|
||||
|
||||
assert isinstance(event_log[5], MethodExecutionStartedEvent)
|
||||
assert event_log[5].method_name == "write_first_sentence"
|
||||
assert event_log[5].params == {}
|
||||
assert isinstance(event_log[5].state, dict)
|
||||
assert event_log[5].state["flower"] == "roses"
|
||||
assert event_log[5].state["color"] == "red"
|
||||
assert event_log[5].state["separator"] == ", "
|
||||
|
||||
assert isinstance(event_log[6], MethodExecutionFinishedEvent)
|
||||
assert event_log[6].method_name == "write_first_sentence"
|
||||
assert event_log[6].result == "roses are red"
|
||||
|
||||
assert isinstance(event_log[7], MethodExecutionStartedEvent)
|
||||
assert event_log[7].method_name == "finish_poem"
|
||||
assert event_log[7].params == {"_0": "roses are red"}
|
||||
assert isinstance(event_log[7].state, dict)
|
||||
assert event_log[7].state["flower"] == "roses"
|
||||
assert event_log[7].state["color"] == "red"
|
||||
|
||||
assert isinstance(event_log[8], MethodExecutionFinishedEvent)
|
||||
assert event_log[8].method_name == "finish_poem"
|
||||
assert event_log[8].result == "roses are red, violets are blue"
|
||||
|
||||
assert isinstance(event_log[9], MethodExecutionStartedEvent)
|
||||
assert event_log[9].method_name == "save_poem_to_database"
|
||||
assert event_log[9].params == {}
|
||||
assert isinstance(event_log[9].state, dict)
|
||||
assert event_log[9].state["flower"] == "roses"
|
||||
assert event_log[9].state["color"] == "red"
|
||||
|
||||
assert isinstance(event_log[10], MethodExecutionFinishedEvent)
|
||||
assert event_log[10].method_name == "save_poem_to_database"
|
||||
assert event_log[10].result is None
|
||||
|
||||
assert isinstance(event_log[11], FlowFinishedEvent)
|
||||
assert event_log[11].flow_name == "PoemFlow"
|
||||
assert event_log[11].result is None
|
||||
assert isinstance(event_log[11].timestamp, datetime)
|
||||
|
||||
|
||||
def test_structured_flow_event_emission():
|
||||
"""Test that the correct events are emitted during structured flow
|
||||
execution with all fields validated."""
|
||||
|
||||
class OnboardingState(BaseModel):
|
||||
name: str = ""
|
||||
sent: bool = False
|
||||
|
||||
class OnboardingFlow(Flow[OnboardingState]):
|
||||
@start()
|
||||
def user_signs_up(self):
|
||||
self.state.sent = False
|
||||
|
||||
@listen(user_signs_up)
|
||||
def send_welcome_message(self):
|
||||
self.state.sent = True
|
||||
return f"Welcome, {self.state.name}!"
|
||||
|
||||
event_log = []
|
||||
|
||||
def handle_event(_, event):
|
||||
event_log.append(event)
|
||||
|
||||
flow = OnboardingFlow()
|
||||
flow.event_emitter.connect(handle_event)
|
||||
flow.kickoff(inputs={"name": "Anakin"})
|
||||
|
||||
assert isinstance(event_log[0], FlowStartedEvent)
|
||||
assert event_log[0].flow_name == "OnboardingFlow"
|
||||
assert event_log[0].inputs == {"name": "Anakin"}
|
||||
assert isinstance(event_log[0].timestamp, datetime)
|
||||
|
||||
assert isinstance(event_log[1], MethodExecutionStartedEvent)
|
||||
assert event_log[1].method_name == "user_signs_up"
|
||||
|
||||
assert isinstance(event_log[2], MethodExecutionFinishedEvent)
|
||||
assert event_log[2].method_name == "user_signs_up"
|
||||
|
||||
assert isinstance(event_log[3], MethodExecutionStartedEvent)
|
||||
assert event_log[3].method_name == "send_welcome_message"
|
||||
assert event_log[3].params == {}
|
||||
assert getattr(event_log[3].state, "sent") is False
|
||||
|
||||
assert isinstance(event_log[4], MethodExecutionFinishedEvent)
|
||||
assert event_log[4].method_name == "send_welcome_message"
|
||||
assert getattr(event_log[4].state, "sent") is True
|
||||
assert event_log[4].result == "Welcome, Anakin!"
|
||||
|
||||
assert isinstance(event_log[5], FlowFinishedEvent)
|
||||
assert event_log[5].flow_name == "OnboardingFlow"
|
||||
assert event_log[5].result == "Welcome, Anakin!"
|
||||
assert isinstance(event_log[5].timestamp, datetime)
|
||||
|
||||
|
||||
def test_stateless_flow_event_emission():
|
||||
"""Test that the correct events are emitted stateless during flow execution
|
||||
with all fields validated."""
|
||||
|
||||
class StatelessFlow(Flow):
|
||||
@start()
|
||||
def init(self):
|
||||
pass
|
||||
|
||||
@listen(init)
|
||||
def process(self):
|
||||
return "Deeds will not be less valiant because they are unpraised."
|
||||
|
||||
event_log = []
|
||||
|
||||
def handle_event(_, event):
|
||||
event_log.append(event)
|
||||
|
||||
flow = StatelessFlow()
|
||||
flow.event_emitter.connect(handle_event)
|
||||
flow.kickoff()
|
||||
|
||||
assert isinstance(event_log[0], FlowStartedEvent)
|
||||
assert event_log[0].flow_name == "StatelessFlow"
|
||||
assert event_log[0].inputs is None
|
||||
assert isinstance(event_log[0].timestamp, datetime)
|
||||
|
||||
assert isinstance(event_log[1], MethodExecutionStartedEvent)
|
||||
assert event_log[1].method_name == "init"
|
||||
|
||||
assert isinstance(event_log[2], MethodExecutionFinishedEvent)
|
||||
assert event_log[2].method_name == "init"
|
||||
|
||||
assert isinstance(event_log[3], MethodExecutionStartedEvent)
|
||||
assert event_log[3].method_name == "process"
|
||||
|
||||
assert isinstance(event_log[4], MethodExecutionFinishedEvent)
|
||||
assert event_log[4].method_name == "process"
|
||||
|
||||
assert isinstance(event_log[5], FlowFinishedEvent)
|
||||
assert event_log[5].flow_name == "StatelessFlow"
|
||||
assert (
|
||||
event_log[5].result
|
||||
== "Deeds will not be less valiant because they are unpraised."
|
||||
)
|
||||
assert isinstance(event_log[5].timestamp, datetime)
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from crewai.tools import FAISSSearchTool
|
||||
|
||||
def test_faiss_search_tool_initialization():
|
||||
tool = FAISSSearchTool()
|
||||
assert tool.name == "FAISS Search Tool"
|
||||
assert tool.dimension == 384
|
||||
|
||||
def test_faiss_search_with_texts():
|
||||
tool = FAISSSearchTool()
|
||||
texts = [
|
||||
"The quick brown fox",
|
||||
"jumps over the lazy dog",
|
||||
"A completely different text"
|
||||
]
|
||||
tool.add_texts(texts)
|
||||
|
||||
results = tool.run(
|
||||
query="quick fox",
|
||||
k=2,
|
||||
score_threshold=0.5
|
||||
)
|
||||
|
||||
assert len(results) > 0
|
||||
assert isinstance(results[0]["text"], str)
|
||||
assert isinstance(results[0]["score"], float)
|
||||
|
||||
def test_faiss_search_threshold_filtering():
|
||||
tool = FAISSSearchTool()
|
||||
texts = ["Text A", "Text B", "Text C"]
|
||||
tool.add_texts(texts)
|
||||
|
||||
results = tool.run(
|
||||
query="Something completely different",
|
||||
score_threshold=0.99 # High threshold
|
||||
)
|
||||
|
||||
assert len(results) == 0 # No results above threshold
|
||||
|
||||
def test_invalid_index_type():
|
||||
with pytest.raises(ValueError):
|
||||
FAISSSearchTool(index_type="INVALID")
|
||||
419
uv.lock
generated
419
uv.lock
generated
@@ -198,6 +198,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/39/e3/893e8757be2612e6c266d9bb58ad2e3651524b5b40cf56761e985a28b13e/asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", size = 23828 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asn1crypto"
|
||||
version = "1.5.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/de/cf/d547feed25b5244fcb9392e288ff9fdc3280b10260362fc45d37a798a6ee/asn1crypto-1.5.1.tar.gz", hash = "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c", size = 121080 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/7f/09065fd9e27da0eda08b4d6897f1c13535066174cc023af248fc2a8d5e5a/asn1crypto-1.5.1-py2.py3-none-any.whl", hash = "sha256:db4e40728b728508912cbb3d44f19ce188f218e9eba635821bb4b68564f8fd67", size = 105045 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asttokens"
|
||||
version = "2.4.1"
|
||||
@@ -219,6 +228,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/fa/e01228c2938de91d47b307831c62ab9e4001e747789d0b05baf779a6488c/async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028", size = 5721 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atpublic"
|
||||
version = "5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5d/18/b1d247792440378abeeb0853f9daa2a127284b68776af6815990be7fcdb0/atpublic-5.0.tar.gz", hash = "sha256:d5cb6cbabf00ec1d34e282e8ce7cbc9b74ba4cb732e766c24e2d78d1ad7f723f", size = 14646 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/03/2cb0e5326e19b7d877bc9c3a7ef436a30a06835b638580d1f5e21a0409ed/atpublic-5.0-py3-none-any.whl", hash = "sha256:b651dcd886666b1042d1e38158a22a4f2c267748f4e97fde94bc492a4a28a3f3", size = 5207 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
version = "24.2.0"
|
||||
@@ -244,6 +262,18 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/0e/38cb7b781371e79e9c697fb78f3ccd18fda8bd547d0a2e76e616561a3792/auth0_python-4.7.2-py3-none-any.whl", hash = "sha256:df2224f9b1e170b3aa12d8bc7ff02eadb7cc229307a09ec6b8a55fd1e0e05dc8", size = 131834 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "authlib"
|
||||
version = "1.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cryptography" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/09/47/df70ecd34fbf86d69833fe4e25bb9ecbaab995c8e49df726dd416f6bb822/authlib-1.3.1.tar.gz", hash = "sha256:7ae843f03c06c5c0debd63c9db91f9fda64fa62a42a77419fa15fbb7e7a58917", size = 146074 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/87/1f/bc95e43ffb57c05b8efcc376dd55a0240bf58f47ddf5a0f92452b6457b75/Authlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:d35800b973099bbadc49b42b256ecb80041ad56b7fe1216a362c7943c088f377", size = 223827 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autoflake"
|
||||
version = "2.3.1"
|
||||
@@ -565,14 +595,14 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.1.8"
|
||||
version = "8.1.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "platform_system == 'Windows'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", size = 97941 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -619,7 +649,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "crewai"
|
||||
version = "0.102.0"
|
||||
version = "0.100.1"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "appdirs" },
|
||||
@@ -703,7 +733,7 @@ requires-dist = [
|
||||
{ name = "blinker", specifier = ">=1.9.0" },
|
||||
{ name = "chromadb", specifier = ">=0.5.23" },
|
||||
{ name = "click", specifier = ">=8.1.7" },
|
||||
{ name = "crewai-tools", marker = "extra == 'tools'", specifier = ">=0.36.0" },
|
||||
{ name = "crewai-tools", marker = "extra == 'tools'", specifier = ">=0.32.1" },
|
||||
{ name = "docling", marker = "extra == 'docling'", specifier = ">=2.12.0" },
|
||||
{ name = "fastembed", marker = "extra == 'fastembed'", specifier = ">=0.4.1" },
|
||||
{ name = "instructor", specifier = ">=1.3.3" },
|
||||
@@ -752,24 +782,33 @@ dev = [
|
||||
|
||||
[[package]]
|
||||
name = "crewai-tools"
|
||||
version = "0.36.0"
|
||||
version = "0.32.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "beautifulsoup4" },
|
||||
{ name = "chromadb" },
|
||||
{ name = "click" },
|
||||
{ name = "crewai" },
|
||||
{ name = "docker" },
|
||||
{ name = "docx2txt" },
|
||||
{ name = "embedchain" },
|
||||
{ name = "lancedb" },
|
||||
{ name = "linkup-sdk" },
|
||||
{ name = "openai" },
|
||||
{ name = "patronus" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "pyright" },
|
||||
{ name = "pytube" },
|
||||
{ name = "requests" },
|
||||
{ name = "scrapegraph-py" },
|
||||
{ name = "selenium" },
|
||||
{ name = "serpapi" },
|
||||
{ name = "snowflake" },
|
||||
{ name = "spider-client" },
|
||||
{ name = "weaviate-client" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4d/e1/d65778cf4aea106f3f60a4208521f04bc7f1d26be4e34eeb63cae6297d50/crewai_tools-0.36.0.tar.gz", hash = "sha256:761b396ee6a4019a988720dd6a14e1409f5de9d0cdc2a8662b487d87efb1a6bf", size = 900178 }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e9/e7/fb07f0089028f7c9003770641d21f5844d4fa22bf5cc4c4b3676bfa0e1fe/crewai_tools-0.32.1.tar.gz", hash = "sha256:41acea9243b17a463f355d48dfe7d73bd59738c8862a8da780eae008e0136414", size = 887378 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/b6/533632a6c2a2e623fc4a1677458aff3539413a196fb220a7fece4ead3f71/crewai_tools-0.36.0-py3-none-any.whl", hash = "sha256:dbd0d95a080acfb281e105f4376e1e98576dae6d53d94f7b883c57af893668b3", size = 545937 },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/f0/8f98f1a2b90b9b989bd01cf48b5e3bb2d842be2062bfd3177a77561e7b61/crewai_tools-0.32.1-py3-none-any.whl", hash = "sha256:6cb436dc66e19e35285a4fce501158a13bce99b244370574f568ec33c5513351", size = 537264 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1060,6 +1099,12 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/7c/e9fcff7623954d86bdc17782036cbf715ecab1bec4847c008557affe1ca8/docstring_parser-0.16-py3-none-any.whl", hash = "sha256:bf0a1387354d3691d102edef7ec124f219ef639982d096e26e3b60aeffa90637", size = 36533 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "docx2txt"
|
||||
version = "0.8"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/7d/7d/60ee3f2b16d9bfdfa72e8599470a2c1a5b759cb113c6fe1006be28359327/docx2txt-0.8.tar.gz", hash = "sha256:2c06d98d7cfe2d3947e5760a57d924e3ff07745b379c8737723922e7009236e5", size = 2814 }
|
||||
|
||||
[[package]]
|
||||
name = "durationpy"
|
||||
version = "0.9"
|
||||
@@ -1601,6 +1646,19 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/1f/acf03ee901313446d52c3916d527d4981de9f6f3edc69267d05509dcfa7b/grpcio-1.67.0-cp312-cp312-win_amd64.whl", hash = "sha256:985b2686f786f3e20326c4367eebdaed3e7aa65848260ff0c6644f817042cb15", size = 4343545 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grpcio-health-checking"
|
||||
version = "1.62.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "grpcio" },
|
||||
{ name = "protobuf" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/eb/9f/09df9b02fc8eafa3031d878c8a4674a0311293c8c6f1c942cdaeec204126/grpcio-health-checking-1.62.3.tar.gz", hash = "sha256:5074ba0ce8f0dcfe328408ec5c7551b2a835720ffd9b69dade7fa3e0dc1c7a93", size = 15640 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/40/4c/ee3173906196b741ac6ba55a9788ba9ebf2cd05f91715a49b6c3bfbb9d73/grpcio_health_checking-1.62.3-py3-none-any.whl", hash = "sha256:f29da7dd144d73b4465fe48f011a91453e9ff6c8af0d449254cf80021cab3e0d", size = 18547 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grpcio-status"
|
||||
version = "1.62.3"
|
||||
@@ -1812,6 +1870,52 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ijson"
|
||||
version = "3.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6c/83/28e9e93a3a61913e334e3a2e78ea9924bb9f9b1ac45898977f9d9dd6133f/ijson-3.3.0.tar.gz", hash = "sha256:7f172e6ba1bee0d4c8f8ebd639577bfe429dee0f3f96775a067b8bae4492d8a0", size = 60079 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/89/96e3608499b4a500b9bc27aa8242704e675849dd65bdfa8682b00a92477e/ijson-3.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7f7a5250599c366369fbf3bc4e176f5daa28eb6bc7d6130d02462ed335361675", size = 85009 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/7e/1098503500f5316c5f7912a51c91aca5cbc609c09ce4ecd9c4809983c560/ijson-3.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f87a7e52f79059f9c58f6886c262061065eb6f7554a587be7ed3aa63e6b71b34", size = 57796 },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/f7/27b8c27a285628719ff55b68507581c86b551eb162ce810fe51e3e1a25f2/ijson-3.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b73b493af9e947caed75d329676b1b801d673b17481962823a3e55fe529c8b8b", size = 57218 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/c5/1698094cb6a336a223c30e1167cc1b15cdb4bfa75399c1a2eb82fa76cc3c/ijson-3.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5576415f3d76290b160aa093ff968f8bf6de7d681e16e463a0134106b506f49", size = 117153 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/21/c206dda0945bd832cc9b0894596b0efc2cb1819a0ac61d8be1429ac09494/ijson-3.3.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e9ffe358d5fdd6b878a8a364e96e15ca7ca57b92a48f588378cef315a8b019e", size = 110781 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/f5/2d733e64577109a9b255d14d031e44a801fa20df9ccc58b54a31e8ecf9e6/ijson-3.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8643c255a25824ddd0895c59f2319c019e13e949dc37162f876c41a283361527", size = 114527 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/a8/78bfee312aa23417b86189a65f30b0edbceaee96dc6a616cc15f611187d1/ijson-3.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:df3ab5e078cab19f7eaeef1d5f063103e1ebf8c26d059767b26a6a0ad8b250a3", size = 116824 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/a4/aff410f7d6aa1a77ee2ab2d6a2d2758422726270cb149c908a9baf33cf58/ijson-3.3.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3dc1fb02c6ed0bae1b4bf96971258bf88aea72051b6e4cebae97cff7090c0607", size = 112647 },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/ee/2b5122dc4713f5a954267147da36e7156240ca21b04ed5295bc0cabf0fbe/ijson-3.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e9afd97339fc5a20f0542c971f90f3ca97e73d3050cdc488d540b63fae45329a", size = 114156 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/d7/ad3b266490b60c6939e8a07fd8e4b7e2002aea08eaa9572a016c3e3a9129/ijson-3.3.0-cp310-cp310-win32.whl", hash = "sha256:844c0d1c04c40fd1b60f148dc829d3f69b2de789d0ba239c35136efe9a386529", size = 48931 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/68/b9e1c743274c8a23dddb12d2ed13b5f021f6d21669d51ff7fa2e9e6c19df/ijson-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:d654d045adafdcc6c100e8e911508a2eedbd2a1b5f93f930ba13ea67d7704ee9", size = 50965 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/df/565ba72a6f4b2c833d051af8e2228cfa0b1fef17bb44995c00ad27470c52/ijson-3.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:501dce8eaa537e728aa35810656aa00460a2547dcb60937c8139f36ec344d7fc", size = 85041 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/42/1361eaa57ece921d0239881bae6a5e102333be5b6e0102a05ec3caadbd5a/ijson-3.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:658ba9cad0374d37b38c9893f4864f284cdcc7d32041f9808fba8c7bcaadf134", size = 57829 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/b0/143dbfe12e1d1303ea8d8cd6f40e95cea8f03bcad5b79708614a7856c22e/ijson-3.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2636cb8c0f1023ef16173f4b9a233bcdb1df11c400c603d5f299fac143ca8d70", size = 57217 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/80/b3b60c5e5be2839365b03b915718ca462c544fdc71e7a79b7262837995ef/ijson-3.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd174b90db68c3bcca273e9391934a25d76929d727dc75224bf244446b28b03b", size = 121878 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/eb/7560fafa4d40412efddf690cb65a9bf2d3429d6035e544103acbf5561dc4/ijson-3.3.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97a9aea46e2a8371c4cf5386d881de833ed782901ac9f67ebcb63bb3b7d115af", size = 115620 },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/2b/5a34c7841388dce161966e5286931518de832067cd83e6f003d93271e324/ijson-3.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c594c0abe69d9d6099f4ece17763d53072f65ba60b372d8ba6de8695ce6ee39e", size = 119200 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/b7/1d64fbec0d0a7b0c02e9ad988a89614532028ead8bb52a2456c92e6ee35a/ijson-3.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8e0ff16c224d9bfe4e9e6bd0395826096cda4a3ef51e6c301e1b61007ee2bd24", size = 121107 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/b9/01044f09850bc545ffc85b35aaec473d4f4ca2b6667299033d252c1b60dd/ijson-3.3.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0015354011303175eae7e2ef5136414e91de2298e5a2e9580ed100b728c07e51", size = 116658 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/0d/53856b61f3d952d299d1695c487e8e28058d01fa2adfba3d6d4b4660c242/ijson-3.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:034642558afa57351a0ffe6de89e63907c4cf6849070cc10a3b2542dccda1afe", size = 118186 },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/2d/5bd86e2307dd594840ee51c4e32de953fee837f028acf0f6afb08914cd06/ijson-3.3.0-cp311-cp311-win32.whl", hash = "sha256:192e4b65495978b0bce0c78e859d14772e841724d3269fc1667dc6d2f53cc0ea", size = 48938 },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/e1/4ba2b65b87f67fb19d698984d92635e46d9ce9dd748ce7d009441a586710/ijson-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:72e3488453754bdb45c878e31ce557ea87e1eb0f8b4fc610373da35e8074ce42", size = 50972 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/4d/3992f7383e26a950e02dc704bc6c5786a080d5c25fe0fc5543ef477c1883/ijson-3.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:988e959f2f3d59ebd9c2962ae71b97c0df58323910d0b368cc190ad07429d1bb", size = 84550 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/cc/3d4372e0d0b02a821b982f1fdf10385512dae9b9443c1597719dd37769a9/ijson-3.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b2f73f0d0fce5300f23a1383d19b44d103bb113b57a69c36fd95b7c03099b181", size = 57572 },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/de/970d48b1ff9da5d9513c86fdd2acef5cb3415541c8069e0d92a151b84adb/ijson-3.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0ee57a28c6bf523d7cb0513096e4eb4dac16cd935695049de7608ec110c2b751", size = 56902 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/a0/4537722c8b3b05e82c23dfe09a3a64dd1e44a013a5ca58b1e77dfe48b2f1/ijson-3.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0155a8f079c688c2ccaea05de1ad69877995c547ba3d3612c1c336edc12a3a5", size = 127400 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/96/54956062a99cf49f7a7064b573dcd756da0563ce57910dc34e27a473d9b9/ijson-3.3.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ab00721304af1ae1afa4313ecfa1bf16b07f55ef91e4a5b93aeaa3e2bd7917c", size = 118786 },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/74/795319531c5b5504508f595e631d592957f24bed7ff51a15bc4c61e7b24c/ijson-3.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40ee3821ee90be0f0e95dcf9862d786a7439bd1113e370736bfdf197e9765bfb", size = 126288 },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/6a/e0cec06fbd98851d5d233b59058c1dc2ea767c9bb6feca41aa9164fff769/ijson-3.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da3b6987a0bc3e6d0f721b42c7a0198ef897ae50579547b0345f7f02486898f5", size = 129569 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/4f/82c0d896d8dcb175f99ced7d87705057bcd13523998b48a629b90139a0dc/ijson-3.3.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:63afea5f2d50d931feb20dcc50954e23cef4127606cc0ecf7a27128ed9f9a9e6", size = 121508 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/b6/8973474eba4a917885e289d9e138267d3d1f052c2d93b8c968755661a42d/ijson-3.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b5c3e285e0735fd8c5a26d177eca8b52512cdd8687ca86ec77a0c66e9c510182", size = 127896 },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/25/00e66af887adbbe70002e0479c3c2340bdfa17a168e25d4ab5a27b53582d/ijson-3.3.0-cp312-cp312-win32.whl", hash = "sha256:907f3a8674e489abdcb0206723e5560a5cb1fa42470dcc637942d7b10f28b695", size = 49272 },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/a2/e187beee237808b2c417109ae0f4f7ee7c81ecbe9706305d6ac2a509cc45/ijson-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:8f890d04ad33262d0c77ead53c85f13abfb82f2c8f078dfbf24b78f59534dfdd", size = 51272 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/28/2e1cf00abe5d97aef074e7835b86a94c9a06be4629a0e2c12600792b51ba/ijson-3.3.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2af323a8aec8a50fa9effa6d640691a30a9f8c4925bd5364a1ca97f1ac6b9b5c", size = 54308 },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/d2/8c541c28da4f931bac8177e251efe2b6902f7c486d2d4bdd669eed4ff5c0/ijson-3.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f64f01795119880023ba3ce43072283a393f0b90f52b66cc0ea1a89aa64a9ccb", size = 66010 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/02/8fec0b9037a368811dba7901035e8e0973ebda308f57f30c42101a16a5f7/ijson-3.3.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a716e05547a39b788deaf22725490855337fc36613288aa8ae1601dc8c525553", size = 66770 },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/23/90c61f978c83647112460047ea0137bde9c7fe26600ce255bb3e17ea7a21/ijson-3.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:473f5d921fadc135d1ad698e2697025045cd8ed7e5e842258295012d8a3bc702", size = 64159 },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/af/aab1a36072590af62d848f03981f1c587ca40a391fc61e418e388d8b0d46/ijson-3.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:dd26b396bc3a1e85f4acebeadbf627fa6117b97f4c10b177d5779577c6607744", size = 51095 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imageio"
|
||||
version = "2.36.1"
|
||||
@@ -2255,6 +2359,19 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/83/60/d497a310bde3f01cb805196ac61b7ad6dc5dcf8dce66634dc34364b20b4f/lazy_loader-0.4-py3-none-any.whl", hash = "sha256:342aa8e14d543a154047afb4ba8ef17f5563baad3fc610d7b15b213b0f119efc", size = 12097 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linkup-sdk"
|
||||
version = "0.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "httpx" },
|
||||
{ name = "pydantic" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2e/ba/b06e8f2ca2f0ce255a40ee4505637536acfe83ec997cd8b61bd5cd031513/linkup_sdk-0.2.1.tar.gz", hash = "sha256:b00ba7cb0117358e975d50196501ac49b247509fd236121e40abe40e6a2a3e9a", size = 8918 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/90/2903b9e2eba501ceb6c6b4fc57bbeddde7e8964921a05d424f5a6125cbd0/linkup_sdk-0.2.1-py3-none-any.whl", hash = "sha256:bf50c88e659c6d9291cbd5e3e99b6a20a14c9b1eb2dc7acca763a3ae6f84b26e", size = 7961 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "litellm"
|
||||
version = "1.60.2"
|
||||
@@ -3307,6 +3424,18 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/8a/ce7c28e4ea337f6d95261345d7c61322f8561c52f57b263a3ad7025984f4/orjson-3.10.10-cp312-none-win_amd64.whl", hash = "sha256:384cd13579a1b4cd689d218e329f459eb9ddc504fa48c5a83ef4889db7fd7a4f", size = 139389 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "outcome"
|
||||
version = "1.3.0.post0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "attrs" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/98/df/77698abfac98571e65ffeb0c1fba8ffd692ab8458d617a0eed7d9a8d38f2/outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8", size = 21060 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/55/8b/5ab7257531a5d830fc8000c476e63c935488d74609b50f9384a643ec0a62/outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b", size = 10692 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overrides"
|
||||
version = "7.7.0"
|
||||
@@ -3396,6 +3525,24 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "patronus"
|
||||
version = "0.0.17"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "httpx" },
|
||||
{ name = "pandas" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "pydantic-settings" },
|
||||
{ name = "pyyaml" },
|
||||
{ name = "tqdm" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c5/a0/d5218ff6f2eab18c5a90266d21cdac673c85070e82e3f8aba538b3200f54/patronus-0.0.17.tar.gz", hash = "sha256:7298f770d4f6774b955806fb319c2c872fda3551bd7fa63d975bbeedc14b28de", size = 27377 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/9e/717c4508d675549ff081a7fecf25af7d70f9d7ad87ea0d4825e02de3b801/patronus-0.0.17-py3-none-any.whl", hash = "sha256:1f322eeee838974515fdb7cbf8530ad25c6c59686abbcb28c1fdbf23d34eb10d", size = 31516 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pdfminer-six"
|
||||
version = "20231228"
|
||||
@@ -3956,6 +4103,18 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/35/c0edf199257ef0a7d407d29cd51c4e70d1dad4370a5f44deb65a7a5475e2/pymdown_extensions-10.11.2-py3-none-any.whl", hash = "sha256:41cdde0a77290e480cf53892f5c5e50921a7ee3e5cd60ba91bf19837b33badcf", size = 259044 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyopenssl"
|
||||
version = "24.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cryptography" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c1/d4/1067b82c4fc674d6f6e9e8d26b3dff978da46d351ca3bac171544693e085/pyopenssl-24.3.0.tar.gz", hash = "sha256:49f7a019577d834746bc55c5fce6ecbcec0f2b4ec5ce1cf43a9a173b8138bb36", size = 178944 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/42/22/40f9162e943f86f0fc927ebc648078be87def360d9d8db346619fb97df2b/pyOpenSSL-24.3.0-py3-none-any.whl", hash = "sha256:e474f5a473cd7f92221cc04976e48f4d11502804657a08a989fb3be5514c904a", size = 56111 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pypdf"
|
||||
version = "5.0.1"
|
||||
@@ -4033,6 +4192,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/48/0a/c99fb7d7e176f8b176ef19704a32e6a9c6aafdf19ef75a187f701fc15801/pysbd-0.3.4-py3-none-any.whl", hash = "sha256:cd838939b7b0b185fcf86b0baf6636667dfb6e474743beeff878e9f42e022953", size = 71082 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pysocks"
|
||||
version = "1.7.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/bd/11/293dd436aea955d45fc4e8a35b6ae7270f5b8e00b53cf6c024c83b657a11/PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0", size = 284429 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/59/b4572118e098ac8e46e399a1dd0f2d85403ce8bbaad9ec79373ed6badaf9/PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", size = 16725 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "8.3.3"
|
||||
@@ -4692,6 +4860,39 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/7d/43ab67228ef98c6b5dd42ab386eae2d7877036970a0d7e3dd3eb47a0d530/scipy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2ff38e22128e6c03ff73b6bb0f85f897d2362f8c052e3b8ad00532198fbdae3f", size = 44521212 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scrapegraph-py"
|
||||
version = "1.8.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "aiohttp" },
|
||||
{ name = "beautifulsoup4" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "python-dotenv" },
|
||||
{ name = "requests" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/33/90/2388754061394a6c95fd5ad48cf4550208ce081c99cbc883672d52ccc360/scrapegraph_py-1.8.0.tar.gz", hash = "sha256:e075f6e6012a14a038537d0664609229069d9d2c2956bcbf9362f0c5c48de786", size = 108112 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/80/14aeb7ba092cfc6928844a6726855f0c33489107f344e71dd8071f6433ed/scrapegraph_py-1.8.0-py3-none-any.whl", hash = "sha256:279176c972a770bac37a284e0bc25e34793797f30ff24dfba8fbcbfda79c8c88", size = 14460 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "selenium"
|
||||
version = "4.25.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
{ name = "trio" },
|
||||
{ name = "trio-websocket" },
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "urllib3", extra = ["socks"] },
|
||||
{ name = "websocket-client" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/0e/5a/d3735b189b91715fd0f5a9b8d55e2605061309849470e96ab830f02cba40/selenium-4.25.0.tar.gz", hash = "sha256:95d08d3b82fb353f3c474895154516604c7f0e6a9a565ae6498ef36c9bac6921", size = 957765 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/85/fa44f23dd5d5066a72f7c4304cce4b5ff9a6e7fd92431a48b2c63fbf63ec/selenium-4.25.0-py3-none-any.whl", hash = "sha256:3798d2d12b4a570bc5790163ba57fef10b2afee958bf1d80f2a3cf07c4141f33", size = 9693127 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semchunk"
|
||||
version = "2.2.0"
|
||||
@@ -4705,6 +4906,18 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/85/3940bb4c586e10603d169d13ffccd59ed32fcb8d1b8104c3aef0e525b3b2/semchunk-2.2.0-py3-none-any.whl", hash = "sha256:7db19ca90ddb48f99265e789e07a7bb111ae25185f9cc3d44b94e1e61b9067fc", size = 10243 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serpapi"
|
||||
version = "0.1.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "requests" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f0/fa/3fd8809287f3977a3e752bb88610e918d49cb1038b14f4bc51e13e594197/serpapi-0.1.5.tar.gz", hash = "sha256:b9707ed54750fdd2f62dc3a17c6a3fb7fa421dc37902fd65b2263c0ac765a1a5", size = 14191 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/df/6a/21deade04100d64844e494353a5d65e7971fbdfddf78eb1f248423593ad0/serpapi-0.1.5-py2.py3-none-any.whl", hash = "sha256:6467b6adec1231059f754ccaa952b229efeaa8b9cae6e71f879703ec9e5bb3d1", size = 10966 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "75.2.0"
|
||||
@@ -4770,6 +4983,96 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snowflake"
|
||||
version = "1.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "snowflake-core" },
|
||||
{ name = "snowflake-legacy" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/80/d1/830929fb7b54586f4ee601f409e80343e16f32b9b579246cd6fa9984bcff/snowflake-1.0.2.tar.gz", hash = "sha256:4009e59af24e444de4a9e9d340fff0979cca8a02a4feee4665da97eb9c76d958", size = 6033 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b6/25/4cbba4da3f9b333d132680a66221d1a101309cce330fa8be38b674ceafd0/snowflake-1.0.2-py3-none-any.whl", hash = "sha256:6bb0fc70aa10234769202861ccb4b091f5e9fb1bbc61a1e708db93baa3f221f4", size = 5623 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snowflake-connector-python"
|
||||
version = "3.12.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "asn1crypto" },
|
||||
{ name = "certifi" },
|
||||
{ name = "cffi" },
|
||||
{ name = "charset-normalizer" },
|
||||
{ name = "cryptography" },
|
||||
{ name = "filelock" },
|
||||
{ name = "idna" },
|
||||
{ name = "packaging" },
|
||||
{ name = "platformdirs" },
|
||||
{ name = "pyjwt" },
|
||||
{ name = "pyopenssl" },
|
||||
{ name = "pytz" },
|
||||
{ name = "requests" },
|
||||
{ name = "sortedcontainers" },
|
||||
{ name = "tomlkit" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6b/de/f43d9c827ccc1974696ffd3c0495e2d4e98b0414b2353b7de932621f23dd/snowflake_connector_python-3.12.4.tar.gz", hash = "sha256:289e0691dfbf8ec8b7a8f58bcbb95a819890fe5e5b278fdbfc885059a63a946f", size = 743445 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/53/6c/edc8909e424654a7a3c18cbf804d8a35c17a65a2131f866a87ed8e762bd0/snowflake_connector_python-3.12.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f141c159e3244bd660279f87f32e39351b2845fcb75f8138f31d2219f983b05", size = 958038 },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/a3/34c5082dfb9b555c914f4233224b8bc1f2c4d5668bc71bb587680b8dcd73/snowflake_connector_python-3.12.4-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:091458ba777c24adff659c5c28f0f5bb0bcca8a9b6ecc5641ae25b7c20a8f43d", size = 970665 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/87/9eceaaba58b2ec4f9094fc3a04d953bbabbfdcc05a6b14ef12610c1039f9/snowflake_connector_python-3.12.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23049d341da681ec7131cead71cdf7b1761ae5bcc08bcbdb931dcef6c25e8a5f", size = 2496731 },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/0a/e35e9e0a142f3779007b0246166a245305858b198ed0dd3a41a3d2405512/snowflake_connector_python-3.12.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc88a09d77a8ce7e445094b2409b606ddb208b5fc9f7c7a379d0255a8d566e9d", size = 2520041 },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/77/9a238c153600adff8fbd1136d9f4be1e42cb827cbe1865924bfe84653e85/snowflake_connector_python-3.12.4-cp310-cp310-win_amd64.whl", hash = "sha256:3c33fbba036805c1767ea48eb40ffc3fb79d61f2a4bb4e77b571ea6f6a998be8", size = 918272 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/95/e8aac28d6913e4b59f96e6d361f31b9576b5f0abe4d2c4f7decf9f075932/snowflake_connector_python-3.12.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ec5cfaa1526084cf4d0e7849d5ace601245cb4ad9675ab3cd7d799b3abea481", size = 958125 },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/b6/a847a94e03bdf39010048feacd57f250a91a655eed333d7d32b165f65201/snowflake_connector_python-3.12.4-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:ff225824b3a0fa5e822442de72172f97028f04ae183877f1305d538d8d6c5d11", size = 970770 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/91/f97812ae9946944bcd9bfe1965af1cb9b1844919da879d90b90dfd3e5086/snowflake_connector_python-3.12.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9beced2789dc75e8f1e749aa637e7ec9b03302b4ed4b793ae0f1ff32823370e", size = 2519875 },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/52/500d72079bfb322ebdf3892180ecf3dc73c117b3a966ee8d4bb1378882b2/snowflake_connector_python-3.12.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ea47450a04ff713f3adf28053e34103bd990291e62daee9721c76597af4b2b5", size = 2542320 },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/92/74ead6bee8dd29fe372002ce59477221e04b9da96ad7aafe584afce02937/snowflake_connector_python-3.12.4-cp311-cp311-win_amd64.whl", hash = "sha256:748f9125854dca07ea471bb2bb3c5bb932a53f9b8a77ba348b50b738c77203ce", size = 918363 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/a3/1cbe0b52b810f069bdc96c372b2d91ac51aeac32986c2832aa3fe0b0b0e5/snowflake_connector_python-3.12.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4bcd0371b20d199f15e6a3c0b489bf18e27f2a88c84cf3194b2569ca039fa7d1", size = 957561 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/05/8a5e16bd908a89f36d59686d356890c4bd6a976a487f86274181010f4b49/snowflake_connector_python-3.12.4-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:7900d82a450b206fa2ed6c42cd65d9b3b9fd4547eca1696937175fac2a03ba37", size = 969045 },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/1b/8f5ab15d224d7bf76533c55cfd8ce73b185ce94d84241f0e900739ce3f37/snowflake_connector_python-3.12.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:300f0562aeea55e40ee03b45205dbef7b78f5ba2f1787a278c7b807e7d8db22c", size = 2533969 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/d9/2e2fd72e0251691b5c54a219256c455141a2d3c104e411b82de598c62553/snowflake_connector_python-3.12.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6762a00948f003be55d7dc5de9de690315d01951a94371ec3db069d9303daba", size = 2558052 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/cb/e0ab230ad5adc9932e595bdbec693b2499d446666daf6cb9cae306a41dd2/snowflake_connector_python-3.12.4-cp312-cp312-win_amd64.whl", hash = "sha256:83ca896790a7463b6c8cd42e1a29b8ea197cc920839ae6ee96a467475eab4ec2", size = 916627 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snowflake-core"
|
||||
version = "1.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "atpublic" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "python-dateutil" },
|
||||
{ name = "pyyaml" },
|
||||
{ name = "requests" },
|
||||
{ name = "snowflake-connector-python" },
|
||||
{ name = "urllib3" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1d/cf/6f91e5b2daaf3df9ae666a65f5ba3938f11a40784e4ada5218ecf154b29a/snowflake_core-1.0.2.tar.gz", hash = "sha256:8bf267ff1efcd17f157432c6e24f6d2eb6c2aeed66f43ab34b215aa76d8edf02", size = 1092618 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/75/3c/ec228b7325b32781081c72254dd0ef793943e853d82616e862e231909c6c/snowflake_core-1.0.2-py3-none-any.whl", hash = "sha256:55c37cf526a0d78dd3359ad96b9ecd7130bbbbc2f5a2fec77bb3da0dac2dc688", size = 1555690 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snowflake-legacy"
|
||||
version = "1.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/94/41/a6211bd2109913eee1506d37865ab13cf9a8cc2faa41833da3d1ffec654b/snowflake_legacy-1.0.0.tar.gz", hash = "sha256:2044661c79ba01841ab279c5e74b994532244c9d103224eba16eb159c8ed6033", size = 4043 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/8c/64f9b5ee0c3f376a733584c480b31addbf2baff7bb41f655e5e3f3719d3b/snowflake_legacy-1.0.0-py3-none-any.whl", hash = "sha256:25f9678f180d7d5f5b60d17f8112f0ee8a7a77b82c67fd599ed6e27bd502be5a", size = 3059 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sortedcontainers"
|
||||
version = "2.4.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "soupsieve"
|
||||
version = "2.6"
|
||||
@@ -4779,6 +5082,18 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9", size = 36186 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spider-client"
|
||||
version = "0.1.25"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "aiohttp" },
|
||||
{ name = "ijson" },
|
||||
{ name = "requests" },
|
||||
{ name = "tenacity" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b8/f2/06d89322f0054ea72e8d5580199f580e29df23476cb3cfe83a70a2a58a1b/spider-client-0.1.25.tar.gz", hash = "sha256:92ca4ce1d9d715dd8db52684ea417653940d8f3bbc13383d78683bc4fbb899a2", size = 15412 }
|
||||
|
||||
[[package]]
|
||||
name = "sqlalchemy"
|
||||
version = "2.0.36"
|
||||
@@ -5010,6 +5325,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/ac/ce90573ba446a9bbe65838ded066a805234d159b4446ae9f8ec5bbd36cbd/tomli_w-1.1.0-py3-none-any.whl", hash = "sha256:1403179c78193e3184bfaade390ddbd071cba48a32a2e62ba11aae47490c63f7", size = 6440 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tomlkit"
|
||||
version = "0.13.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b1/09/a439bec5888f00a54b8b9f05fa94d7f901d6735ef4e55dcec9bc37b5d8fa/tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79", size = 192885 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/b6/a447b5e4ec71e13871be01ba81f5dfc9d0af7e473da256ff46bc0e24026f/tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde", size = 37955 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "torch"
|
||||
version = "2.4.1"
|
||||
@@ -5115,6 +5439,38 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/51/51/b87caa939fedf307496e4dbf412f4b909af3d9ca8b189fc3b65c1faa456f/transformers-4.46.3-py3-none-any.whl", hash = "sha256:a12ef6f52841fd190a3e5602145b542d03507222f2c64ebb7ee92e8788093aef", size = 10034536 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trio"
|
||||
version = "0.27.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "attrs" },
|
||||
{ name = "cffi", marker = "implementation_name != 'pypy' and os_name == 'nt'" },
|
||||
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
||||
{ name = "idna" },
|
||||
{ name = "outcome" },
|
||||
{ name = "sniffio" },
|
||||
{ name = "sortedcontainers" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/17/d1/a83dee5be404da7afe5a71783a33b8907bacb935a6dc8c69ab785e4a3eed/trio-0.27.0.tar.gz", hash = "sha256:1dcc95ab1726b2da054afea8fd761af74bad79bd52381b84eae408e983c76831", size = 568064 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/83/ec3196c360afffbc5b342ead48d1eb7393dd74fa70bca75d33905a86f211/trio-0.27.0-py3-none-any.whl", hash = "sha256:68eabbcf8f457d925df62da780eff15ff5dc68fd6b367e2dde59f7aaf2a0b884", size = 481734 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trio-websocket"
|
||||
version = "0.11.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
||||
{ name = "trio" },
|
||||
{ name = "wsproto" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/dd/36/abad2385853077424a11b818d9fd8350d249d9e31d583cb9c11cd4c85eda/trio-websocket-0.11.1.tar.gz", hash = "sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f", size = 26511 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/48/be/a9ae5f50cad5b6f85bd2574c2c923730098530096e170c1ce7452394d7aa/trio_websocket-0.11.1-py3-none-any.whl", hash = "sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638", size = 17408 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "triton"
|
||||
version = "3.0.0"
|
||||
@@ -5195,6 +5551,11 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
socks = [
|
||||
{ name = "pysocks" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uv"
|
||||
version = "0.4.26"
|
||||
@@ -5271,6 +5632,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/eb/f7032be105877bcf924709c97b1bf3b90255b4ec251f9340cef912559f28/uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f", size = 4659022 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "validators"
|
||||
version = "0.34.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/64/07/91582d69320f6f6daaf2d8072608a4ad8884683d4840e7e4f3a9dbdcc639/validators-0.34.0.tar.gz", hash = "sha256:647fe407b45af9a74d245b943b18e6a816acf4926974278f6dd617778e1e781f", size = 70955 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/78/36828a4d857b25896f9774c875714ba4e9b3bc8a92d2debe3f4df3a83d4f/validators-0.34.0-py3-none-any.whl", hash = "sha256:c804b476e3e6d3786fa07a30073a4ef694e617805eb1946ceee3fe5a9b8b1321", size = 43536 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vcrpy"
|
||||
version = "5.1.0"
|
||||
@@ -5390,6 +5760,25 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "weaviate-client"
|
||||
version = "4.9.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "authlib" },
|
||||
{ name = "grpcio" },
|
||||
{ name = "grpcio-health-checking" },
|
||||
{ name = "grpcio-tools" },
|
||||
{ name = "httpx" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "requests" },
|
||||
{ name = "validators" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5d/7d/3894d12065d006743271b0b6bcc3bf911910473e91179d5966966816d694/weaviate_client-4.9.6.tar.gz", hash = "sha256:56d67c40fc94b0d53e81e0aa4477baaebbf3646fbec26551df66e396a72adcb6", size = 696813 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2f/40/e3550e743b92ddd8dc69ebfd69cceb6de45b7d9a1cd439995454b499e9a3/weaviate_client-4.9.6-py3-none-any.whl", hash = "sha256:1d3b551939c0f7314f25e417cbcf4cf34e7adf942627993eef36ae6b4a044673", size = 386998 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webencodings"
|
||||
version = "0.5.1"
|
||||
@@ -5504,6 +5893,18 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/21/abdedb4cdf6ff41ebf01a74087740a709e2edb146490e4d9beea054b0b7a/wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1", size = 23362 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wsproto"
|
||||
version = "1.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "h11" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c9/4a/44d3c295350d776427904d73c189e10aeae66d7f555bb2feee16d1e4ba5a/wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", size = 53425 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736", size = 24226 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xlsxwriter"
|
||||
version = "3.2.0"
|
||||
|
||||
Reference in New Issue
Block a user