참고소스 수정본
This commit is contained in:
71
참고/guardrails-main/guardrails/call_tracing/trace_handler.py
Normal file
71
참고/guardrails-main/guardrails/call_tracing/trace_handler.py
Normal file
@@ -0,0 +1,71 @@
|
||||
"""trace_handler.py.
|
||||
|
||||
A set of tools to track the behavior of guards, specifically with the intent of
|
||||
collating the pre/post validation text and timing of guard calls. Uses a singleton to
|
||||
share write access to a SQLite database across threads.
|
||||
|
||||
By default, logs will be created in a temporary directory. This can be overridden by
|
||||
setting GUARDRAILS_LOG_FILE_PATH in the environment. tracehandler.log_path will give
|
||||
the full path of the current log file.
|
||||
|
||||
# Reading logs (basic):
|
||||
>>> reader = TraceHandler.get_reader()
|
||||
>>> for t in reader.tail_logs():
|
||||
>>> print(t)
|
||||
|
||||
# Reading logs (advanced):
|
||||
>>> reader = TraceHandler.get_reader()
|
||||
>>> reader.db.execute("SELECT * FROM guard_logs;") # Arbitrary SQL support.
|
||||
|
||||
# Saving logs
|
||||
>>> writer = TraceHandler()
|
||||
>>> writer.log(
|
||||
>>> "my_guard_name", 0.0, 1.0, "Raw LLM Output Text", "Sanitized", "exception?"
|
||||
>>> )
|
||||
"""
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
import threading
|
||||
|
||||
from guardrails.call_tracing.sqlite_trace_handler import SQLiteTraceHandler
|
||||
from guardrails.call_tracing.tracer_mixin import TracerMixin
|
||||
|
||||
# TODO: We should read this from guardrailsrc.
|
||||
LOG_FILENAME = "guardrails_calls.db"
|
||||
LOGFILE_PATH = os.environ.get(
|
||||
"GUARDRAILS_LOG_FILE_PATH", # Document this environment variable.
|
||||
os.path.join(tempfile.gettempdir(), LOG_FILENAME),
|
||||
)
|
||||
|
||||
|
||||
class TraceHandler(TracerMixin):
|
||||
"""TraceHandler wraps the internal _SQLiteTraceHandler to make it multi-
|
||||
thread safe.
|
||||
|
||||
Coupled with some write ahead journaling in the _SyncTrace internal,
|
||||
we have a faux-multi-write multi-read interface for SQLite.
|
||||
"""
|
||||
|
||||
_instance = None
|
||||
_lock = threading.Lock()
|
||||
|
||||
def __new__(cls):
|
||||
if cls._instance is None:
|
||||
# We run two 'if None' checks so we don't have to call the mutex check for
|
||||
# the cases where there's obviously no handler. Only do a check if there
|
||||
# MIGHT not be a handler instantiated.
|
||||
with cls._lock:
|
||||
if cls._instance is None:
|
||||
cls._instance = cls._create()
|
||||
return cls._instance
|
||||
|
||||
@classmethod
|
||||
def _create(cls) -> TracerMixin: # type: ignore
|
||||
return SQLiteTraceHandler(LOGFILE_PATH, read_mode=False) # type: ignore
|
||||
# To disable logging:
|
||||
# return _BaseTraceHandler(LOGFILE_PATH, read_mode=False)
|
||||
|
||||
@classmethod
|
||||
def get_reader(cls) -> TracerMixin: # type: ignore
|
||||
return SQLiteTraceHandler(LOGFILE_PATH, read_mode=True) # type: ignore
|
||||
Reference in New Issue
Block a user