Skip to content

Instantly share code, notes, and snippets.

@eliasdabbas
Last active February 3, 2026 18:59
Show Gist options
  • Select an option

  • Save eliasdabbas/0a621df7d3924cbf64721a078ce2b36d to your computer and use it in GitHub Desktop.

Select an option

Save eliasdabbas/0a621df7d3924cbf64721a078ce2b36d to your computer and use it in GitHub Desktop.
Chatbot that searches and generates answers from the given domains
# /// script
# requires-python = ">=3.13"
# dependencies = [
# "anthropic>=0.77.0",
# "chatnificent>=0.0.10",
# "dash-bootstrap-components>=2.0.4",
# ]
# ///
import chatnificent as chat
from anthropic.types import TextBlock
from chatnificent import Chatnificent
ALLOWED_DOMAINS = ["dash.plotly.com"] # <-- change this
class AnthropicSearch(chat.llm.Anthropic):
def format_search_results(self, response, n_references=3) -> str:
output = []
references = []
for block in response.content:
if block.type == "web_search_tool_result":
for i, result in enumerate(block.content):
if (
result.type == "web_search_result"
and i < n_references
and result.url
):
title = result.title or result.url
references.append(f"- [{title}]({result.url})")
elif block.type == "text":
if block.text.strip():
output.append(block.text)
if references:
output.append("\n\nReferences:")
output.extend(references)
return "\n".join(output)
def generate_response(self, messages):
response = self.client.messages.create(
model="claude-opus-4-5-20251101",
max_tokens=20024,
messages=messages,
system="""You are the Dash search bot. You only provide answers from
the given domains.
Assume users are searching for stuff related to Plotly's Dash framework.
An "app" should be understood as a Dash app, a "callback" is a Dash app's callback
function, and so on.
Check these domains for answers every single time.
If you don't find a good answer from the domains, you apologize with a polite message.""",
tools=[
{
"type": "web_search_20250305",
"name": "web_search",
"max_uses": 5,
"allowed_domains": ALLOWED_DOMAINS,
}
],
tool_choice={"type": "tool", "name": "web_search"},
)
formatted_output = self.format_search_results(response, n_references=3)
response.content = [TextBlock(type="text", text=formatted_output)]
return response
app = Chatnificent(
llm=AnthropicSearch(),
store=chat.store.File("chat_history"), # <-- chat history will be saved to this directory
)
if __name__ == "__main__":
app.run(debug=True)
@eliasdabbas
Copy link
Author

An AI website search bot built with Chatnificent

  • Set a domain(s) for the LLM to search from and provide/generate answers
  • Great to have in addition to documentation (AI docs)
  • Uses Anthropic's web search tool, easily modifiable to use Gemini, OpenAI, etc
  • You can run it locally using uv:
uv run --script https://gist.githubusercontent.com/eliasdabbas/0a621df7d3924cbf64721a078ce2b36d/raw/449960aef2863b8cafefb6436cdd37cd0a686d47/ai_website_search.py
  • You should have an environment variable with your API key: ANTHROPIC_API_KEY (or the other providers)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment