Initial commit: 25 scripts Python sauvegardés
Date: 2026-08-28 11:43:34 EDT
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Pipecat Bot Template — OpenAILLMService avec API Hermes
|
||||
========================================================
|
||||
Template minimal pour un bot texte via WebSocket.
|
||||
Adapté de ~/workspace/jarvis-pipecat/bot.py
|
||||
|
||||
Prérequis: pipecat-ai[websocket]>=1.4.0, openai, uvicorn, websockets
|
||||
"""
|
||||
|
||||
import json, os, subprocess, sys
|
||||
from fastapi import FastAPI, WebSocket
|
||||
from fastapi.responses import HTMLResponse
|
||||
import uvicorn
|
||||
|
||||
# ⚠️ Pipecat 1.4.0 : utiliser `import module as m` (from-import cassé)
|
||||
import pipecat.frames.frames as pframes
|
||||
from pipecat.pipeline.pipeline import Pipeline
|
||||
from pipecat.pipeline.runner import PipelineRunner
|
||||
from pipecat.pipeline.task import PipelineTask
|
||||
from pipecat.processors.frame_processor import FrameProcessor, FrameDirection
|
||||
from pipecat.services.openai.llm import OpenAILLMService
|
||||
from pipecat.transports.websocket.fastapi import FastAPIWebsocketParams, FastAPIWebsocketTransport
|
||||
|
||||
# ─── Config ──────────────────────────────────────────────────
|
||||
PORT = int(os.environ.get("BOT_PORT", "7081"))
|
||||
HERMES_URL = os.environ.get("HERMES_API_URL", "http://localhost:8642/v1")
|
||||
HERMES_KEY = os.environ.get("HERMES_API_KEY", "")
|
||||
SYSTEM_PROMPT = "Tu es un assistant vocal concis. Parle en français, 3 phrases max."
|
||||
|
||||
|
||||
# ─── Processeur custom : texte → LLMMessagesFrame ────────────
|
||||
class TextToLLMProcessor(FrameProcessor):
|
||||
"""Remplace le context aggregator (buggé en 1.4.0)."""
|
||||
|
||||
def __init__(self, system_prompt: str):
|
||||
super().__init__()
|
||||
self._messages = [{"role": "system", "content": system_prompt}]
|
||||
|
||||
async def process_frame(self, frame, direction):
|
||||
await self.push_frame(frame, direction)
|
||||
if isinstance(frame, pframes.InputTransportMessageFrame):
|
||||
text = frame.message
|
||||
if isinstance(text, str) and text.strip():
|
||||
self._messages.append({"role": "user", "content": text})
|
||||
if len(self._messages) > 21:
|
||||
self._messages = [self._messages[0]] + self._messages[-20:]
|
||||
await self.push_frame(pframes.LLMMessagesFrame(messages=list(self._messages)))
|
||||
elif isinstance(frame, pframes.LLMFullResponseStartFrame):
|
||||
self._response_text = ""
|
||||
elif isinstance(frame, pframes.TextFrame):
|
||||
if hasattr(self, '_response_text'):
|
||||
self._response_text += frame.text
|
||||
elif isinstance(frame, pframes.LLMFullResponseEndFrame):
|
||||
if hasattr(self, '_response_text') and self._response_text.strip():
|
||||
self._messages.append({"role": "assistant", "content": self._response_text.strip()})
|
||||
del self._response_text
|
||||
|
||||
|
||||
# ─── App ─────────────────────────────────────────────────────
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.websocket("/ws")
|
||||
async def ws_endpoint(websocket: WebSocket):
|
||||
transport = FastAPIWebsocketTransport(
|
||||
websocket=websocket,
|
||||
params=FastAPIWebsocketParams(add_wav_header=False, session_timeout=None),
|
||||
)
|
||||
llm = OpenAILLMService(
|
||||
api_key=HERMES_KEY,
|
||||
base_url=HERMES_URL,
|
||||
settings=OpenAILLMService.Settings(model="Hermes Agent", temperature=0.8, max_tokens=300, system_instruction=SYSTEM_PROMPT),
|
||||
)
|
||||
proc = TextToLLMProcessor(SYSTEM_PROMPT)
|
||||
pipeline = Pipeline(processors=[transport.input(), proc, llm, transport.output()])
|
||||
task = PipelineTask(pipeline)
|
||||
runner = PipelineRunner()
|
||||
await runner.run(task)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn.run(app, host="0.0.0.0", port=PORT)
|
||||
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Scan ~/.hermes/skills/ for corrupted .py scripts.
|
||||
|
||||
Usage: python corruption-scanner.py [--fix-dir /path/to/output]
|
||||
Output: JSON summary of clean vs corrupted files.
|
||||
"""
|
||||
import json, os, sys
|
||||
from pathlib import Path
|
||||
|
||||
def scan_skills(base_dir):
|
||||
results = {"clean": [], "corrupted": [], "skipped": []}
|
||||
|
||||
for root, dirs, files in os.walk(base_dir):
|
||||
if '__pycache__' in root or 'venv' in root:
|
||||
continue
|
||||
|
||||
for fname in files:
|
||||
if not fname.endswith('.py'):
|
||||
continue
|
||||
|
||||
fpath = os.path.join(root, fname)
|
||||
size = os.path.getsize(fpath)
|
||||
|
||||
# Skip empty __init__.py (normal)
|
||||
if fname == '__init__.py' and size <= 50:
|
||||
results["skipped"].append({"path": fpath, "reason": "empty __init__.py"})
|
||||
continue
|
||||
|
||||
try:
|
||||
with open(fpath, 'r') as f:
|
||||
content = f.read(1000)
|
||||
|
||||
first_line = content.strip().split('\n')[0].lower()
|
||||
|
||||
if '% partial rewrite' in first_line[:200] or 'latex' in first_line[:200]:
|
||||
results["corrupted"].append({
|
||||
"path": fpath,
|
||||
"size": size,
|
||||
"type": "latex_contamination"
|
||||
})
|
||||
elif first_line.startswith('%pdf') or '%PDF' in first_line[:20]:
|
||||
results["corrupted"].append({
|
||||
"path": fpath,
|
||||
"size": size,
|
||||
"type": "pdf_binary"
|
||||
})
|
||||
elif len(content) > 200000:
|
||||
results["corrupted"].append({
|
||||
"path": fpath,
|
||||
"size": size,
|
||||
"type": "oversized"
|
||||
})
|
||||
else:
|
||||
results["clean"].append({"path": fpath, "size": size})
|
||||
|
||||
except UnicodeDecodeError:
|
||||
results["skipped"].append({"path": fpath, "reason": "binary file"})
|
||||
except Exception as e:
|
||||
results["skipped"].append({"path": fpath, "reason": str(e)})
|
||||
|
||||
return results
|
||||
|
||||
if __name__ == '__main__':
|
||||
base = os.environ.get('HERMES_HOME', str(Path.home() / '.hermes'))
|
||||
skills_dir = os.path.join(base, 'skills')
|
||||
|
||||
fix_dir = None
|
||||
args = sys.argv[1:]
|
||||
if '--fix-dir' in args:
|
||||
idx = args.index('--fix-dir')
|
||||
if idx + 1 < len(args):
|
||||
fix_dir = args[idx + 1]
|
||||
|
||||
results = scan_skills(skills_dir)
|
||||
|
||||
print(json.dumps(results, indent=2, ensure_ascii=False))
|
||||
|
||||
# Summary
|
||||
print(f"\n{'='*60}")
|
||||
print(f"Scan complete:")
|
||||
print(f" Clean: {len(results['clean'])}")
|
||||
print(f" Corrupted: {len(results['corrupted'])}")
|
||||
print(f" Skipped: {len(results['skipped'])}")
|
||||
|
||||
if results['corrupted']:
|
||||
print(f"\nCorrupted files:")
|
||||
for f in results['corrupted']:
|
||||
print(f" ❌ {f['path']} ({f['size']:,} bytes) - {f['type']}")
|
||||
Reference in New Issue
Block a user