사용자 피드백
사용자 피드백 (User Feedback)
사용자 피드백은 우리 AI가 실제로 사용자에게 도움이 됐는지 측정하는 방법이에요. 품질 이슈를 찾고, 더 나은 평가 데이터셋을 만들고, 실제 사용자 경험을 바탕으로 개선 우선순위를 정하는 데 쓸 수 있어요. Langfuse에서 피드백은 scores로 캡처되어 트레이스에 연결돼요.
출처: 문서
본문
피드백 유형
명시적 피드백 (Explicit Feedback)
사용자가 좋아요/싫어요(thumbs up/down), 별점, 또는 댓글로 응답을 직접 평가해요.
| 장점 | 단점 | | 만족도에 대한 명확한 신호 | 낮은 응답률 | | 구현이 간단함 | 불만족한 사용자가 응답할 가능성이 더 높음 | | 조치를 취하기 쉬움 | 사용자의 행동이 필요함 |
암묵적 피드백 (Implicit Feedback)
읽는 데 쓴 시간, 출력 복사, 제안 수락, 쿼리 재시도 같은 사용자 행동에서 파생돼요.
| 장점 | 단점 | | 모든 인터랙션에서 높은 볼륨 | 구현하기 더 어려움 | | 사용자 노력이 필요 없음 | 모호한 신호 | | 실제 사용을 반영함 | 해석이 필요함 |
둘 모두 Langfuse에서 scores로 작동해요. 점수로 트레이스를 필터링하고, annotation queues를 만들거나, 피드백을 자동 평가의 ground truth로 사용할 수 있어요.
빠른 시작
이 예시는 Next.js와 AI SDK로 만든 챗봇에서 명시적 사용자 피드백을 수집하는 방법을 보여줘요. 전체 구현은 Langfuse Example 저장소에서 찾을 수 있어요.
1. 프론트엔드에 트레이스 ID 반환하기
백엔드가 트레이스 ID를 보내면 프론트엔드가 피드백을 트레이스에 연결할 수 있어요.
// app/api/chat/route.ts
import { getActiveTraceId } from "@langfuse/tracing";
export const POST = observe(async (req: Request) => {
const result = streamText({
model: openai('gpt-4o-mini'),
messages: convertToModelMessages(messages),
});
return result.toUIMessageStreamResponse({
generateMessageId: () => getActiveTraceId() || "",
});
});
2. 프론트엔드에서 피드백 수집하기
Langfuse Browser SDK를 사용해 피드백을 score로 보내요. 브라우저 SDK는 공개 키(public key)만 필요해요. 프론트엔드 코드에 Langfuse secret key를 절대 노출하면 안 돼요.
import { LangfuseBrowserClient } from "@langfuse/browser";
const langfuse = new LangfuseBrowserClient({
publicKey: process.env.NEXT_PUBLIC_LANGFUSE_PUBLIC_KEY!,
baseUrl: process.env.NEXT_PUBLIC_LANGFUSE_BASE_URL,
});
function FeedbackButtons({ messageId }: { messageId: string }) {
const handleFeedback = async (value: number, comment?: string) => {
await langfuse.score({
traceId: messageId,
id: `user-feedback-${messageId}`,
name: "user-feedback",
value: value, // 1 for positive, 0 for negative
dataType: "BOOLEAN",
comment: comment,
});
};
return (
<div>
<button onClick={() => handleFeedback(1)}>:+1:</button>
<button onClick={() => handleFeedback(0)}>:-1:</button>
</div>
);
}
3. Langfuse에서 피드백 보기
피드백은 트레이스 위의 score로 나타나요. user-feedback < 1로 필터링하면 낮은 평가를 받은 응답을 찾을 수 있어요.
서버 측 피드백
사용자 설문이나 후속 인터랙션 이후처럼 필요할 때 백엔드에서 피드백을 기록할 수도 있어요. 티켓 해결이나 성공적인 작업 완료 같은 암묵적 피드백 신호를 로깅하는 데도 쓸 수 있어요.
from langfuse import get_client
langfuse = get_client()
# Check if customer support ticket was resolved successfully
ticket_status = checkIfTicketClosed(ticket_id="ticket-456")
if ticket_status.is_closed:
langfuse.create_score(
trace_id=ticket_status.trace_id,
name="ticket-resolution",
value=1,
comment=f"Ticket closed successfully after {ticket_status.resolution_time}"
)
else:
langfuse.create_score(
trace_id=ticket_status.trace_id,
name="ticket-resolution",
value=0,
comment=f"Ticket escalated to human agent"
)
LLM-as-a-Judge로 암묵적 피드백 얻기
LLM을 judge로 사용해 사용자 감정, 만족도, 참여도 같은 품질 지표를 모든 응답에서 자동으로 평가할 수 있어요. 이렇게 하면 사용자 개입 없이 대규모 피드백을 수집할 수 있어요.
구현 패턴과 예시는 LLM-as-a-Judge Evaluators 문서를 참고하세요.
예시 앱
user-feedback example은 완전한 Next.js 구현을 보여줘요:
- OpenTelemetry 트레이싱
- 선택적 댓글이 있는 좋아요/싫어요
- 대화 전반의 세션 추적
관련 자료
신호 선택부터 조치까지의 전체 과정을 알아보려면 사용자 피드백 루프 설정 가이드를 참고하세요. 수집한 피드백을 회귀 테스트와 judge 보정 데이터로 바꾸려면 사용자 피드백을 평가 데이터셋으로 전환하는 방법을 참고하세요.
더 알아보기 (Learn more)
- 출처 문서: 사용자 피드백 (User Feedback)