Initial commit
This commit is contained in:
186
hooks/utils/llm/anth.py
Executable file
186
hooks/utils/llm/anth.py
Executable file
@@ -0,0 +1,186 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
from dotenv import load_dotenv
|
||||
|
||||
|
||||
def prompt_llm(prompt_text):
|
||||
"""
|
||||
Base Anthropic LLM prompting method using fastest model.
|
||||
|
||||
Args:
|
||||
prompt_text (str): The prompt to send to the model
|
||||
|
||||
Returns:
|
||||
str: The model's response text, or None if error
|
||||
"""
|
||||
load_dotenv()
|
||||
|
||||
api_key = os.getenv("__ANTHROPIC_API_KEY")
|
||||
if not api_key:
|
||||
return None
|
||||
|
||||
try:
|
||||
import anthropic
|
||||
|
||||
client = anthropic.Anthropic(api_key=api_key)
|
||||
|
||||
message = client.messages.create(
|
||||
model="claude-3-5-haiku-20241022", # Fastest Anthropic model
|
||||
max_tokens=100,
|
||||
temperature=0.7,
|
||||
messages=[{"role": "user", "content": prompt_text}],
|
||||
)
|
||||
|
||||
return message.content[0].text.strip()
|
||||
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def generate_completion_message():
|
||||
"""
|
||||
Generate a completion message using Anthropic LLM.
|
||||
|
||||
Returns:
|
||||
str: A natural language completion message, or None if error
|
||||
"""
|
||||
engineer_name = os.getenv("ENGINEER_NAME", "").strip()
|
||||
|
||||
if engineer_name:
|
||||
name_instruction = f"Sometimes (about 30% of the time) include the engineer's name '{engineer_name}' in a natural way."
|
||||
examples = f"""Examples of the style:
|
||||
- Standard: "Work complete!", "All done!", "Task finished!", "Ready for your next move!"
|
||||
- Personalized: "{engineer_name}, all set!", "Ready for you, {engineer_name}!", "Complete, {engineer_name}!", "{engineer_name}, we're done!" """
|
||||
else:
|
||||
name_instruction = ""
|
||||
examples = """Examples of the style: "Work complete!", "All done!", "Task finished!", "Ready for your next move!" """
|
||||
|
||||
prompt = f"""Generate a short, friendly completion message for when an AI coding assistant finishes a task.
|
||||
|
||||
Requirements:
|
||||
- Keep it under 10 words
|
||||
- Make it positive and future focused
|
||||
- Use natural, conversational language
|
||||
- Focus on completion/readiness
|
||||
- Do NOT include quotes, formatting, or explanations
|
||||
- Return ONLY the completion message text
|
||||
{name_instruction}
|
||||
|
||||
{examples}
|
||||
|
||||
Generate ONE completion message:"""
|
||||
|
||||
response = prompt_llm(prompt)
|
||||
|
||||
# Clean up response - remove quotes and extra formatting
|
||||
if response:
|
||||
response = response.strip().strip('"').strip("'").strip()
|
||||
# Take first line if multiple lines
|
||||
response = response.split("\n")[0].strip()
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def generate_agent_name():
|
||||
"""
|
||||
Generate a one-word agent name using Anthropic.
|
||||
|
||||
Returns:
|
||||
str: A single-word agent name, or fallback name if error
|
||||
"""
|
||||
import random
|
||||
|
||||
# Example names to guide generation
|
||||
example_names = [
|
||||
"Phoenix", "Sage", "Nova", "Echo", "Atlas", "Cipher", "Nexus",
|
||||
"Oracle", "Quantum", "Zenith", "Aurora", "Vortex", "Nebula",
|
||||
"Catalyst", "Prism", "Axiom", "Helix", "Flux", "Synth", "Vertex"
|
||||
]
|
||||
|
||||
# If no API key, return random fallback
|
||||
if not os.getenv("__ANTHROPIC_API_KEY"):
|
||||
return random.choice(example_names)
|
||||
|
||||
# Create examples string
|
||||
examples_str = ", ".join(example_names[:10]) # Use first 10 as examples
|
||||
|
||||
prompt_text = f"""Generate exactly ONE unique agent/assistant name.
|
||||
|
||||
Requirements:
|
||||
- Single word only (no spaces, hyphens, or punctuation)
|
||||
- Abstract and memorable
|
||||
- Professional sounding
|
||||
- Easy to pronounce
|
||||
- Similar style to these examples: {examples_str}
|
||||
|
||||
Generate a NEW name (not from the examples). Respond with ONLY the name, nothing else.
|
||||
|
||||
Name:"""
|
||||
|
||||
try:
|
||||
# Use faster Haiku model with lower tokens for name generation
|
||||
load_dotenv()
|
||||
api_key = os.getenv("__ANTHROPIC_API_KEY")
|
||||
if not api_key:
|
||||
raise Exception("No API key")
|
||||
|
||||
import anthropic
|
||||
client = anthropic.Anthropic(api_key=api_key)
|
||||
|
||||
message = client.messages.create(
|
||||
model="claude-3-5-haiku-20241022", # Fast model
|
||||
max_tokens=20,
|
||||
temperature=0.7,
|
||||
messages=[{"role": "user", "content": prompt_text}],
|
||||
)
|
||||
|
||||
# Extract and clean the name
|
||||
name = message.content[0].text.strip()
|
||||
# Ensure it's a single word
|
||||
name = name.split()[0] if name else "Agent"
|
||||
# Remove any punctuation
|
||||
name = ''.join(c for c in name if c.isalnum())
|
||||
# Capitalize first letter
|
||||
name = name.capitalize() if name else "Agent"
|
||||
|
||||
# Validate it's not empty and reasonable length
|
||||
if name and 3 <= len(name) <= 20:
|
||||
return name
|
||||
else:
|
||||
raise Exception("Invalid name generated")
|
||||
|
||||
except Exception:
|
||||
# Return random fallback name
|
||||
return random.choice(example_names)
|
||||
|
||||
|
||||
def main():
|
||||
"""Command line interface for testing."""
|
||||
import json
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
if sys.argv[1] == "--completion":
|
||||
message = generate_completion_message()
|
||||
if message:
|
||||
print(message)
|
||||
else:
|
||||
print("Error generating completion message")
|
||||
elif sys.argv[1] == "--agent-name":
|
||||
# Generate agent name (no input needed)
|
||||
name = generate_agent_name()
|
||||
print(name)
|
||||
else:
|
||||
prompt_text = " ".join(sys.argv[1:])
|
||||
response = prompt_llm(prompt_text)
|
||||
if response:
|
||||
print(response)
|
||||
else:
|
||||
print("Error calling Anthropic API")
|
||||
else:
|
||||
print("Usage: ./anth.py 'your prompt here' or ./anth.py --completion or ./anth.py --agent-name")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
98
hooks/utils/tts/pyttsx3_tts.py
Executable file
98
hooks/utils/tts/pyttsx3_tts.py
Executable file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import random
|
||||
|
||||
def main():
|
||||
"""
|
||||
pyttsx3 TTS Script
|
||||
|
||||
Uses pyttsx3 for offline text-to-speech synthesis.
|
||||
Accepts optional text prompt as command-line argument.
|
||||
|
||||
Usage:
|
||||
- ./pyttsx3_tts.py # Uses default text
|
||||
- ./pyttsx3_tts.py "Your custom text" # Uses provided text
|
||||
|
||||
Features:
|
||||
- Offline TTS (no API key required)
|
||||
- Cross-platform compatibility
|
||||
- Configurable voice settings
|
||||
- Immediate audio playback
|
||||
"""
|
||||
|
||||
try:
|
||||
import pyttsx3
|
||||
|
||||
# Initialize TTS engine
|
||||
engine = pyttsx3.init()
|
||||
|
||||
# Configure French voice if available
|
||||
voices = engine.getProperty('voices')
|
||||
french_voice = None
|
||||
|
||||
# Priority order for French voices
|
||||
french_voice_preferences = [
|
||||
'roa/fr', # French (France) - preferred
|
||||
'roa/fr-be', # French (Belgium)
|
||||
'roa/fr-ch', # French (Switzerland)
|
||||
]
|
||||
|
||||
# Find the best French voice (exact match)
|
||||
for pref in french_voice_preferences:
|
||||
for voice in voices:
|
||||
if voice.id == pref: # Exact match instead of substring
|
||||
french_voice = voice
|
||||
break
|
||||
if french_voice:
|
||||
break
|
||||
|
||||
# Set French voice if found
|
||||
if french_voice:
|
||||
engine.setProperty('voice', french_voice.id)
|
||||
print(f"🎙️ Voix française sélectionnée: {french_voice.name}")
|
||||
else:
|
||||
print("⚠️ Aucune voix française trouvée, utilisation de la voix par défaut")
|
||||
|
||||
# Configure engine settings
|
||||
engine.setProperty('rate', 160) # Slightly slower for better French pronunciation
|
||||
engine.setProperty('volume', 0.8) # Volume (0.0 to 1.0)
|
||||
|
||||
print("🎙️ pyttsx3 TTS")
|
||||
print("=" * 15)
|
||||
|
||||
# Get text from command line argument or use default
|
||||
if len(sys.argv) > 1:
|
||||
text = " ".join(sys.argv[1:]) # Join all arguments as text
|
||||
else:
|
||||
# Default completion messages in French
|
||||
completion_messages = [
|
||||
"Travail terminé !",
|
||||
"Tout est fini !",
|
||||
"Tâche accomplie !",
|
||||
"Mission accomplie !",
|
||||
"Prêt pour la prochaine tâche !",
|
||||
"C'est dans la boîte !",
|
||||
"Opération réussie !"
|
||||
]
|
||||
text = random.choice(completion_messages)
|
||||
|
||||
print(f"🎯 Text: {text}")
|
||||
print("🔊 Speaking...")
|
||||
|
||||
# Speak the text
|
||||
engine.say(text)
|
||||
engine.runAndWait()
|
||||
|
||||
print("✅ Playback complete!")
|
||||
|
||||
except ImportError:
|
||||
print("❌ Error: pyttsx3 package not installed")
|
||||
print("This script uses UV to auto-install dependencies.")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"❌ Error: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user