I built a research-mode toggle for my LINE bot that actually

JordanGeek Expert 55m ago 204 views 13 likes 2 min read

The summary button was fine for quick TL;DRs, but users kept asking for "the real report with links." Swapping in Google Search Grounding via the Gemini API turned a three-line summary into a cited, sectioned brief you can actually trust. Below is the exact prompt I ship to the model, plus the wiring notes so you can drop it into your own webhook.

The prompt (copy-paste ready)

You are a research analyst. The user provides a URL or topic.
1. Use Google Search Grounding to fetch 8–12 authoritative sources published within the last 18 months.
2. Synthesize a structured report with these sections:
   • Executive Summary (3 bullets)
   • Key Findings (numbered, each with inline citation like [1], [2])
   • Contrasting Viewpoints (if sources disagree)
   • Data Points & Metrics (table-friendly numbers with units)
   • Open Questions / Gaps
   • Source List (full title, publication, date, URL)
3. Tone: professional, neutral, no fluff.
4. Output language: match the user's input language.
5. If grounding returns <4 usable sources, reply: "Insufficient recent coverage — try a broader query."

Why this prompt works

Explicit source count & recency — "8–12 sources, last 18 months" stops the model from hallucinating old blog posts.
Section schema — numbering the sections forces consistent structure; the frontend can render each as a collapsible card.
Inline citation contract[1] style tags map 1:1 to the Source List, so the LINE flex message can make them tap-to-open.
Failure guardrail — the "insufficient coverage" line prevents confident-sounding nonsense when the topic is too niche.

Wiring it into the LINE webhook (Node sketch)

// webhook handler (express)
app.post('/webhook', line.middleware(config), async (req, res) => {
  await Promise.all(req.body.events.map(handleEvent));
  res.sendStatus(200);
});

async function handleEvent(event) {
  if (event.type !== 'message' || event.message.type !== 'text') return;
  const text = event.message.text.trim();

  // user taps the "Research Report" quick-reply button → payload starts with "research:"
  if (text.startsWith('research:')) {
    const query = text.slice(9);
    const report = await callGeminiWithGrounding(query);
    await pushFlexReport(event.source.userId, report);
  }
}

callGeminiWithGrounding hits generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent with tools: [{ googleSearchRetrieval: {} }] and the prompt above in systemInstruction. The response's groundingMetadata.groundingChunks gives you the citation URLs — map those to the [n] markers before you build the flex JSON.

Cost & latency reality check

  • Tokens: ~2.2k input / 1.8k output per report (Gemini 1.5 Pro)
  • Latency: 6–9 s end-to-end (grounding adds ~3 s)
  • Bill: ~$0.018 per report at current pricing — cheap enough for a freemium bot tier

One gotcha

Grounding sometimes returns paywalled PDFs. I filter groundingChunks for web.uri containing .pdf and drop them unless the domain is arxiv.org or pubmed.ncbi.nlm.nih.gov. Keeps the "tap to open" experience honest.

Ship the prompt, wire the webhook, and your users get a citeable brief instead of a paragraph guess.

GeminiPrompt

All Replies (4)

N
NovaGuru Advanced 48m ago
Added grounding to my Discord bot — citations hallucinate less but still invent URLs sometimes.
0 Reply
A
AlexSurfer Intermediate 45m ago
@NovaGuru URL hallucinations persist — tried a post-retrieval validator against a known domain list?
0 Reply
S
Sam46 Advanced 44m ago
Now watch your Gemini bill exceed your rent
0 Reply
N
NovaOwl Intermediate 44m ago
Perplexity does this natively without the API hassle
0 Reply

Write a Reply

Markdown supported