diff --git a/kalibr/__init__.py b/kalibr/__init__.py index 587a86a..e2c5ae7 100644 --- a/kalibr/__init__.py +++ b/kalibr/__init__.py @@ -103,7 +103,7 @@ def call_openai(prompt): from .feedback import ( KalibrFeedback, track_run, user_rejected, user_accepted, get_feedback, classify_satisfaction, classify_satisfaction_async, emit_signal, - report_pipeline, report_user_turn, report_action, request_feedback, submit_feedback, + report_pipeline, report_user_turn, report_action, ) if os.getenv("KALIBR_AUTO_INSTRUMENT", "true").lower() == "true": @@ -204,6 +204,4 @@ def call_openai(prompt): "report_pipeline", "report_user_turn", "report_action", - "request_feedback", - "submit_feedback", ] diff --git a/kalibr/feedback.py b/kalibr/feedback.py index 4c7a34e..9c9ee47 100644 --- a/kalibr/feedback.py +++ b/kalibr/feedback.py @@ -658,78 +658,6 @@ def _send(): logger.warning("report_action failed: %s", e) -_DIMENSION_DEFS = { - "length": {"label": "Length", "options": [-1, 0, 1], "labels": ["Too long", "Good", "Too short"]}, - "tone": {"label": "Tone", "options": [-1, 0, 1], "labels": ["Too casual", "Good", "Too formal"]}, - "content": {"label": "Content", "options": [-1, 0, 1], "labels": ["Off-topic", "Good", "Missing info"]}, - "factuality": {"label": "Factuality", "options": [-1, 0, 1], "labels": ["Inaccurate", "Good", "Unsure"]}, - "format": {"label": "Format", "options": [-1, 0, 1], "labels": ["Poor format", "Good", "Needs restructuring"]}, -} - - -def request_feedback( - dimensions: Optional[list] = None, -) -> dict: - """ - SDK-only. Returns a structured feedback form dict the developer renders - to their users. No network call. - """ - if dimensions is None: - dimensions = ["length", "tone", "content", "factuality", "format"] - return { - "question": "How was this response?", - "dimensions": { - d: _DIMENSION_DEFS.get(d, {"label": d.title(), "options": [-1, 0, 1], "labels": ["Bad", "Good", "Needs work"]}) - for d in dimensions - }, - } - - -def submit_feedback(session_id: str, ratings: dict) -> None: - """ - Submit explicit user feedback. Writes ONE signal row PER dimension - with a non-zero rating. Fire-and-forget. - - ratings: {"length": -1, "tone": 0, "content": 1, ...} - Values: -1 (negative), 0 (neutral — skipped), 1 (positive) - """ - try: - session = _read_session(session_id) - if session is None: - return - - api_key, tenant_id, base_url = _fb_config() - if not api_key or not tenant_id: - return - - trace_id = session.get("trace_id", "") - goal_val = session.get("goal", "") - - def _send_all(): - try: - for dimension, rating in ratings.items(): - if rating == 0: - continue - strength = 0.0 if rating == -1 else 1.0 - payload = { - "trace_id": trace_id, - "signal_type": "explicit_feedback", - "signal_source": "explicit_feedback", - "strength": strength, - "confidence": 1.0, - "dimension": dimension, - "goal": goal_val, - "session_id": session_id, - } - _emit_signal_http(base_url, api_key, tenant_id, payload) - except Exception: - pass - - threading.Thread(target=_send_all, daemon=True).start() - except Exception as e: - logger.warning("submit_feedback failed: %s", e) - - def emit_signal( signal_type: str, strength: float = 0.5, diff --git a/pyproject.toml b/pyproject.toml index 3e65916..ce36f42 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "kalibr" -version = "1.12.0" +version = "1.12.1" description = "Outcome-aware LLM routing for production AI agents. Routes between models, tools, and parameters based on real success signals using Thompson Sampling. Automatic fallback, cost optimization, and continuous learning — no redeploy required." authors = [{name = "Kalibr Team", email = "support@kalibr.systems"}] readme = "README.md"