ElisaTrippetti commited on
Commit
259107b
Β·
verified Β·
1 Parent(s): a184f29

Upload 5 files

Browse files
Files changed (4) hide show
  1. README.md +11 -13
  2. chat-engine.jsx +42 -12
  3. debug-panel.jsx +3 -3
  4. variant-terminal.jsx +3 -3
README.md CHANGED
@@ -1,11 +1,10 @@
1
  ---
2
- title: Fetch Pup
3
- emoji: 🐢
4
  colorFrom: gray
5
  colorTo: yellow
6
  sdk: static
7
  pinned: false
8
- short_description: Dog-loving baseline chatbot. A zero-backend static demo
9
  ---
10
 
11
  # This is Fetch
@@ -17,21 +16,20 @@ Space. It runs entirely in the browser β€” no GPU, no Python, no backend.
17
 
18
  ## How it works
19
 
20
- Fetch answers using the same logic as the original Python reference:
21
 
 
 
22
  - A small **keyword lookup** table (dogs, breeds, care, trivia, reactions).
23
  If the user's question contains a known keyword, the matching fact is
24
  returned verbatim.
25
- - Three **fallback replies** cover the "I don't know" case.
26
- - **Four-turn context** is kept in memory for the session.
27
 
28
- The generative path (BlenderBot-400M-distill in the original, or an
29
- LLM-backed helper in the Claude preview) is intentionally disabled in this
30
- static build. Static Spaces don't run Python or serve models, so the
31
- deterministic keyword-lookup path is the honest option here.
32
 
33
- If you want the generative version, deploy the original `app.py` to a
34
- Gradio Space instead (`sdk: gradio`, CPU hardware is fine).
35
 
36
  ## Files
37
 
@@ -48,4 +46,4 @@ Gradio Space instead (`sdk: gradio`, CPU hardware is fine).
48
  ## Credits
49
 
50
  Design and frontend: a set of explorations for *This is Fetch*.
51
- Reference model: [facebook/blenderbot-400M-distill](https://huggingface.co/facebook/blenderbot-400M-distill).
 
1
  ---
2
+ title: This is Fetch
3
+ emoji: πŸ•
4
  colorFrom: gray
5
  colorTo: yellow
6
  sdk: static
7
  pinned: false
 
8
  ---
9
 
10
  # This is Fetch
 
16
 
17
  ## How it works
18
 
19
+ Fetch answers using a layered response pipeline:
20
 
21
+ - A lightweight **intent matcher** that handles greetings, small talk, and
22
+ questions like "what can you do".
23
  - A small **keyword lookup** table (dogs, breeds, care, trivia, reactions).
24
  If the user's question contains a known keyword, the matching fact is
25
  returned verbatim.
26
+ - Three **fallback replies** cover everything else.
 
27
 
28
+ There is no model running in this build. Static Spaces don't run Python or
29
+ serve models, so the deterministic response pipeline is the honest option here.
 
 
30
 
31
+ The generative version, powered by Meta's BlenderBot-400M-distill, runs
32
+ separately as a [Docker Space](https://huggingface.co/spaces/ElisaTrippetti/Fetch-Good-Boi).
33
 
34
  ## Files
35
 
 
46
  ## Credits
47
 
48
  Design and frontend: a set of explorations for *This is Fetch*.
49
+ Reference model: [facebook/blenderbot-400M-distill](https://huggingface.co/facebook/blenderbot-400M-distill).
chat-engine.jsx CHANGED
@@ -1,7 +1,7 @@
1
  // chat-engine.jsx β€” shared chat logic for all Fetch variants.
2
- // Mirrors the Python reference: 4-turn context, keyword lookup, fallbacks.
3
- // Two backends: "claude" (window.claude.complete) and "local" (keyword
4
- // lookup + fallback only β€” the path HuggingFace Static Spaces will take).
5
 
6
  const KNOWLEDGE_BASE = [
7
  ["domesticate", "Dogs have been domesticated for at least 15,000 years, making them the oldest domesticated animal."],
@@ -34,6 +34,33 @@ const FALLBACKS = [
34
  "I'm not sure about that, but dogs are great!",
35
  ];
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  const SUGGESTIONS = [
38
  "Tell me about border collies",
39
  "How good is a dog's sense of smell?",
@@ -93,6 +120,9 @@ function buildPrompt(history, userInput, fact, personality) {
93
  }
94
 
95
  async function generateReply({ userInput, history, backend, personality }) {
 
 
 
96
  const fact = retrieveFact(userInput);
97
 
98
  if (backend === "claude" && typeof window !== "undefined" && window.claude?.complete) {
@@ -170,18 +200,18 @@ function useFetchChat({ backend = "claude", personality = "subtle" } = {}) {
170
  return { messages, pending, debug, send, reset };
171
  }
172
 
173
- // Rotating suggestion carousel β€” 3 chips visible, rotates on interval.
174
  function useRotatingSuggestions({ visible = 3, intervalMs = 4200 } = {}) {
175
- const [offset, setOffset] = React.useState(0);
 
 
176
  React.useEffect(() => {
177
- const id = setInterval(() => setOffset(o => (o + 1) % SUGGESTIONS.length), intervalMs);
 
 
 
178
  return () => clearInterval(id);
179
- }, [intervalMs]);
180
- const current = React.useMemo(() => {
181
- const out = [];
182
- for (let i = 0; i < visible; i++) out.push(SUGGESTIONS[(offset + i) % SUGGESTIONS.length]);
183
- return out;
184
- }, [offset, visible]);
185
  return current;
186
  }
187
 
 
1
  // chat-engine.jsx β€” shared chat logic for all Fetch variants.
2
+ // Response pipeline: intent matching β†’ keyword lookup β†’ fallbacks.
3
+ // Two backends: "claude" (window.claude.complete) and "local" (intent
4
+ // matching + keyword lookup + fallbacks β€” the path HF Static Spaces take).
5
 
6
  const KNOWLEDGE_BASE = [
7
  ["domesticate", "Dogs have been domesticated for at least 15,000 years, making them the oldest domesticated animal."],
 
34
  "I'm not sure about that, but dogs are great!",
35
  ];
36
 
37
+ const INTENTS = [
38
+ {
39
+ patterns: [/\b(hi|hello|hey)\b/i, /good (morning|afternoon|evening)/i],
40
+ response: "Hi! I'm Fetch Pup. Ask me something about dogs, or try the suggestions below.",
41
+ },
42
+ {
43
+ patterns: [/how are you/i, /how('s| is) it going/i, /what'?s up/i],
44
+ response: "Tail's wagging, thanks for asking! Got a dog question for me?",
45
+ },
46
+ {
47
+ patterns: [/what can you do/i, /what do you (know|do)/i, /\bhelp\b/i],
48
+ response: "I know a bunch of dog facts. Ask a question or try the suggestions β€” I'll do my best.",
49
+ },
50
+ {
51
+ patterns: [/who are you/i, /what are you/i],
52
+ response: "I'm Fetch Pup β€” a static chatbot demo. No model running, just intent matching and keyword lookup. But I know my dogs!",
53
+ },
54
+ ];
55
+
56
+ function matchIntent(query) {
57
+ const q = query || "";
58
+ for (const intent of INTENTS) {
59
+ if (intent.patterns.some(p => p.test(q))) return intent.response;
60
+ }
61
+ return null;
62
+ }
63
+
64
  const SUGGESTIONS = [
65
  "Tell me about border collies",
66
  "How good is a dog's sense of smell?",
 
120
  }
121
 
122
  async function generateReply({ userInput, history, backend, personality }) {
123
+ const intent = matchIntent(userInput);
124
+ if (intent) return { text: intent, fact: null };
125
+
126
  const fact = retrieveFact(userInput);
127
 
128
  if (backend === "claude" && typeof window !== "undefined" && window.claude?.complete) {
 
200
  return { messages, pending, debug, send, reset };
201
  }
202
 
203
+ // Suggestion carousel β€” picks 3 at random on each interval tick.
204
  function useRotatingSuggestions({ visible = 3, intervalMs = 4200 } = {}) {
205
+ const [current, setCurrent] = React.useState(() =>
206
+ [...SUGGESTIONS].sort(() => Math.random() - 0.5).slice(0, visible)
207
+ );
208
  React.useEffect(() => {
209
+ const id = setInterval(() =>
210
+ setCurrent([...SUGGESTIONS].sort(() => Math.random() - 0.5).slice(0, visible)),
211
+ intervalMs
212
+ );
213
  return () => clearInterval(id);
214
+ }, [visible, intervalMs]);
 
 
 
 
 
215
  return current;
216
  }
217
 
debug-panel.jsx CHANGED
@@ -125,9 +125,9 @@ function DebugAbout({ palette }) {
125
  return (
126
  <div style={{ lineHeight: 1.6, color: palette.fg, display: "flex", flexDirection: "column", gap: 10 }}>
127
  <div>Fetch Pup is a static browser demo β€” there is no model running.</div>
128
- <div>Responses come from a small keyword lookup table: if your question contains a known word, the matching fact is returned verbatim. Otherwise you get one of three fallback replies.</div>
129
- <div>The generative version, powered by Meta's BlenderBot-400M-distill, runs separately as a Gradio Space.</div>
130
- <div style={{ color: palette.dim }}>β–Ž Designed with Claude Design Β· Built with Claude Code</div>
131
  </div>
132
  );
133
  }
 
125
  return (
126
  <div style={{ lineHeight: 1.6, color: palette.fg, display: "flex", flexDirection: "column", gap: 10 }}>
127
  <div>Fetch Pup is a static browser demo β€” there is no model running.</div>
128
+ <div>Responses come from two layers: an intent matcher that handles greetings and small talk, and a keyword lookup table that returns dog facts verbatim. If neither matches, you get one of three fallback replies.</div>
129
+ <div>The generative version, powered by Meta's BlenderBot-400M-distill, runs separately as a <a href="https://huggingface.co/spaces/ElisaTrippetti/Fetch-Good-Boi" target="_blank" rel="noopener noreferrer" style={{ color: palette.accent, textDecoration: "underline" }}>Docker Space</a>.</div>
130
+ <div style={{ color: palette.dim }}>Designed with Claude Design Β· Built with Claude Code</div>
131
  </div>
132
  );
133
  }
variant-terminal.jsx CHANGED
@@ -91,9 +91,9 @@ function TerminalVariant({ backend, personality, density, accent, fontPair, bubb
91
  margin: 0, fontFamily: "inherit", color: palette.dim,
92
  whiteSpace: "pre-wrap", marginBottom: 16,
93
  }}>
94
- {`// fetch pup is the first static chatbot i put together, and i use it as a learning baseline.
95
- // it comes with a small keyword lookup layer and a set of fallback responses.
96
- // type a question and hit enter, or try the suggestions below.
97
  `}
98
  </pre>
99
 
 
91
  margin: 0, fontFamily: "inherit", color: palette.dim,
92
  whiteSpace: "pre-wrap", marginBottom: 16,
93
  }}>
94
+ {`// hey! i'm fetch pup β€” a dog-loving chatbot demo and learning baseline.
95
+ // i do intent matching, keyword lookup, and fallbacks β€” no model, all browser.
96
+ // ask me something, or try the suggestions below.
97
  `}
98
  </pre>
99