Spaces:
Sleeping
Sleeping
| import React from 'react' | |
| import { Bot, User } from 'lucide-react' | |
| import EvalCard from './EvalCard.jsx' | |
| export default function ChatMessage({ message }) { | |
| const { role, content, evaluation, retryResult, retryPerformed, scoreImprovement } = message | |
| if (role === 'user') { | |
| return ( | |
| <div className="flex items-end gap-2.5 justify-end message-enter"> | |
| <div className="max-w-[75%] bg-gradient-to-br from-brand-600 to-brand-700 text-white rounded-2xl rounded-br-sm px-4 py-3 shadow-sm"> | |
| <p className="text-sm leading-relaxed">{content}</p> | |
| </div> | |
| <div className="w-8 h-8 rounded-full bg-brand-100 flex items-center justify-center flex-shrink-0"> | |
| <User size={15} className="text-brand-600" /> | |
| </div> | |
| </div> | |
| ) | |
| } | |
| if (role === 'typing') { | |
| return ( | |
| <div className="flex items-end gap-2.5 message-enter"> | |
| <div className="w-8 h-8 rounded-full bg-gradient-to-br from-brand-500 to-brand-700 flex items-center justify-center flex-shrink-0 shadow-sm"> | |
| <Bot size={15} className="text-white" /> | |
| </div> | |
| <div className="bg-white border border-slate-100 rounded-2xl rounded-bl-sm px-4 py-3 shadow-sm"> | |
| <div className="flex items-center gap-1.5"> | |
| <span className="typing-dot"></span> | |
| <span className="typing-dot"></span> | |
| <span className="typing-dot"></span> | |
| </div> | |
| </div> | |
| </div> | |
| ) | |
| } | |
| return ( | |
| <div className="flex items-start gap-2.5 message-enter"> | |
| <div className="w-8 h-8 rounded-full bg-gradient-to-br from-brand-500 to-brand-700 flex items-center justify-center flex-shrink-0 shadow-sm mt-1"> | |
| <Bot size={15} className="text-white" /> | |
| </div> | |
| <div className="flex-1 min-w-0 space-y-3"> | |
| {/* Response bubble */} | |
| <div className="bg-white border border-slate-100 rounded-2xl rounded-tl-sm px-4 py-3 shadow-sm"> | |
| <p className="text-sm text-slate-700 leading-relaxed">{content}</p> | |
| </div> | |
| {/* Evaluation card */} | |
| {evaluation && ( | |
| <EvalCard evaluation={evaluation} /> | |
| )} | |
| {/* Retry result */} | |
| {retryPerformed && retryResult && ( | |
| <div className="space-y-2"> | |
| <div className="flex items-center gap-2"> | |
| <div className="h-px flex-1 bg-slate-200" /> | |
| <span className="text-xs text-slate-400 font-medium px-2 bg-slate-50 rounded-full border border-slate-200"> | |
| ↻ Auto-Retry with Optimized Prompt | |
| </span> | |
| <div className="h-px flex-1 bg-slate-200" /> | |
| </div> | |
| {/* Improved response */} | |
| {retryResult.response && ( | |
| <div className="bg-brand-50 border border-brand-200 rounded-2xl px-4 py-3"> | |
| <div className="flex items-center gap-1.5 mb-2"> | |
| <span className="text-xs font-bold text-brand-700">Optimized Response</span> | |
| <span className="text-xs bg-brand-100 text-brand-600 px-2 py-0.5 rounded-full"> | |
| {retryResult.prompt_version || 'optimized'} prompt | |
| </span> | |
| </div> | |
| <p className="text-sm text-slate-700 leading-relaxed">{retryResult.response}</p> | |
| </div> | |
| )} | |
| {/* Score improvement badge */} | |
| {scoreImprovement !== undefined && scoreImprovement !== null && ( | |
| <div className="flex items-center gap-2"> | |
| <div className={`flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-bold ${ | |
| scoreImprovement > 0 ? 'bg-success-50 text-success-700 border border-success-500/20' : 'bg-slate-100 text-slate-600' | |
| }`}> | |
| {scoreImprovement > 0 ? '↑' : '→'} Score {scoreImprovement > 0 ? '+' : ''}{Math.round(scoreImprovement * 100)}% | |
| </div> | |
| </div> | |
| )} | |
| <EvalCard evaluation={retryResult} isRetry /> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| ) | |
| } | |