Guide
Requirements
Section titled “Requirements”| Package | Required | Purpose |
|---|---|---|
lexigram | Yes | Core framework |
lexigram-contracts | Yes | Protocol definitions |
lexigram-cache | Optional | Feedback caching |
lexigram-sql | Optional | Feedback storage |
The Problem
Section titled “The Problem”AI systems generate outputs that need human evaluation — thumbs up/down, ratings, text corrections, or ground-truth labels. Without a structured feedback pipeline, you lose the signal needed for model improvement, quality tracking, and RLHF data collection.
lexigram-ai-feedback provides four feedback types, a pluggable storage layer, processor pipelines, and lifecycle hooks — all wired via DI.
Mental Model
Section titled “Mental Model”Feedback flows through four layers:
User/Action → FeedbackCollector → FeedbackStoreProtocol → Database/Cache ↓ FeedbackSummary (aggregates)- Types:
rating,text,correction,label— defined byFeedbackTypeenum. - Storage:
DatabaseFeedbackStore(SQL viaDatabaseProviderProtocol) orCachedFeedbackStore(write-through cache on top of DB). - Service:
FeedbackServiceimplementsFeedbackProtocolfrom contracts — high-level submit/query by trace ID. - Processors:
FeedbackProcessorRegistryroutes eachFeedbackTypeto a dedicated processor.
Core Concepts
Section titled “Core Concepts”FeedbackItem
Section titled “FeedbackItem”A FeedbackItem is the unit of feedback — a frozen dataclass with a FeedbackType, value, context dict, metadata dict, auto-generated id, and timestamp:
from lexigram.ai.feedback import FeedbackItem, FeedbackType
item = FeedbackItem( feedback_type=FeedbackType.RATING, value=4.5, context={"session_id": "sess-123", "model": "gpt-4o"}, metadata={"user_id": "user-42"},)FeedbackType
Section titled “FeedbackType”from lexigram.ai.feedback import FeedbackType
# Available typesFeedbackType.RATING # "rating" — numeric scoreFeedbackType.TEXT # "text" — free-text commentFeedbackType.CORRECTION # "correction" — original + correctedFeedbackType.LABEL # "label" — ground truth label + inputStorage Backends
Section titled “Storage Backends”The store is resolved by FeedbackProvider.boot():
- If
DatabaseProviderProtocolis registered →DatabaseFeedbackStore(auto-createsai_feedbacktable). - If both
DatabaseProviderProtocolandCacheBackendProtocolare registered →CachedFeedbackStorewrapping the DB store (write-through, 5-minute session TTL).
from lexigram.ai.feedback import DatabaseFeedbackStore, CachedFeedbackStorefrom lexigram.result import Ok
result = await store.save(feedback_item)if result.is_ok(): feedback_id = result.unwrap()Typical Usage
Section titled “Typical Usage”Submit Feedback by Trace ID
Section titled “Submit Feedback by Trace ID”from lexigram.contracts.ai.feedback import FeedbackProtocol
service: FeedbackProtocol # resolved from containerawait service.submit_feedback( trace_id="trace-abc-123", score=0.95, comment="Great response, very accurate", metadata={"user_role": "admin"},)Collect Different Types
Section titled “Collect Different Types”from lexigram.ai.feedback import FeedbackCollector
collector: FeedbackCollector
# Ratingawait collector.collect_rating(rating=5, context={"model": "gpt-4o"})
# Textawait collector.collect_text( text="The answer was too verbose", context={"query": "summarize this document"},)
# Correctionawait collector.collect_correction( original="incorrect output", corrected="correct output", context={"model_id": "123"},)
# Labelawait collector.collect_label( label="SPAM", input_data="Buy cheap watches now!", context={"classifier": "email-filter"},)Query Aggregates
Section titled “Query Aggregates”from lexigram.ai.feedback import FeedbackService
service: FeedbackServicestats = await service.get_feedback_stats( model="gpt-4o", provider="openai",)# {"total_count": 142, "average_rating": 4.2, "by_type": {"rating": 100, "text": 42}}Common Patterns
Section titled “Common Patterns”Web Middleware Integration
Section titled “Web Middleware Integration”from lexigram.ai.feedback import FeedbackMiddleware, FeedbackCollector
collector: FeedbackCollectormiddleware = FeedbackMiddleware( collector=collector, capture_inputs=True, capture_outputs=True,)# Register with your web appProcessor Pipeline
Section titled “Processor Pipeline”Built-in processors handle each FeedbackType. Custom processors can be registered:
from lexigram.ai.feedback.processors.processor_registry import ( FeedbackProcessorRegistry, FeedbackProcessor,)
class SentimentProcessor(FeedbackProcessor): async def process(self, value, context, collector): score = analyze_sentiment(value) return await collector.collect_rating(rating=score, context=context)
registry = FeedbackProcessorRegistry()registry.register("sentiment", SentimentProcessor())FeedbackContext for Scoped Operations
Section titled “FeedbackContext for Scoped Operations”from lexigram.ai.feedback import FeedbackContext, FeedbackCollector
collector: FeedbackCollectorasync with FeedbackContext(collector, operation="prediction") as ctx: result = await model.predict(input_data) ctx.set_result(result)# Context data is stored for later feedback submissionBest Practices
Section titled “Best Practices”- Use
ASYNC_PROCESSING=true(default) for non-blocking feedback pipelines. - Always provide
session_idin feedback context for session-scoped queries. - Enable
store_raw_payloadsin production for audit traceability (increases storage). - Wire
CachedFeedbackStorefor read-heavy dashboards — cache is invalidated on writes. - Use
FeedbackService.submit_feedback()for trace-id-correlated feedback from production traffic. - Register custom processors for domain-specific feedback routing.
Next Steps
Section titled “Next Steps”- How-Tos — practical recipes
- Architecture — internal design
- Configuration — every config key