mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-04-13 14:32:47 +00:00
Compare commits
1 Commits
feat/ibm-m
...
sec_docs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f1b26bde2 |
@@ -25,55 +25,52 @@ By default, CrewAI uses the `gpt-4o-mini` model. It uses environment variables i
|
|||||||
- `OPENAI_API_BASE`
|
- `OPENAI_API_BASE`
|
||||||
- `OPENAI_API_KEY`
|
- `OPENAI_API_KEY`
|
||||||
|
|
||||||
### 2. Custom LLM Objects
|
### 2. String Identifier
|
||||||
|
|
||||||
|
```python Code
|
||||||
|
agent = Agent(llm="gpt-4o", ...)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. LLM Instance
|
||||||
|
|
||||||
|
List of [more providers](https://docs.litellm.ai/docs/providers).
|
||||||
|
|
||||||
|
```python Code
|
||||||
|
from crewai import LLM
|
||||||
|
|
||||||
|
llm = LLM(model="gpt-4", temperature=0.7)
|
||||||
|
agent = Agent(llm=llm, ...)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Custom LLM Objects
|
||||||
|
|
||||||
Pass a custom LLM implementation or object from another library.
|
Pass a custom LLM implementation or object from another library.
|
||||||
|
|
||||||
See below for examples.
|
|
||||||
|
|
||||||
<Tabs>
|
|
||||||
<Tab title="String Identifier">
|
|
||||||
```python Code
|
|
||||||
agent = Agent(llm="gpt-4o", ...)
|
|
||||||
```
|
|
||||||
</Tab>
|
|
||||||
|
|
||||||
<Tab title="LLM Instance">
|
|
||||||
```python Code
|
|
||||||
from crewai import LLM
|
|
||||||
|
|
||||||
llm = LLM(model="gpt-4", temperature=0.7)
|
|
||||||
agent = Agent(llm=llm, ...)
|
|
||||||
```
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
|
||||||
|
|
||||||
## Connecting to OpenAI-Compatible LLMs
|
## Connecting to OpenAI-Compatible LLMs
|
||||||
|
|
||||||
You can connect to OpenAI-compatible LLMs using either environment variables or by setting specific attributes on the LLM class:
|
You can connect to OpenAI-compatible LLMs using either environment variables or by setting specific attributes on the LLM class:
|
||||||
|
|
||||||
<Tabs>
|
1. Using environment variables:
|
||||||
<Tab title="Using Environment Variables">
|
|
||||||
```python Code
|
|
||||||
import os
|
|
||||||
|
|
||||||
os.environ["OPENAI_API_KEY"] = "your-api-key"
|
```python Code
|
||||||
os.environ["OPENAI_API_BASE"] = "https://api.your-provider.com/v1"
|
import os
|
||||||
```
|
|
||||||
</Tab>
|
|
||||||
<Tab title="Using LLM Class Attributes">
|
|
||||||
```python Code
|
|
||||||
from crewai import LLM
|
|
||||||
|
|
||||||
llm = LLM(
|
os.environ["OPENAI_API_KEY"] = "your-api-key"
|
||||||
model="custom-model-name",
|
os.environ["OPENAI_API_BASE"] = "https://api.your-provider.com/v1"
|
||||||
api_key="your-api-key",
|
```
|
||||||
base_url="https://api.your-provider.com/v1"
|
|
||||||
)
|
2. Using LLM class attributes:
|
||||||
agent = Agent(llm=llm, ...)
|
|
||||||
```
|
```python Code
|
||||||
</Tab>
|
from crewai import LLM
|
||||||
</Tabs>
|
|
||||||
|
llm = LLM(
|
||||||
|
model="custom-model-name",
|
||||||
|
api_key="your-api-key",
|
||||||
|
base_url="https://api.your-provider.com/v1"
|
||||||
|
)
|
||||||
|
agent = Agent(llm=llm, ...)
|
||||||
|
```
|
||||||
|
|
||||||
## LLM Configuration Options
|
## LLM Configuration Options
|
||||||
|
|
||||||
@@ -100,149 +97,55 @@ When configuring an LLM for your agent, you have access to a wide range of param
|
|||||||
| **api_key** | `str` | Your API key for authentication. |
|
| **api_key** | `str` | Your API key for authentication. |
|
||||||
|
|
||||||
|
|
||||||
These are examples of how to configure LLMs for your agent.
|
## OpenAI Example Configuration
|
||||||
|
|
||||||
<AccordionGroup>
|
```python Code
|
||||||
<Accordion title="OpenAI">
|
from crewai import LLM
|
||||||
|
|
||||||
```python Code
|
llm = LLM(
|
||||||
from crewai import LLM
|
model="gpt-4",
|
||||||
|
temperature=0.8,
|
||||||
|
max_tokens=150,
|
||||||
|
top_p=0.9,
|
||||||
|
frequency_penalty=0.1,
|
||||||
|
presence_penalty=0.1,
|
||||||
|
stop=["END"],
|
||||||
|
seed=42,
|
||||||
|
base_url="https://api.openai.com/v1",
|
||||||
|
api_key="your-api-key-here"
|
||||||
|
)
|
||||||
|
agent = Agent(llm=llm, ...)
|
||||||
|
```
|
||||||
|
|
||||||
llm = LLM(
|
## Cerebras Example Configuration
|
||||||
model="gpt-4",
|
|
||||||
temperature=0.8,
|
|
||||||
max_tokens=150,
|
|
||||||
top_p=0.9,
|
|
||||||
frequency_penalty=0.1,
|
|
||||||
presence_penalty=0.1,
|
|
||||||
stop=["END"],
|
|
||||||
seed=42,
|
|
||||||
base_url="https://api.openai.com/v1",
|
|
||||||
api_key="your-api-key-here"
|
|
||||||
)
|
|
||||||
agent = Agent(llm=llm, ...)
|
|
||||||
```
|
|
||||||
</Accordion>
|
|
||||||
|
|
||||||
<Accordion title="Cerebras">
|
```python Code
|
||||||
|
from crewai import LLM
|
||||||
|
|
||||||
```python Code
|
llm = LLM(
|
||||||
from crewai import LLM
|
model="cerebras/llama-3.1-70b",
|
||||||
|
base_url="https://api.cerebras.ai/v1",
|
||||||
|
api_key="your-api-key-here"
|
||||||
|
)
|
||||||
|
agent = Agent(llm=llm, ...)
|
||||||
|
```
|
||||||
|
|
||||||
llm = LLM(
|
## Using Ollama (Local LLMs)
|
||||||
model="cerebras/llama-3.1-70b",
|
|
||||||
base_url="https://api.cerebras.ai/v1",
|
|
||||||
api_key="your-api-key-here"
|
|
||||||
)
|
|
||||||
agent = Agent(llm=llm, ...)
|
|
||||||
```
|
|
||||||
</Accordion>
|
|
||||||
|
|
||||||
<Accordion title="Ollama (Local LLMs)">
|
|
||||||
|
|
||||||
CrewAI supports using Ollama for running open-source models locally:
|
CrewAI supports using Ollama for running open-source models locally:
|
||||||
|
|
||||||
1. Install Ollama: [ollama.ai](https://ollama.ai/)
|
1. Install Ollama: [ollama.ai](https://ollama.ai/)
|
||||||
2. Run a model: `ollama run llama2`
|
2. Run a model: `ollama run llama2`
|
||||||
3. Configure agent:
|
3. Configure agent:
|
||||||
|
|
||||||
```python Code
|
```python Code
|
||||||
from crewai import LLM
|
from crewai import LLM
|
||||||
|
|
||||||
agent = Agent(
|
agent = Agent(
|
||||||
llm=LLM(
|
llm=LLM(model="ollama/llama3.1", base_url="http://localhost:11434"),
|
||||||
model="ollama/llama3.1",
|
...
|
||||||
base_url="http://localhost:11434"
|
)
|
||||||
),
|
```
|
||||||
...
|
|
||||||
)
|
|
||||||
```
|
|
||||||
</Accordion>
|
|
||||||
|
|
||||||
<Accordion title="Groq">
|
|
||||||
|
|
||||||
```python Code
|
|
||||||
from crewai import LLM
|
|
||||||
|
|
||||||
llm = LLM(
|
|
||||||
model="groq/llama3-8b-8192",
|
|
||||||
base_url="https://api.groq.com/openai/v1",
|
|
||||||
api_key="your-api-key-here"
|
|
||||||
)
|
|
||||||
agent = Agent(llm=llm, ...)
|
|
||||||
```
|
|
||||||
</Accordion>
|
|
||||||
|
|
||||||
<Accordion title="Anthropic">
|
|
||||||
|
|
||||||
```python Code
|
|
||||||
from crewai import LLM
|
|
||||||
|
|
||||||
llm = LLM(
|
|
||||||
model="anthropic/claude-3-5-sonnet-20241022",
|
|
||||||
base_url="https://api.anthropic.com/v1",
|
|
||||||
api_key="your-api-key-here"
|
|
||||||
)
|
|
||||||
agent = Agent(llm=llm, ...)
|
|
||||||
```
|
|
||||||
</Accordion>
|
|
||||||
|
|
||||||
<Accordion title="Fireworks">
|
|
||||||
|
|
||||||
```python Code
|
|
||||||
from crewai import LLM
|
|
||||||
|
|
||||||
llm = LLM(
|
|
||||||
model="fireworks/meta-llama-3.1-8b-instruct",
|
|
||||||
base_url="https://api.fireworks.ai/inference/v1",
|
|
||||||
api_key="your-api-key-here"
|
|
||||||
)
|
|
||||||
agent = Agent(llm=llm, ...)
|
|
||||||
```
|
|
||||||
</Accordion>
|
|
||||||
|
|
||||||
<Accordion title="Gemini">
|
|
||||||
|
|
||||||
```python Code
|
|
||||||
from crewai import LLM
|
|
||||||
|
|
||||||
llm = LLM(
|
|
||||||
model="gemini/gemini-1.5-flash",
|
|
||||||
base_url="https://api.gemini.google.com/v1",
|
|
||||||
api_key="your-api-key-here"
|
|
||||||
)
|
|
||||||
agent = Agent(llm=llm, ...)
|
|
||||||
```
|
|
||||||
</Accordion>
|
|
||||||
|
|
||||||
<Accordion title="Perplexity AI (pplx-api)">
|
|
||||||
|
|
||||||
```python Code
|
|
||||||
from crewai import LLM
|
|
||||||
|
|
||||||
llm = LLM(
|
|
||||||
model="perplexity/mistral-7b-instruct",
|
|
||||||
base_url="https://api.perplexity.ai/v1",
|
|
||||||
api_key="your-api-key-here"
|
|
||||||
)
|
|
||||||
agent = Agent(llm=llm, ...)
|
|
||||||
```
|
|
||||||
</Accordion>
|
|
||||||
|
|
||||||
<Accordion title="IBM watsonx.ai">
|
|
||||||
|
|
||||||
```python Code
|
|
||||||
from crewai import LLM
|
|
||||||
|
|
||||||
llm = LLM(
|
|
||||||
model="watsonx/ibm/granite-13b-chat-v2",
|
|
||||||
base_url="https://api.watsonx.ai/v1",
|
|
||||||
api_key="your-api-key-here"
|
|
||||||
)
|
|
||||||
agent = Agent(llm=llm, ...)
|
|
||||||
```
|
|
||||||
</Accordion>
|
|
||||||
</AccordionGroup>
|
|
||||||
|
|
||||||
## Changing the Base API URL
|
## Changing the Base API URL
|
||||||
|
|
||||||
|
|||||||
@@ -254,31 +254,6 @@ my_crew = Crew(
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using Watson embeddings
|
|
||||||
|
|
||||||
```python Code
|
|
||||||
from crewai import Crew, Agent, Task, Process
|
|
||||||
|
|
||||||
# Note: Ensure you have installed and imported `ibm_watsonx_ai` for Watson embeddings to work.
|
|
||||||
|
|
||||||
my_crew = Crew(
|
|
||||||
agents=[...],
|
|
||||||
tasks=[...],
|
|
||||||
process=Process.sequential,
|
|
||||||
memory=True,
|
|
||||||
verbose=True,
|
|
||||||
embedder={
|
|
||||||
"provider": "watson",
|
|
||||||
"config": {
|
|
||||||
"model": "<model_name>",
|
|
||||||
"api_url": "<api_url>",
|
|
||||||
"api_key": "<YOUR_API_KEY>",
|
|
||||||
"project_id": "<YOUR_PROJECT_ID>",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Resetting Memory
|
### Resetting Memory
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
import json
|
|
||||||
from pathlib import Path
|
|
||||||
from pydantic import BaseModel, Field
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
DEFAULT_CONFIG_PATH = Path.home() / ".config" / "crewai" / "settings.json"
|
|
||||||
|
|
||||||
class Settings(BaseModel):
|
|
||||||
tool_repository_username: Optional[str] = Field(None, description="Username for interacting with the Tool Repository")
|
|
||||||
tool_repository_password: Optional[str] = Field(None, description="Password for interacting with the Tool Repository")
|
|
||||||
config_path: Path = Field(default=DEFAULT_CONFIG_PATH, exclude=True)
|
|
||||||
|
|
||||||
def __init__(self, config_path: Path = DEFAULT_CONFIG_PATH, **data):
|
|
||||||
"""Load Settings from config path"""
|
|
||||||
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
file_data = {}
|
|
||||||
if config_path.is_file():
|
|
||||||
try:
|
|
||||||
with config_path.open("r") as f:
|
|
||||||
file_data = json.load(f)
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
file_data = {}
|
|
||||||
|
|
||||||
merged_data = {**file_data, **data}
|
|
||||||
super().__init__(config_path=config_path, **merged_data)
|
|
||||||
|
|
||||||
def dump(self) -> None:
|
|
||||||
"""Save current settings to settings.json"""
|
|
||||||
if self.config_path.is_file():
|
|
||||||
with self.config_path.open("r") as f:
|
|
||||||
existing_data = json.load(f)
|
|
||||||
else:
|
|
||||||
existing_data = {}
|
|
||||||
|
|
||||||
updated_data = {**existing_data, **self.model_dump(exclude_unset=True)}
|
|
||||||
with self.config_path.open("w") as f:
|
|
||||||
json.dump(updated_data, f, indent=4)
|
|
||||||
@@ -1,15 +1,17 @@
|
|||||||
import base64
|
import base64
|
||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from netrc import netrc
|
||||||
|
import stat
|
||||||
|
|
||||||
import click
|
import click
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
|
||||||
from crewai.cli import git
|
from crewai.cli import git
|
||||||
from crewai.cli.command import BaseCommand, PlusAPIMixin
|
from crewai.cli.command import BaseCommand, PlusAPIMixin
|
||||||
from crewai.cli.config import Settings
|
|
||||||
from crewai.cli.utils import (
|
from crewai.cli.utils import (
|
||||||
get_project_description,
|
get_project_description,
|
||||||
get_project_name,
|
get_project_name,
|
||||||
@@ -151,16 +153,26 @@ class ToolCommand(BaseCommand, PlusAPIMixin):
|
|||||||
raise SystemExit
|
raise SystemExit
|
||||||
|
|
||||||
login_response_json = login_response.json()
|
login_response_json = login_response.json()
|
||||||
|
self._set_netrc_credentials(login_response_json["credential"])
|
||||||
settings = Settings()
|
|
||||||
settings.tool_repository_username = login_response_json["credential"]["username"]
|
|
||||||
settings.tool_repository_password = login_response_json["credential"]["password"]
|
|
||||||
settings.dump()
|
|
||||||
|
|
||||||
console.print(
|
console.print(
|
||||||
"Successfully authenticated to the tool repository.", style="bold green"
|
"Successfully authenticated to the tool repository.", style="bold green"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _set_netrc_credentials(self, credentials, netrc_path=None):
|
||||||
|
if not netrc_path:
|
||||||
|
netrc_filename = "_netrc" if platform.system() == "Windows" else ".netrc"
|
||||||
|
netrc_path = Path.home() / netrc_filename
|
||||||
|
netrc_path.touch(mode=stat.S_IRUSR | stat.S_IWUSR, exist_ok=True)
|
||||||
|
|
||||||
|
netrc_instance = netrc(file=netrc_path)
|
||||||
|
netrc_instance.hosts["app.crewai.com"] = (credentials["username"], "", credentials["password"])
|
||||||
|
|
||||||
|
with open(netrc_path, 'w') as file:
|
||||||
|
file.write(str(netrc_instance))
|
||||||
|
|
||||||
|
console.print(f"Added credentials to {netrc_path}", style="bold green")
|
||||||
|
|
||||||
def _add_package(self, tool_details):
|
def _add_package(self, tool_details):
|
||||||
tool_handle = tool_details["handle"]
|
tool_handle = tool_details["handle"]
|
||||||
repository_handle = tool_details["repository"]["handle"]
|
repository_handle = tool_details["repository"]["handle"]
|
||||||
@@ -175,11 +187,7 @@ class ToolCommand(BaseCommand, PlusAPIMixin):
|
|||||||
tool_handle,
|
tool_handle,
|
||||||
]
|
]
|
||||||
add_package_result = subprocess.run(
|
add_package_result = subprocess.run(
|
||||||
add_package_command,
|
add_package_command, capture_output=False, text=True, check=True
|
||||||
capture_output=False,
|
|
||||||
env=self._build_env_with_credentials(repository_handle),
|
|
||||||
text=True,
|
|
||||||
check=True
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if add_package_result.stderr:
|
if add_package_result.stderr:
|
||||||
@@ -198,13 +206,3 @@ class ToolCommand(BaseCommand, PlusAPIMixin):
|
|||||||
"[bold yellow]Tip:[/bold yellow] Navigate to a different directory and try again."
|
"[bold yellow]Tip:[/bold yellow] Navigate to a different directory and try again."
|
||||||
)
|
)
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
|
|
||||||
def _build_env_with_credentials(self, repository_handle: str):
|
|
||||||
repository_handle = repository_handle.upper().replace("-", "_")
|
|
||||||
settings = Settings()
|
|
||||||
|
|
||||||
env = os.environ.copy()
|
|
||||||
env[f"UV_INDEX_{repository_handle}_USERNAME"] = str(settings.tool_repository_username or "")
|
|
||||||
env[f"UV_INDEX_{repository_handle}_PASSWORD"] = str(settings.tool_repository_password or "")
|
|
||||||
|
|
||||||
return env
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ class ContextualMemory:
|
|||||||
formatted_results = "\n".join(
|
formatted_results = "\n".join(
|
||||||
[f"- {result['context']}" for result in stm_results]
|
[f"- {result['context']}" for result in stm_results]
|
||||||
)
|
)
|
||||||
print("formatted_results stm", formatted_results)
|
|
||||||
return f"Recent Insights:\n{formatted_results}" if stm_results else ""
|
return f"Recent Insights:\n{formatted_results}" if stm_results else ""
|
||||||
|
|
||||||
def _fetch_ltm_context(self, task) -> Optional[str]:
|
def _fetch_ltm_context(self, task) -> Optional[str]:
|
||||||
@@ -54,8 +53,6 @@ class ContextualMemory:
|
|||||||
formatted_results = list(dict.fromkeys(formatted_results))
|
formatted_results = list(dict.fromkeys(formatted_results))
|
||||||
formatted_results = "\n".join([f"- {result}" for result in formatted_results]) # type: ignore # Incompatible types in assignment (expression has type "str", variable has type "list[str]")
|
formatted_results = "\n".join([f"- {result}" for result in formatted_results]) # type: ignore # Incompatible types in assignment (expression has type "str", variable has type "list[str]")
|
||||||
|
|
||||||
print("formatted_results ltm", formatted_results)
|
|
||||||
|
|
||||||
return f"Historical Data:\n{formatted_results}" if ltm_results else ""
|
return f"Historical Data:\n{formatted_results}" if ltm_results else ""
|
||||||
|
|
||||||
def _fetch_entity_context(self, query) -> str:
|
def _fetch_entity_context(self, query) -> str:
|
||||||
@@ -67,5 +64,4 @@ class ContextualMemory:
|
|||||||
formatted_results = "\n".join(
|
formatted_results = "\n".join(
|
||||||
[f"- {result['context']}" for result in em_results] # type: ignore # Invalid index type "str" for "str"; expected type "SupportsIndex | slice"
|
[f"- {result['context']}" for result in em_results] # type: ignore # Invalid index type "str" for "str"; expected type "SupportsIndex | slice"
|
||||||
)
|
)
|
||||||
print("formatted_results em", formatted_results)
|
|
||||||
return f"Entities:\n{formatted_results}" if em_results else ""
|
return f"Entities:\n{formatted_results}" if em_results else ""
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class KickoffTaskOutputsSQLiteStorage:
|
|||||||
task.expected_output,
|
task.expected_output,
|
||||||
json.dumps(output, cls=CrewJSONEncoder),
|
json.dumps(output, cls=CrewJSONEncoder),
|
||||||
task_index,
|
task_index,
|
||||||
json.dumps(inputs, cls=CrewJSONEncoder),
|
json.dumps(inputs),
|
||||||
was_replayed,
|
was_replayed,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import uuid
|
import uuid
|
||||||
from typing import Any, Dict, List, Optional, cast
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
from chromadb import Documents, EmbeddingFunction, Embeddings
|
|
||||||
from chromadb.api import ClientAPI
|
|
||||||
from chromadb.api.types import validate_embedding_function
|
|
||||||
from crewai.memory.storage.base_rag_storage import BaseRAGStorage
|
from crewai.memory.storage.base_rag_storage import BaseRAGStorage
|
||||||
from crewai.utilities.paths import db_storage_path
|
from crewai.utilities.paths import db_storage_path
|
||||||
|
from chromadb.api import ClientAPI
|
||||||
|
from chromadb.api.types import validate_embedding_function
|
||||||
|
from chromadb import Documents, EmbeddingFunction, Embeddings
|
||||||
|
from typing import cast
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
@@ -21,11 +21,9 @@ def suppress_logging(
|
|||||||
logger = logging.getLogger(logger_name)
|
logger = logging.getLogger(logger_name)
|
||||||
original_level = logger.getEffectiveLevel()
|
original_level = logger.getEffectiveLevel()
|
||||||
logger.setLevel(level)
|
logger.setLevel(level)
|
||||||
with (
|
with contextlib.redirect_stdout(io.StringIO()), contextlib.redirect_stderr(
|
||||||
contextlib.redirect_stdout(io.StringIO()),
|
io.StringIO()
|
||||||
contextlib.redirect_stderr(io.StringIO()),
|
), contextlib.suppress(UserWarning):
|
||||||
contextlib.suppress(UserWarning),
|
|
||||||
):
|
|
||||||
yield
|
yield
|
||||||
logger.setLevel(original_level)
|
logger.setLevel(original_level)
|
||||||
|
|
||||||
@@ -115,52 +113,12 @@ class RAGStorage(BaseRAGStorage):
|
|||||||
self.embedder_config = embedding_functions.HuggingFaceEmbeddingServer(
|
self.embedder_config = embedding_functions.HuggingFaceEmbeddingServer(
|
||||||
url=config.get("api_url"),
|
url=config.get("api_url"),
|
||||||
)
|
)
|
||||||
elif provider == "watson":
|
|
||||||
try:
|
|
||||||
import ibm_watsonx_ai.foundation_models as watson_models
|
|
||||||
from ibm_watsonx_ai import Credentials
|
|
||||||
from ibm_watsonx_ai.metanames import (
|
|
||||||
EmbedTextParamsMetaNames as EmbedParams,
|
|
||||||
)
|
|
||||||
except ImportError as e:
|
|
||||||
raise ImportError(
|
|
||||||
"IBM Watson dependencies are not installed. Please install them to use Watson embedding."
|
|
||||||
) from e
|
|
||||||
|
|
||||||
class WatsonEmbeddingFunction(EmbeddingFunction):
|
|
||||||
def __call__(self, input: Documents) -> Embeddings:
|
|
||||||
if isinstance(input, str):
|
|
||||||
input = [input]
|
|
||||||
|
|
||||||
embed_params = {
|
|
||||||
EmbedParams.TRUNCATE_INPUT_TOKENS: 3,
|
|
||||||
EmbedParams.RETURN_OPTIONS: {"input_text": True},
|
|
||||||
}
|
|
||||||
|
|
||||||
embedding = watson_models.Embeddings(
|
|
||||||
model_id=config.get("model"),
|
|
||||||
params=embed_params,
|
|
||||||
credentials=Credentials(
|
|
||||||
api_key=config.get("api_key"), url=config.get("api_url")
|
|
||||||
),
|
|
||||||
project_id=config.get("project_id"),
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
|
||||||
embeddings = embedding.embed_documents(input)
|
|
||||||
return cast(Embeddings, embeddings)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print("Error during Watson embedding:", e)
|
|
||||||
raise e
|
|
||||||
|
|
||||||
self.embedder_config = WatsonEmbeddingFunction()
|
|
||||||
else:
|
else:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
f"Unsupported embedding provider: {provider}, supported providers: [openai, azure, ollama, vertexai, google, cohere, huggingface, watson]"
|
f"Unsupported embedding provider: {provider}, supported providers: [openai, azure, ollama, vertexai, google, cohere, huggingface]"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
validate_embedding_function(self.embedder_config)
|
validate_embedding_function(self.embedder_config) # type: ignore # used for validating embedder_config if defined a embedding function/class
|
||||||
self.embedder_config = self.embedder_config
|
self.embedder_config = self.embedder_config
|
||||||
|
|
||||||
def _initialize_app(self):
|
def _initialize_app(self):
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ with suppress_warnings():
|
|||||||
|
|
||||||
|
|
||||||
from opentelemetry import trace # noqa: E402
|
from opentelemetry import trace # noqa: E402
|
||||||
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter # noqa: E402
|
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter # noqa: E402
|
||||||
from opentelemetry.sdk.resources import SERVICE_NAME, Resource # noqa: E402
|
from opentelemetry.sdk.resources import SERVICE_NAME, Resource # noqa: E402
|
||||||
from opentelemetry.sdk.trace import TracerProvider # noqa: E402
|
from opentelemetry.sdk.trace import TracerProvider # noqa: E402
|
||||||
from opentelemetry.sdk.trace.export import BatchSpanProcessor # noqa: E402
|
from opentelemetry.sdk.trace.export import BatchSpanProcessor # noqa: E402
|
||||||
@@ -48,10 +48,6 @@ class Telemetry:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.ready = False
|
self.ready = False
|
||||||
self.trace_set = False
|
self.trace_set = False
|
||||||
|
|
||||||
if os.getenv("OTEL_SDK_DISABLED", "false").lower() == "true":
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
telemetry_endpoint = "https://telemetry.crewai.com:4319"
|
telemetry_endpoint = "https://telemetry.crewai.com:4319"
|
||||||
self.resource = Resource(
|
self.resource = Resource(
|
||||||
|
|||||||
@@ -2,14 +2,13 @@ from datetime import datetime, date
|
|||||||
import json
|
import json
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
|
|
||||||
class CrewJSONEncoder(json.JSONEncoder):
|
class CrewJSONEncoder(json.JSONEncoder):
|
||||||
def default(self, obj):
|
def default(self, obj):
|
||||||
if isinstance(obj, BaseModel):
|
if isinstance(obj, BaseModel):
|
||||||
return self._handle_pydantic_model(obj)
|
return self._handle_pydantic_model(obj)
|
||||||
elif isinstance(obj, UUID) or isinstance(obj, Decimal):
|
elif isinstance(obj, UUID):
|
||||||
return str(obj)
|
return str(obj)
|
||||||
|
|
||||||
elif isinstance(obj, datetime) or isinstance(obj, date):
|
elif isinstance(obj, datetime) or isinstance(obj, date):
|
||||||
|
|||||||
@@ -1,109 +0,0 @@
|
|||||||
import unittest
|
|
||||||
import json
|
|
||||||
import tempfile
|
|
||||||
import shutil
|
|
||||||
from pathlib import Path
|
|
||||||
from crewai.cli.config import Settings
|
|
||||||
|
|
||||||
class TestSettings(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.test_dir = Path(tempfile.mkdtemp())
|
|
||||||
self.config_path = self.test_dir / "settings.json"
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
shutil.rmtree(self.test_dir)
|
|
||||||
|
|
||||||
def test_empty_initialization(self):
|
|
||||||
settings = Settings(config_path=self.config_path)
|
|
||||||
self.assertIsNone(settings.tool_repository_username)
|
|
||||||
self.assertIsNone(settings.tool_repository_password)
|
|
||||||
|
|
||||||
def test_initialization_with_data(self):
|
|
||||||
settings = Settings(
|
|
||||||
config_path=self.config_path,
|
|
||||||
tool_repository_username="user1"
|
|
||||||
)
|
|
||||||
self.assertEqual(settings.tool_repository_username, "user1")
|
|
||||||
self.assertIsNone(settings.tool_repository_password)
|
|
||||||
|
|
||||||
def test_initialization_with_existing_file(self):
|
|
||||||
self.config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
with self.config_path.open("w") as f:
|
|
||||||
json.dump({"tool_repository_username": "file_user"}, f)
|
|
||||||
|
|
||||||
settings = Settings(config_path=self.config_path)
|
|
||||||
self.assertEqual(settings.tool_repository_username, "file_user")
|
|
||||||
|
|
||||||
def test_merge_file_and_input_data(self):
|
|
||||||
self.config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
with self.config_path.open("w") as f:
|
|
||||||
json.dump({
|
|
||||||
"tool_repository_username": "file_user",
|
|
||||||
"tool_repository_password": "file_pass"
|
|
||||||
}, f)
|
|
||||||
|
|
||||||
settings = Settings(
|
|
||||||
config_path=self.config_path,
|
|
||||||
tool_repository_username="new_user"
|
|
||||||
)
|
|
||||||
self.assertEqual(settings.tool_repository_username, "new_user")
|
|
||||||
self.assertEqual(settings.tool_repository_password, "file_pass")
|
|
||||||
|
|
||||||
def test_dump_new_settings(self):
|
|
||||||
settings = Settings(
|
|
||||||
config_path=self.config_path,
|
|
||||||
tool_repository_username="user1"
|
|
||||||
)
|
|
||||||
settings.dump()
|
|
||||||
|
|
||||||
with self.config_path.open("r") as f:
|
|
||||||
saved_data = json.load(f)
|
|
||||||
|
|
||||||
self.assertEqual(saved_data["tool_repository_username"], "user1")
|
|
||||||
|
|
||||||
def test_update_existing_settings(self):
|
|
||||||
self.config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
with self.config_path.open("w") as f:
|
|
||||||
json.dump({"existing_setting": "value"}, f)
|
|
||||||
|
|
||||||
settings = Settings(
|
|
||||||
config_path=self.config_path,
|
|
||||||
tool_repository_username="user1"
|
|
||||||
)
|
|
||||||
settings.dump()
|
|
||||||
|
|
||||||
with self.config_path.open("r") as f:
|
|
||||||
saved_data = json.load(f)
|
|
||||||
|
|
||||||
self.assertEqual(saved_data["existing_setting"], "value")
|
|
||||||
self.assertEqual(saved_data["tool_repository_username"], "user1")
|
|
||||||
|
|
||||||
def test_none_values(self):
|
|
||||||
settings = Settings(
|
|
||||||
config_path=self.config_path,
|
|
||||||
tool_repository_username=None
|
|
||||||
)
|
|
||||||
settings.dump()
|
|
||||||
|
|
||||||
with self.config_path.open("r") as f:
|
|
||||||
saved_data = json.load(f)
|
|
||||||
|
|
||||||
self.assertIsNone(saved_data.get("tool_repository_username"))
|
|
||||||
|
|
||||||
def test_invalid_json_in_config(self):
|
|
||||||
self.config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
with self.config_path.open("w") as f:
|
|
||||||
f.write("invalid json")
|
|
||||||
|
|
||||||
try:
|
|
||||||
settings = Settings(config_path=self.config_path)
|
|
||||||
self.assertIsNone(settings.tool_repository_username)
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
self.fail("Settings initialization should handle invalid JSON")
|
|
||||||
|
|
||||||
def test_empty_config_file(self):
|
|
||||||
self.config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
self.config_path.touch()
|
|
||||||
|
|
||||||
settings = Settings(config_path=self.config_path)
|
|
||||||
self.assertIsNone(settings.tool_repository_username)
|
|
||||||
@@ -82,7 +82,6 @@ def test_install_success(mock_get, mock_subprocess_run):
|
|||||||
capture_output=False,
|
capture_output=False,
|
||||||
text=True,
|
text=True,
|
||||||
check=True,
|
check=True,
|
||||||
env=unittest.mock.ANY
|
|
||||||
)
|
)
|
||||||
|
|
||||||
assert "Succesfully installed sample-tool" in output
|
assert "Succesfully installed sample-tool" in output
|
||||||
|
|||||||
Reference in New Issue
Block a user