-
Notifications
You must be signed in to change notification settings - Fork 49
feat: Add web search capability using Tavily #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
LeonMelamud
commented
Dec 26, 2025
- Added enable_web_search flag to Group model and DB migration
- Integrated Tavily API for web search
- Updated RAG agent to use web search tool when enabled
- Added Group Management UI support for web search toggle
- Updated documentation
- Added enable_web_search flag to Group model and DB migration - Integrated Tavily API for web search - Updated RAG agent to use web search tool when enabled - Added Group Management UI support for web search toggle - Updated documentation
| @@ -0,0 +1,33 @@ | |||
| import asyncio | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a file for local tests ?
| await self.send_message( | ||
| message.chat_jid, | ||
| "I'm an open-source bot created for the GenAI Israel community - https://llm.org.il.\nI can help you catch up on the chat messages and answer questions based on the group's knowledge.\nPlease send me PRs and star me at https://github.com/ilanbenb/wa_llm ⭐️", | ||
| "Greetings, mortals! I am AGI (Almost General Intelligence) 🤖.\nI was forged by Ilan from GenAI Israel, but my brain was polished and fine-tuned by the one and only Leon Melamud (he taught me everything I know, including how to be this charming).\nI'm here to make sense of your chaos—summarizing chats and answering questions so you can pretend you read everything.\nFeed my ego with stars: https://github.com/ilanbenb/wa_llm ⭐️", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use environment variable :)
| Returns: | ||
| Simple "ok" response to acknowledge receipt | ||
| """ | ||
| print(f"Received webhook payload: {payload}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove debug logs. At least put in comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request adds comprehensive web search capability using the Tavily API, along with several significant features including a Group Management UI, auto-summary functionality, local model support, and rate limiting.
Key Changes:
- Web Search Integration: Added Tavily API integration to enable the bot to search the web when answering questions
- Group Management UI: New web interface at
/group/uifor managing groups, participants, and settings - Auto-Summary Feature: Groups can now be configured to automatically trigger summaries after a threshold of messages
- Local Model Support: Added optional support for running local Hugging Face models with GPU acceleration
Reviewed changes
Copilot reviewed 47 out of 49 changed files in this pull request and generated 25 comments.
Show a summary per file
| File | Description |
|---|---|
uv.lock |
Added dependencies for Tavily, Torch, Transformers, and related ML libraries |
pyproject.toml |
Added tavily-python and optional local model dependencies |
src/services/web_search.py |
New service for Tavily web search integration |
src/templates/rag.j2 |
Updated RAG prompt template to support web search capability |
src/handler/knowledge_base_answers.py |
Integrated web search tool into RAG agent |
src/models/group.py |
Added enable_web_search field and auto-summary configuration |
src/api/group.py |
New comprehensive Group Management API with UI |
src/api/bot_settings.py |
New Bot Settings API for DM auto-reply management |
src/handler/__init__.py |
Added auto-summary trigger logic and rate limiting |
migrations/ |
Three new database migrations for GroupMember table, auto-summary fields, and web search flag |
docker-compose.yml |
Added GPU support and updated volume mounts |
README.md |
Updated documentation with new features |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| class MessageMixin(WhatsAppClientProtocol): | ||
| async def send_message(self, request: SendMessageRequest) -> MessageSendResponse: | ||
| response = await self._post("/send/message", json=request) | ||
| time.sleep(1) |
Copilot
AI
Jan 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using time.sleep(1) in an async function blocks the entire event loop. This should be replaced with await asyncio.sleep(1) to avoid blocking other async operations. The synchronous sleep will prevent any other coroutines from executing during that second, which defeats the purpose of using async/await.
| # Log the request payload for debugging | ||
| if content: | ||
| # Avoid logging large payloads if necessary, but for now it's useful | ||
| print(f"DEBUG: Sending POST to {path} with body: {content}") |
Copilot
AI
Jan 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debug print statements should not be committed to production code. Consider using proper logging with the logger module instead, or remove these debug prints. If debugging is needed, use logger.debug() which can be controlled via log level configuration.
| # Tavily's python client is synchronous, but we can wrap it or just use it if it's fast enough. | ||
| # For now, let's use it directly. | ||
| try: | ||
| response = self.client.search(query=query, search_depth=search_depth, max_results=max_results) | ||
| results = response.get("results", []) |
Copilot
AI
Jan 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Tavily client's synchronous search() method is being called directly within an async function without proper wrapping. While the comment acknowledges this, it should be wrapped in asyncio.to_thread() or similar to avoid blocking the event loop during the search operation. This could cause the entire application to hang if the search takes a long time.
|
|
||
| def get_model(settings: Settings) -> Union[str, Model]: | ||
| global _local_model_instance | ||
| print(f"get_model called. use_local_model={settings.use_local_model}, instance={_local_model_instance}") |
Copilot
AI
Jan 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debug print statement should be removed from production code or replaced with proper logging using the logging module.
|
|
||
| async def _route(self, message: str) -> IntentEnum: | ||
| async def _route(self, message: str) -> Intent: | ||
| print(f"Routing message: {message}") |
Copilot
AI
Jan 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debug print statement should be removed from production code or replaced with proper logging.
| print(f"Routing message: {message}") | |
| logger.debug("Routing message: %s", message) |
| @@ -0,0 +1,116 @@ | |||
| import asyncio | |||
| from typing import Optional, List | |||
Copilot
AI
Jan 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import of 'List' is not used.
| from pydantic import BaseModel, Field | ||
| from pydantic_ai import Agent | ||
| from sqlmodel import desc, select | ||
| from sqlmodel import desc, select, col |
Copilot
AI
Jan 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import of 'col' is not used.
| from sqlmodel import desc, select, col | |
| from sqlmodel import desc, select |
|
|
||
| from handler.knowledge_base_answers import KnowledgeBaseAnswers | ||
| from models import Message | ||
| from models import Message, Group, GroupMember, Sender, BaseSender, upsert |
Copilot
AI
Jan 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import of 'Group' is not used.
Import of 'GroupMember' is not used.
Import of 'Sender' is not used.
Import of 'BaseSender' is not used.
Import of 'upsert' is not used.
| from models import Message, Group, GroupMember, Sender, BaseSender, upsert | |
| from models import Message |
| import asyncio | ||
| import httpx | ||
| import os | ||
| import sys |
Copilot
AI
Jan 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import of 'sys' is not used.
| import sys |
| @@ -0,0 +1,47 @@ | |||
| from typing import List, Dict, Any, Optional | |||
Copilot
AI
Jan 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import of 'Optional' is not used.