11from typing import Callable , Any , Dict , List
22import logging
33
4+ logger = logging .getLogger (__name__ )
5+
6+
47class PromptCorrectionLayer :
58 """
69 Observability and self-healing layer for LLM/agent pipelines.
@@ -19,23 +22,61 @@ def add_correction_hook(self, hook: Callable[[str, Dict], str]):
1922 def add_adapter_update_hook (self , hook : Callable [[str , str ], None ]):
2023 self .adapter_update_hooks .append (hook )
2124
25+ def _compute_issue_score (self , prompt : str , output : str , trace : Dict ) -> float :
26+ """
27+ Heuristic scoring function for potential issues / hallucinations.
28+ Returns a score in [0, 1], where higher means more suspicious.
29+ """
30+ text = output .lower ()
31+ score = 0.0
32+
33+ # Strong indicators
34+ strong_markers = [
35+ "[error]" , "hallucination" , "not based on real data" ,
36+ "fabricated answer" , "made this up"
37+ ]
38+ if any (marker in text for marker in strong_markers ):
39+ score += 0.7
40+
41+ # Weaker indicators based on uncertainty phrases
42+ weak_markers = [
43+ "i am not sure" , "i'm not sure" , "i do not know" ,
44+ "i don't know" , "cannot verify" , "not certain"
45+ ]
46+ if any (marker in text for marker in weak_markers ):
47+ score += 0.2
48+
49+ # If trace provides an explicit model_score / confidence, incorporate it.
50+ # Expecting trace.get("confidence") in [0, 1] where low is suspicious.
51+ confidence = trace .get ("confidence" )
52+ if isinstance (confidence , (int , float )):
53+ confidence_clamped = max (0.0 , min (1.0 , float (confidence )))
54+ score += (1.0 - confidence_clamped ) * 0.3
55+
56+ return min (score , 1.0 )
57+
2258 def monitor (self , prompt : str , output : str , trace : Dict = None ) -> str :
2359 """
2460 Monitor output for errors/hallucinations and apply corrections if needed.
61+ Uses a heuristic score instead of a single string check.
2562 """
2663 trace = trace or {}
2764 try :
28- # Example: simple hallucination check (can be replaced with real logic)
29- if "[error]" in output or "hallucination" in output .lower ():
30- self .logger .warning (f"Detected issue in output: { output } " )
65+ issue_score = self ._compute_issue_score (prompt , output , trace )
66+ threshold = trace .get ("hallucination_threshold" , 0.6 )
67+ if issue_score >= threshold :
68+ self .logger .warning (
69+ "Detected potential hallucination (score=%.2f, threshold=%.2f): %s" ,
70+ issue_score ,
71+ threshold ,
72+ output ,
73+ )
3174 for hook in self .error_hooks :
3275 hook (prompt , Exception ("Detected hallucination" ), trace )
33- # Apply correction hooks to the *output* and return corrected output.
34- # (Correction hooks are expected to take a string and trace, and return a string.)
3576 corrected_output = output
3677 for hook in self .correction_hooks :
3778 corrected_output = hook (corrected_output , trace )
38- self .logger .info (f "Corrected output: { corrected_output } " )
79+ self .logger .info ("Corrected output: %s" , corrected_output )
3980 return corrected_output
4081 return output
4182 except Exception as e :
@@ -54,15 +95,15 @@ def update_adapter(self, adapter_key: str, new_adapter_path: str):
5495if __name__ == "__main__" :
5596 pcl = PromptCorrectionLayer ()
5697 def error_logger (prompt , exc , trace ):
57- print ( f "Error detected for prompt '{ prompt } ': { exc } " )
98+ logger . error ( "Error detected for prompt '%s ': %s" , prompt , exc )
5899 def simple_correction (prompt , trace ):
59100 return prompt + " [CORRECTED]"
60101 def adapter_updater (adapter_key , new_path ):
61- print ( f "Adapter { adapter_key } updated to { new_path } " )
102+ logger . info ( "Adapter %s updated to %s" , adapter_key , new_path )
62103 pcl .add_error_hook (error_logger )
63104 pcl .add_correction_hook (simple_correction )
64105 pcl .add_adapter_update_hook (adapter_updater )
65106 # Simulate monitoring
66107 corrected_output = pcl .monitor ("What is the capital of France?" , "[error] hallucination detected" , {"step" : 1 })
67- print ("Corrected output after correction:" , corrected_output )
108+ logger . info ("Corrected output after correction: %s " , corrected_output )
68109 pcl .update_adapter ("user123" , "lora_adapter_v2" )
0 commit comments