Skip to main content

Overview

User feedback (thumbs up/down, corrections) is essential for improving your AI system. Artanis makes it easy to link feedback to specific traces so you can understand what went wrong and build better evaluation datasets.

Complete Integration Flow

1

Backend: Return Trace ID

Include the trace ID in your API response
2

Frontend: Store Trace ID

Save the trace ID with the displayed message
3

Frontend: Collect Feedback

When user provides feedback, send it with the trace ID
4

Backend: Record in Artanis

Forward feedback to Artanis with the trace ID

Step 1: Backend - Return Trace ID

Include the trace ID in your API response:
from flask import Flask, request, jsonify
from artanis import Artanis

app = Flask(__name__)
artanis = Artanis()

@app.post("/api/ask")
def ask():
    data = request.json
    user_id = data.get("user_id")
    question = data.get("question")

    # Create trace with user context
    trace = artanis.trace("ask", user_id=user_id)

    # Process question
    response = process_question(question, trace)

    # Return trace ID to frontend
    return jsonify({
        "answer": response,
        "trace_id": trace.id,  # ← Include this
    })

Step 2: Frontend - Store Trace ID

Store the trace ID alongside the displayed message:
// Message interface
interface Message {
  id: string;
  text: string;
  traceId: string; // ← Store this from API response
  timestamp: Date;
  isUser: boolean;
}

// When displaying AI response
async function askQuestion(question: string) {
  const response = await fetch("/api/ask", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ question, userId: currentUser.id }),
  });

  const data = await response.json();

  // Store message with trace ID
  const message: Message = {
    id: generateId(),
    text: data.answer,
    traceId: data.traceId, // ← Store for later
    timestamp: new Date(),
    isUser: false,
  };

  addMessageToUI(message);
}

Step 3: Frontend - Collect Feedback

When user provides feedback, send it to your backend:
// Feedback UI component
function FeedbackButtons({ message }: { message: Message }) {
    async function handleFeedback(isPositive: boolean) {
        await fetch("/api/feedback", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
                trace_id: message.traceId,
                rating: isPositive ? "positive" : "negative",
            }),
        });

        // Show confirmation
        showToast("Feedback submitted!");
    }

    return (
        <div>
            <button onClick={() => handleFeedback(true)}>👍</button>
            <button onClick={() => handleFeedback(false)}>👎</button>
        </div>
    );
}

// With comment/correction
async function submitDetailedFeedback(
    traceId: string,
    isPositive: boolean,
    comment?: string,
    correction?: string
) {
    await fetch("/api/feedback", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
            trace_id: traceId,
            rating: isPositive ? "positive" : "negative",
            comment,
            correction: correction ? { answer: correction } : undefined,
        }),
    });
}

Step 4: Backend - Record in Artanis

Forward feedback to Artanis:
@app.post("/api/feedback")
def submit_feedback():
    data = request.json

    # Record feedback in Artanis
    artanis.feedback(
        trace_id=data["trace_id"],
        rating=data["rating"],
        comment=data.get("comment"),
        correction=data.get("correction"),
    )

    return jsonify({"status": "ok"})

Feedback Types

Simple positive/negative feedback:
artanis.feedback(
    trace_id="trace_abc123",
    rating="positive"  # or "negative"
)
Numeric rating from 0 to 1:
artanis.feedback(
    trace_id="trace_abc123",
    rating=0.8  # 0.0 to 1.0
)
User comments explaining the feedback:
artanis.feedback(
    trace_id="trace_abc123",
    rating="negative",
    comment="The refund policy information is outdated"
)
What the correct output should have been:
artanis.feedback(
    trace_id="trace_abc123",
    rating="negative",
    correction={
        "answer": "Our refund policy is 30 days, not 14 days."
    },
    comment="User corrected the refund window"
)

Complete React Example

Here’s a complete React component with feedback:
import { useState } from "react";

interface Message {
    id: string;
    text: string;
    traceId?: string;
    isUser: boolean;
}

function ChatInterface() {
    const [messages, setMessages] = useState<Message[]>([]);
    const [input, setInput] = useState("");

    async function sendMessage() {
        // Add user message
        const userMessage: Message = {
            id: generateId(),
            text: input,
            isUser: true,
        };
        setMessages([...messages, userMessage]);

        // Get AI response
        const response = await fetch("/api/ask", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ question: input }),
        });

        const data = await response.json();

        // Add AI message with trace ID
        const aiMessage: Message = {
            id: generateId(),
            text: data.answer,
            traceId: data.traceId,  // Store trace ID
            isUser: false,
        };
        setMessages([...messages, userMessage, aiMessage]);
        setInput("");
    }

    async function submitFeedback(message: Message, isPositive: boolean) {
        if (!message.traceId) return;

        await fetch("/api/feedback", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
                trace_id: message.traceId,
                rating: isPositive ? "positive" : "negative",
            }),
        });

        alert("Feedback submitted!");
    }

    return (
        <div>
            <div className="messages">
                {messages.map((msg) => (
                    <div key={msg.id} className={msg.isUser ? "user" : "ai"}>
                        <p>{msg.text}</p>
                        {!msg.isUser && msg.traceId && (
                            <div className="feedback">
                                <button onClick={() => submitFeedback(msg, true)}>
                                    👍
                                </button>
                                <button onClick={() => submitFeedback(msg, false)}>
                                    👎
                                </button>
                            </div>
                        )}
                    </div>
                ))}
            </div>
            <input
                value={input}
                onChange={(e) => setInput(e.target.value)}
                onKeyDown={(e) => e.key === "Enter" && sendMessage()}
            />
        </div>
    );
}

Viewing Feedback in Dashboard

Once feedback is recorded, you can view it in the Artanis Dashboard:
  1. Filter traces by rating (rating:negative)
  2. See feedback comments and corrections
  3. Export traces with feedback for evaluation datasets
  4. Track feedback trends over time

Best Practices

Always Return Trace ID

Include trace ID in every API response that generates content

Make Feedback Easy

Add thumbs up/down buttons directly on AI responses

Collect Context

Ask users to explain negative feedback

Show Appreciation

Thank users for feedback to encourage more

Next Steps