|
1 | 1 | 'use client'; |
2 | 2 |
|
3 | 3 | import { useState, useEffect } from 'react'; |
4 | | -import { Copy, Check } from 'lucide-react'; |
| 4 | +import { Copy, Check, RotateCcw } from 'lucide-react'; |
5 | 5 |
|
6 | 6 | export function Terminal() { |
7 | 7 | const [terminalStep, setTerminalStep] = useState(0); |
8 | 8 | const [copied, setCopied] = useState(false); |
9 | 9 | const terminalSteps = [ |
10 | | - 'conda create -n collabllm python=3.10', |
11 | | - 'conda activate collabllm', |
12 | | - 'pip install collabllm', |
13 | | - '', |
14 | | - 'git clone https://github.com/Wuyxin/collabllm.git', |
15 | | - 'python -m scripts.engine.build_dataset <...>', |
16 | | - 'python -m scripts.train.{sft/*_dpo/ppo} <...>', |
| 10 | + { line: 'Generate 10 responses to the user query. Each response should be approximately 200 words.', showPrompt: true }, |
| 11 | + { line: '', showPrompt: false }, |
| 12 | + { line: 'Return the responses in JSON format with the key: "responses" (list of dicts). Each dictionary must include:', showPrompt: false }, |
| 13 | + { line: '- \'text\': the response string only (no explanation or extra text).', showPrompt: false }, |
| 14 | + { line: '- \'probability\': the estimated probability from 0.0 to 1.0 of this response given the input prompt (relative to the full distribution).', showPrompt: false }, |
| 15 | + { line: '', showPrompt: false }, |
| 16 | + { line: 'Randomly sample the responses from the full distribution. Return ONLY the JSON object, with no additional explanations or text.', showPrompt: false }, |
| 17 | + { line: '', showPrompt: false }, |
| 18 | + { line: '<user_query>Write a short story about a bear.</user_query>', showPrompt: true }, |
17 | 19 | ]; |
18 | 20 |
|
19 | | - useEffect(() => { |
20 | | - const timer = setTimeout(() => { |
21 | | - setTerminalStep((prev) => |
22 | | - prev < terminalSteps.length - 1 ? prev + 1 : prev |
23 | | - ); |
24 | | - }, 500); |
| 21 | + const fullPrompt = terminalSteps.map(step => step.line).join('\n'); |
25 | 22 |
|
26 | | - return () => clearTimeout(timer); |
27 | | - }, [terminalStep]); |
| 23 | + useEffect(() => { |
| 24 | + if (terminalStep < terminalSteps.length) { |
| 25 | + const timer = setTimeout(() => { |
| 26 | + setTerminalStep(prev => prev + 1); |
| 27 | + }, 800); |
| 28 | + return () => clearTimeout(timer); |
| 29 | + } |
| 30 | + }, [terminalStep, terminalSteps.length]); |
28 | 31 |
|
29 | 32 | const copyToClipboard = () => { |
30 | | - navigator.clipboard.writeText(terminalSteps.join('\n')); |
| 33 | + navigator.clipboard.writeText(fullPrompt); |
31 | 34 | setCopied(true); |
32 | 35 | setTimeout(() => setCopied(false), 2000); |
33 | 36 | }; |
34 | 37 |
|
| 38 | + const restartAnimation = () => { |
| 39 | + setTerminalStep(0); |
| 40 | + }; |
| 41 | + |
35 | 42 | return ( |
36 | | - <div className="w-full rounded-lg shadow-lg overflow-hidden bg-gray-900 text-white font-mono text-sm relative"> |
| 43 | + <div className="w-full rounded-lg shadow-lg overflow-hidden bg-gray-900 text-white font-mono text-sm relative min-h-[400px]"> |
37 | 44 | <div className="p-4"> |
38 | 45 | <div className="flex justify-between items-center mb-4"> |
39 | 46 | <div className="flex space-x-2"> |
40 | 47 | <div className="w-3 h-3 rounded-full bg-red-500"></div> |
41 | 48 | <div className="w-3 h-3 rounded-full bg-yellow-500"></div> |
42 | 49 | <div className="w-3 h-3 rounded-full bg-green-500"></div> |
43 | 50 | </div> |
44 | | - <button |
45 | | - onClick={copyToClipboard} |
46 | | - className="text-gray-400 hover:text-white transition-colors" |
47 | | - aria-label="Copy to clipboard" |
48 | | - > |
49 | | - {copied ? ( |
50 | | - <Check className="h-5 w-5" /> |
51 | | - ) : ( |
52 | | - <Copy className="h-5 w-5" /> |
53 | | - )} |
54 | | - </button> |
| 51 | + <div className="flex space-x-2"> |
| 52 | + <button |
| 53 | + onClick={restartAnimation} |
| 54 | + className="text-gray-400 hover:text-white transition-colors" |
| 55 | + aria-label="Restart animation" |
| 56 | + > |
| 57 | + <RotateCcw className="h-5 w-5" /> |
| 58 | + </button> |
| 59 | + <button |
| 60 | + onClick={copyToClipboard} |
| 61 | + className="text-gray-400 hover:text-white transition-colors" |
| 62 | + aria-label="Copy to clipboard" |
| 63 | + > |
| 64 | + {copied ? ( |
| 65 | + <Check className="h-5 w-5" /> |
| 66 | + ) : ( |
| 67 | + <Copy className="h-5 w-5" /> |
| 68 | + )} |
| 69 | + </button> |
| 70 | + </div> |
55 | 71 | </div> |
56 | 72 | <div className="space-y-2"> |
57 | 73 | {terminalSteps.map((step, index) => ( |
58 | 74 | <div |
59 | 75 | key={index} |
60 | 76 | className={`${index > terminalStep ? 'opacity-0' : 'opacity-100'} transition-opacity duration-300`} |
61 | 77 | > |
62 | | - <span className="text-green-400">$</span> {step} |
| 78 | + {step.showPrompt && <span className="text-green-400">$ </span>} |
| 79 | + {step.line} |
63 | 80 | </div> |
64 | 81 | ))} |
65 | 82 | </div> |
|
0 commit comments