Claude 24f816b6a3
Consolidate 22 sibling repos into layered organism structure
Place useful parts of the surrounding repos into sica-fondt by layer, per the
body model (Ada = membrane; brain/endocrine/capabilities/knowledge non-Ada):

- brain/        LLM reasoning + providers (dapr, hermes, MoMoA)
- capabilities/ REPRAG sidecars: hermes tools/skills, dapr tools, parallel
                dispatch, A51 channels, and the OSINT cluster
- knowledge/    LORAG corpus: 754 cyber-skills, agency personas, secure-coding,
                MITRE ATT&CK data
- reference/    defensive threat-reference (C3, shhbruh doc) + AdaYaml parser

License handling: AGPL sources (worldosint, advanced_evolution, mercury,
Reticulum) and GPL DeTTECT are SPEC-only clean-room/port descriptions — no
copyleft code copied. MIT/Apache/data parts copied as working trees.

Safety: shhbruh escape/persistence material and C3 covert-C2 kept as reference
only, not wired into the running organism. See CONSOLIDATION.md.

https://claude.ai/code/session_01UehUqEXXJJCsHoA4voCU5c
2026-06-10 06:53:01 +00:00

215 lines
7.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#
# Copyright 2026 The Dapr Authors
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
from pathlib import Path
from typing import (
Any,
ClassVar,
Dict,
Iterable,
Iterator,
List,
Literal,
Optional,
Type,
Union,
)
from pydantic import BaseModel, Field
from dapr_agents.llm.chat import ChatClientBase
from dapr_agents.llm.nvidia.client import NVIDIAClientBase
from dapr_agents.llm.utils import RequestHandler, ResponseHandler
from dapr_agents.prompt.base import PromptTemplateBase
from dapr_agents.prompt.prompty import Prompty
from dapr_agents.tool import AgentTool
from dapr_agents.types.message import (
BaseMessage,
LLMChatCandidateChunk,
LLMChatResponse,
)
logger = logging.getLogger(__name__)
class NVIDIAChatClient(NVIDIAClientBase, ChatClientBase):
"""
Chat client for NVIDIA chat models, combining NVIDIA client management
with Prompty-specific prompt templates and unified request/response handling.
Inherits:
- NVIDIAClientBase: manages API key, base_url, retries, etc. for NVIDIA endpoints.
- ChatClientBase: provides chat-specific abstractions.
Attributes:
model: the model name to use (e.g. "meta/llama-3.1-8b-instruct").
max_tokens: maximum number of tokens to generate per call.
"""
model: str = Field(
default="meta/llama-3.1-8b-instruct",
description="Model name to use. Defaults to 'meta/llama-3.1-8b-instruct'.",
)
max_tokens: Optional[int] = Field(
default=1024,
description=(
"Maximum number of tokens to generate in a single call. "
"Must be ≥1; defaults to 1024."
),
)
prompty: Optional[Prompty] = Field(
default=None, description="Optional Prompty instance for templating."
)
prompt_template: Optional[PromptTemplateBase] = Field(
default=None, description="Optional prompt-template to format inputs."
)
# NVIDIA currently only supports function_call structured output
SUPPORTED_STRUCTURED_MODES: ClassVar[set[str]] = {"function_call"}
def model_post_init(self, __context: Any) -> None:
"""
After Pydantic init, configure the client for 'chat' API.
"""
self._api = "chat"
super().model_post_init(__context)
@classmethod
def from_prompty(cls, prompty_source: Union[str, Path]) -> "NVIDIAChatClient":
"""
Build an NVIDIAChatClient from a Prompty spec (file path or inline YAML/JSON).
Args:
prompty_source: Path or inline content of a Prompty specification.
Returns:
Configured NVIDIAChatClient instance.
"""
prompty_instance = Prompty.load(prompty_source)
prompt_template = Prompty.to_prompt_template(prompty_instance)
cfg = prompty_instance.model.configuration
return cls.model_validate(
{
"model": cfg.name,
"api_key": cfg.api_key,
"base_url": cfg.base_url,
"prompty": prompty_instance,
"prompt_template": prompt_template,
}
)
def generate(
self,
messages: Union[
str,
Dict[str, Any],
BaseMessage,
Iterable[Union[Dict[str, Any], BaseMessage]],
] = None,
*,
input_data: Optional[Dict[str, Any]] = None,
model: Optional[str] = None,
tools: Optional[List[Union[AgentTool, Dict[str, Any]]]] = None,
response_format: Optional[Type[BaseModel]] = None,
max_tokens: Optional[int] = None,
structured_mode: Literal["function_call"] = "function_call",
stream: bool = False,
**kwargs: Any,
) -> Union[
Iterator[LLMChatCandidateChunk], # streaming
LLMChatResponse, # nonstream + no format
BaseModel, # nonstream + single structured format
List[BaseModel], # nonstream + list structured format
]:
"""
Issue a chat completion to NVIDIA.
- If `stream=True` in kwargs, returns an iterator of
`LLMChatCandidateChunk` via ResponseHandler.
- Otherwise returns either:
• a raw `LLMChatResponse`, or
• validated Pydantic model(s) per `response_format`.
Args:
messages: Pre-built messages or None to use `input_data`.
input_data: Variables for the Prompty template.
model: Override default model name.
tools: List of AgentTool or dict specs.
response_format: Pydantic model (or list thereof) for structured output.
max_tokens: Override default max_tokens.
structured_mode: Must be "function_call" (only supported mode).
stream: If True, return an iterator of `LLMChatCandidateChunk`.
**kwargs: Other LLM params (temperature, stream, etc.).
Raises:
ValueError: for invalid structured_mode or missing inputs.
"""
# 1) Validate structured_mode
if structured_mode not in self.SUPPORTED_STRUCTURED_MODES:
raise ValueError(
f"structured_mode must be one of {self.SUPPORTED_STRUCTURED_MODES}"
)
# 2) If input_data is provided, format messages via Prompty
if input_data:
if not self.prompt_template:
raise ValueError("input_data provided but no prompt_template is set.")
logger.info("Formatting messages via prompt_template.")
messages = self.prompt_template.format_prompt(**input_data)
if not messages:
raise ValueError("Either 'messages' or 'input_data' must be provided.")
# 3) Normalize messages + merge client/prompty defaults
params: Dict[str, Any] = {
"messages": RequestHandler.normalize_chat_messages(messages)
}
if self.prompty:
params = {**self.prompty.model.parameters.model_dump(), **params, **kwargs}
else:
params.update(kwargs)
# 4) Add the stream parameter explicitly to params
params["stream"] = stream
# 5) Override model & max_tokens if provided
params["model"] = model or self.model
params["max_tokens"] = max_tokens or self.max_tokens
# 6) Inject tools / response_format / structured_mode
params = RequestHandler.process_params(
params,
llm_provider=self.provider,
tools=tools,
response_format=response_format,
structured_mode=structured_mode,
)
# 7) Call NVIDIA API + dispatch to ResponseHandler
try:
logger.info("Calling NVIDIA ChatCompletion API.")
logger.debug(f"Parameters: {params}")
resp = self.client.chat.completions.create(**params)
return ResponseHandler.process_response(
response=resp,
llm_provider=self.provider,
response_format=response_format,
structured_mode=structured_mode,
stream=stream,
)
except Exception:
logger.error("NVIDIA ChatCompletion error", exc_info=True)
raise