Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .hooks/generate_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def simple_convert_markdown(
html_id: str = "",
**kwargs: t.Any,
) -> t.Any:
return Markup(md.convert(text) if text else "") # noqa: S704 # nosec
return Markup(md.convert(text) if text else "") # nosec # noqa: S704

self.handler.env.filters["convert_markdown"] = simple_convert_markdown

Expand Down
2 changes: 1 addition & 1 deletion dreadnode/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from dreadnode.version import VERSION

if t.TYPE_CHECKING:
from dreadnode import scorers # noqa: F401
from dreadnode import scorers

logger.disable("dreadnode")

Expand Down
5 changes: 2 additions & 3 deletions dreadnode/agent/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
from dreadnode.agent.stop import StopCondition, stop_never
from dreadnode.agent.thread import Thread
from dreadnode.agent.tools import AnyTool, Tool, Toolset, discover_tools_on_obj
from dreadnode.agent.tools.planning import update_todo
from dreadnode.agent.tools.tasking import finish_task, give_up_on_task
from dreadnode.agent.types import Message, ToolCall
from dreadnode.meta import Component, Config, Model, component
from dreadnode.scorers import ScorersLike
Expand Down Expand Up @@ -745,9 +747,6 @@ class TaskAgent(Agent):
"""

def model_post_init(self, _: t.Any) -> None:
from dreadnode.agent.tools.planning import update_todo
from dreadnode.agent.tools.tasking import finish_task, give_up_on_task

if not any(tool for tool in self.tools if tool.name == "finish_task"):
self.tools.append(finish_task)

Expand Down
12 changes: 6 additions & 6 deletions dreadnode/agent/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ def _handle_tool_start(self, event: ToolStart) -> None:
self._status_table, console=self.console, transient=True, auto_refresh=True
)
self._live_status.start()
if self._status_table is not None:
# Add a new row for the running tool with a spinner.
self._status_table.add_row(
Text(f"Running [bold]{event.tool_call.name}[/bold]...", style="yellow")
)

# Add a new row for the running tool with a spinner.
self._status_table.add_row(
Text(f"Running [bold]{event.tool_call.name}[/bold]...", style="yellow")
)

def _handle_tool_end(self, event: ToolEnd):
def _handle_tool_end(self, event: ToolEnd) -> None:
"""Prints the tool's result and cleans up the status board."""
# First, print the static result panel. This ensures it's in the
# console history even after the live display is gone.
Expand Down
4 changes: 2 additions & 2 deletions dreadnode/agent/hooks/summarize.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import contextlib
import typing as t

from litellm.exceptions import ContextWindowExceededError

from dreadnode.agent.events import AgentError, AgentEvent, GenerationEnd, StepStart
from dreadnode.agent.prompts import summarize_conversation
from dreadnode.agent.reactions import Continue, Reaction, Retry
Expand All @@ -23,8 +25,6 @@
def _is_context_length_error(error: BaseException) -> bool:
"""Checks if an exception is likely due to exceeding the context window."""
with contextlib.suppress(ImportError):
from litellm.exceptions import ContextWindowExceededError

if isinstance(error, ContextWindowExceededError):
return True

Expand Down
4 changes: 2 additions & 2 deletions dreadnode/agent/tools/fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import rigging as rg
from fsspec import AbstractFileSystem # type: ignore[import-untyped]
from pydantic import PrivateAttr
from upath import UPath
from upath import UPath # type: ignore[import-not-found]

from dreadnode.agent.tools import Toolset, tool_method
from dreadnode.meta import Config
Expand Down Expand Up @@ -127,7 +127,7 @@ def read_file(
content = _path.read_bytes()

try:
return content.decode("utf-8")
return content.decode("utf-8") # type: ignore[no-any-return]
except UnicodeDecodeError as e:
if self.multi_modal:
return rg.ContentImageUrl.from_file(path)
Expand Down
2 changes: 1 addition & 1 deletion dreadnode/agent/tools/tasking.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


@tool
async def finish_task(success: bool, summary: str) -> None: # noqa: ARG001, FBT001
async def finish_task(success: bool, summary: str) -> None: # noqa: ARG001
"""
Mark your task as complete with a success/failure status and markdown summary of actions taken.

Expand Down
4 changes: 2 additions & 2 deletions dreadnode/airt/attack/prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def prompt_attack(
beam_width: int = 3,
branching_factor: int = 3,
max_steps: int = 10,
additional_scorers: list[Scorer] | None = None,
additional_scorers: list[Scorer[t.Any]] | None = None,
name: str | None = None,
) -> Attack[str, str]:
"""
Expand Down Expand Up @@ -88,7 +88,7 @@ def prompt_attack(

objective = weighted_avg(
(judge_scorer, 1),
*[(scorer, 1) for scorer in additional_scorers],
*[(scorer, 1) for scorer in (additional_scorers or [])],
name="prompt_objective",
)

Expand Down
2 changes: 1 addition & 1 deletion dreadnode/airt/attack/tap.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def tap_attack(
beam_width: int = 10,
branching_factor: int = 3,
max_steps: int = 10,
additional_constraints: list[Scorer] | None = None,
additional_constraints: list[Scorer[t.Any]] | None = None,
) -> Attack[str, str]:
"""
Creates a Generative Attack optimized for the TAP (Tree-of-thought Attack Prompting) pattern,
Expand Down
9 changes: 7 additions & 2 deletions dreadnode/airt/target/llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class LLMTarget(Model, Target[t.Any, str]):

@property
def name(self) -> str:
if self._generator is None:
return "unknown"
return self._generator.to_identifier(short=True)

def as_task(self, input: t.Any) -> Task[[], str]:
Expand All @@ -51,9 +53,12 @@ def as_task(self, input: t.Any) -> Task[[], str]:

@task(name=f"generate - {self.name}", label="llm_target_generate", tags=["target"])
async def generate(
messages: list[rg.Message] = messages, params: rg.GenerateParams = params
messages: list[rg.Message] = messages, params: rg.GenerateParams | None = params
) -> str:
generated = (await self._generator.generate_messages([messages], [params]))[0]
if self._generator is None:
raise ValueError("Generator not initialized")
params_list = [params] if params is not None else [rg.GenerateParams()]
generated = (await self._generator.generate_messages([messages], params_list))[0]
if isinstance(generated, BaseException):
raise generated
return generated.message.content
Expand Down
2 changes: 1 addition & 1 deletion dreadnode/artifact/credential_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from datetime import datetime, timezone
from typing import TYPE_CHECKING, TypeVar

from botocore.exceptions import ClientError
from botocore.exceptions import ClientError # type: ignore[import-untyped]
from loguru import logger
from s3fs import S3FileSystem # type: ignore[import-untyped]

Expand Down
3 changes: 1 addition & 2 deletions dreadnode/cli/agent/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import rich

from dreadnode import log_input
from dreadnode import run as run_span
from dreadnode.agent import Agent
from dreadnode.agent.format import format_agent, format_agents_table
from dreadnode.discovery import DEFAULT_SEARCH_PATHS, discover
Expand Down Expand Up @@ -118,8 +119,6 @@ async def agent_cli(
*,
config: t.Any = config_default,
) -> None:
from dreadnode import run as run_span

flat_config = {k: v for k, v in flatten_model(config).items() if v is not None}
agent = hydrate(agent_blueprint, config)

Expand Down
6 changes: 2 additions & 4 deletions dreadnode/cli/main.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import contextlib
import importlib.metadata
import pathlib
import platform
import shutil
import sys
import typing as t
Expand Down Expand Up @@ -202,10 +204,6 @@ def clone(

@cli.command(help="Show versions and exit.", group="Meta")
def version() -> None:
import importlib.metadata
import platform
import sys

version = importlib.metadata.version("dreadnode")
python_version = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"

Expand Down
3 changes: 1 addition & 2 deletions dreadnode/cli/profile/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import cyclopts
import rich
from rich import box
from rich.prompt import Prompt
from rich.table import Table

from dreadnode.cli.api import Token
Expand Down Expand Up @@ -59,8 +60,6 @@ def switch(

# If no profile provided, prompt user to choose
if profile is None:
from rich.prompt import Prompt

profiles = list(config.servers.keys())
rich.print("\nAvailable profiles:")
for i, p in enumerate(profiles, 1):
Expand Down
10 changes: 4 additions & 6 deletions dreadnode/convert.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import typing as t

if t.TYPE_CHECKING:
import networkx as nx # type: ignore [import-untyped]
import networkx as nx # type: ignore[import-untyped]

if t.TYPE_CHECKING:
from dreadnode.tracing.span import RunSpan


def run_span_to_graph(run: "RunSpan") -> "nx.DiGraph":
try:
import networkx as nx # pyright: ignore[reportMissingModuleSource]
except ImportError as e:
graph = nx.DiGraph()
except NameError as e:
raise RuntimeError("The `networkx` package is required for graph conversion") from e

graph = nx.DiGraph()

graph.add_node(
run.run_id,
name=run.name,
Expand Down
26 changes: 9 additions & 17 deletions dreadnode/data_types/audio.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
import importlib.util
import io
import typing as t
from pathlib import Path

from dreadnode.data_types.base import DataType
import numpy as np

if t.TYPE_CHECKING:
import numpy as np
from dreadnode.data_types.base import DataType


def check_imports() -> None:
try:
import soundfile as sf # type: ignore[import-untyped,unused-ignore] # noqa: F401
except ImportError as e:
if importlib.util.find_spec("soundfile") is None:
raise ImportError(
"Audio processing requires SoundFile. Install with: pip install dreadnode[multimodal]"
) from e
)

try:
import numpy as np # type: ignore[import-untyped,unused-ignore] # noqa: F401
except ImportError as e:
if importlib.util.find_spec("numpy") is None:
raise ImportError(
"Audio processing requires NumPy. Install with: pip install dreadnode[multimodal]"
) from e
)


AudioDataType: t.TypeAlias = "str | Path | np.ndarray[t.Any, t.Any] | bytes"
Expand Down Expand Up @@ -78,7 +74,6 @@ def _process_audio_data(self) -> tuple[bytes, str, int | None, float | None]:
Returns:
A tuple of (audio_bytes, format_name, sample_rate, duration)
"""
import numpy as np

if isinstance(self._data, str | Path) and Path(self._data).exists():
return self._process_file_path()
Expand All @@ -94,7 +89,7 @@ def _process_file_path(self) -> tuple[bytes, str, int | None, float | None]:
Returns:
A tuple of (audio_bytes, format_name, sample_rate, duration)
"""
import soundfile as sf # type: ignore[import-not-found,unused-ignore]
import soundfile as sf # type: ignore # noqa: PGH003

path_str = str(self._data)
audio_bytes = Path(path_str).read_bytes()
Expand All @@ -113,8 +108,7 @@ def _process_numpy_array(self) -> tuple[bytes, str, int | None, float | None]:
Returns:
A tuple of (audio_bytes, format_name, sample_rate, duration)
"""
import numpy as np # type: ignore[import-not-found,unused-ignore]
import soundfile as sf # type: ignore[import-not-found,unused-ignore]
import soundfile as sf

if self._sample_rate is None:
raise ValueError('Argument "sample_rate" is required when using numpy arrays.')
Expand Down Expand Up @@ -151,8 +145,6 @@ def _generate_metadata(
Returns:
A dictionary of metadata
"""
import numpy as np # type: ignore[import-not-found,unused-ignore]

metadata: dict[str, str | int | float | None] = {
"extension": format_name.lower(),
"x-python-datatype": "dreadnode.Audio.bytes",
Expand Down
2 changes: 2 additions & 0 deletions dreadnode/data_types/base.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import typing as t
from abc import ABC, abstractmethod

Expand Down
Loading