mirror of
https://github.com/schwartz1375/genai-security-training
synced 2026-08-09 13:08:41 +00:00
66 lines
1.8 KiB
Python
66 lines
1.8 KiB
Python
"""Local LLM adapter for Module 9 agent decisions."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import re
|
|
from dataclasses import dataclass
|
|
from typing import Any, Dict
|
|
|
|
|
|
@dataclass
|
|
class LLMConfig:
|
|
model_name: str = "distilgpt2"
|
|
max_new_tokens: int = 120
|
|
temperature: float = 0.2
|
|
|
|
|
|
class LocalLLMAdapter:
|
|
def __init__(self, config: LLMConfig | None = None):
|
|
self.config = config or LLMConfig()
|
|
self._generator = None
|
|
self._load_error = None
|
|
try:
|
|
from transformers import pipeline
|
|
|
|
self._generator = pipeline("text-generation", model=self.config.model_name)
|
|
except Exception as exc:
|
|
self._load_error = str(exc)
|
|
|
|
@property
|
|
def available(self) -> bool:
|
|
return self._generator is not None
|
|
|
|
def generate(self, prompt: str) -> str:
|
|
if not self.available:
|
|
return ""
|
|
pad_token_id = None
|
|
try:
|
|
pad_token_id = self._generator.tokenizer.eos_token_id
|
|
except Exception:
|
|
pad_token_id = None
|
|
out = self._generator(
|
|
prompt,
|
|
max_new_tokens=self.config.max_new_tokens,
|
|
temperature=self.config.temperature,
|
|
do_sample=self.config.temperature > 0,
|
|
truncation=True,
|
|
pad_token_id=pad_token_id,
|
|
)
|
|
return out[0]["generated_text"][len(prompt) :].strip()
|
|
|
|
def generate_json(self, prompt: str, fallback: Dict[str, Any]) -> Dict[str, Any]:
|
|
text = self.generate(prompt)
|
|
if not text:
|
|
return fallback
|
|
|
|
# Prefer explicit JSON object in the output.
|
|
match = re.search(r"\{.*\}", text, flags=re.DOTALL)
|
|
if not match:
|
|
return fallback
|
|
candidate = match.group(0)
|
|
try:
|
|
return json.loads(candidate)
|
|
except Exception:
|
|
return fallback
|