mirror of
https://github.com/SHOGGOTH-SECTOR/sica-fondt.git
synced 2026-08-01 00:23:15 +00:00
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
161 lines
5.7 KiB
Python
161 lines
5.7 KiB
Python
#
|
|
# 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 typing import Any, Dict, Optional, Union
|
|
|
|
from dapr_agents.llm.openai.client.base import OpenAIClientBase
|
|
from dapr_agents.llm.utils import RequestHandler
|
|
from dapr_agents.types.llm import (
|
|
AudioSpeechRequest,
|
|
AudioTranscriptionRequest,
|
|
AudioTranscriptionResponse,
|
|
AudioTranslationRequest,
|
|
AudioTranslationResponse,
|
|
)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class OpenAIAudioClient(OpenAIClientBase):
|
|
"""
|
|
Client for handling OpenAI's audio functionalities, including speech generation, transcription, and translation.
|
|
Inherits shared logic and configuration from OpenAIClientBase.
|
|
"""
|
|
|
|
def model_post_init(self, __context: Any) -> None:
|
|
"""
|
|
Initializes the private attributes specific to the audio client.
|
|
"""
|
|
self._api = "audio"
|
|
super().model_post_init(__context)
|
|
|
|
def create_speech(
|
|
self,
|
|
request: Union[AudioSpeechRequest, Dict[str, Any]],
|
|
file_name: Optional[str] = None,
|
|
) -> Union[bytes, None]:
|
|
"""
|
|
Generate speech audio from text and optionally save it to a file.
|
|
|
|
Args:
|
|
request (Union[AudioSpeechRequest, Dict[str, Any]]): The request parameters for speech generation.
|
|
file_name (Optional[str]): Optional file name to save the generated audio.
|
|
|
|
Returns:
|
|
Union[bytes, None]: The generated audio content as bytes if no file_name is provided, otherwise None.
|
|
"""
|
|
# Transform dictionary to Pydantic object if needed
|
|
validated_request: AudioSpeechRequest = RequestHandler.validate_request(
|
|
request, AudioSpeechRequest
|
|
)
|
|
|
|
logger.info(f"Using model '{validated_request.model}' for speech generation.")
|
|
|
|
input_text = validated_request.input
|
|
|
|
max_chunk_size = 4096
|
|
|
|
if len(input_text) > max_chunk_size:
|
|
logger.info(
|
|
f"Input exceeds {max_chunk_size} characters. Splitting into smaller chunks."
|
|
)
|
|
|
|
# Split input text into manageable chunks
|
|
def split_text(text, max_size):
|
|
chunks = []
|
|
while len(text) > max_size:
|
|
split_index = text.rfind(". ", 0, max_size) + 1 or max_size
|
|
chunks.append(text[:split_index].strip())
|
|
text = text[split_index:].strip()
|
|
chunks.append(text)
|
|
return chunks
|
|
|
|
text_chunks = split_text(input_text, max_chunk_size)
|
|
|
|
audio_chunks = []
|
|
|
|
try:
|
|
for chunk in text_chunks:
|
|
validated_request.input = chunk
|
|
with self.client.with_streaming_response.audio.speech.create(
|
|
**validated_request.model_dump()
|
|
) as response:
|
|
if file_name:
|
|
# Write each chunk incrementally to the file
|
|
logger.info(f"Saving audio chunk to file: {file_name}")
|
|
with open(file_name, "ab") as audio_file:
|
|
for chunk in response.iter_bytes():
|
|
audio_file.write(chunk)
|
|
else:
|
|
# Collect all chunks in memory for combining
|
|
audio_chunks.extend(response.iter_bytes())
|
|
|
|
if file_name:
|
|
return None
|
|
else:
|
|
# Combine all chunks into one bytes object
|
|
return b"".join(audio_chunks)
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to create or save speech: {e}")
|
|
raise ValueError(f"An error occurred during speech generation: {e}")
|
|
|
|
def create_transcription(
|
|
self, request: Union[AudioTranscriptionRequest, Dict[str, Any]]
|
|
) -> AudioTranscriptionResponse:
|
|
"""
|
|
Transcribe audio to text.
|
|
|
|
Args:
|
|
request (Union[AudioTranscriptionRequest, Dict[str, Any]]): The request parameters for transcription.
|
|
|
|
Returns:
|
|
AudioTranscriptionResponse: The transcription result.
|
|
"""
|
|
validated_request: AudioTranscriptionRequest = RequestHandler.validate_request(
|
|
request, AudioTranscriptionRequest
|
|
)
|
|
|
|
logger.info(f"Using model '{validated_request.model}' for transcription.")
|
|
|
|
response = self.client.audio.transcriptions.create(
|
|
file=validated_request.file,
|
|
**validated_request.model_dump(exclude={"file"}),
|
|
)
|
|
return response
|
|
|
|
def create_translation(
|
|
self, request: Union[AudioTranslationRequest, Dict[str, Any]]
|
|
) -> AudioTranslationResponse:
|
|
"""
|
|
Translate audio to English.
|
|
|
|
Args:
|
|
request (Union[AudioTranslationRequest, Dict[str, Any]]): The request parameters for translation.
|
|
|
|
Returns:
|
|
AudioTranslationResponse: The translation result.
|
|
"""
|
|
validated_request: AudioTranslationRequest = RequestHandler.validate_request(
|
|
request, AudioTranslationRequest
|
|
)
|
|
|
|
logger.info(f"Using model '{validated_request.model}' for translation.")
|
|
|
|
response = self.client.audio.translations.create(
|
|
file=validated_request.file,
|
|
**validated_request.model_dump(exclude={"file"}),
|
|
)
|
|
return response
|