Add AI-powered question answering with Perplexity API integration
- Integrate Perplexity AI API for intelligent question answering - Add AIResponseHandler class with question detection and response generation - Implement automatic question detection using regex patterns - Add AI commands: /perplexity, /ai on/off for configuration - Display AI responses in terminal before sending to Slack - Update configuration management to store Perplexity API key - Add comprehensive AI features documentation to README - Update requirements.txt with OpenAI library dependency - Fix Perplexity model name to use valid 'sonar' model - Enhance interactive chat mode with AI-powered capabilities - Maintain backward compatibility with existing CLI functionality
This commit is contained in:
parent
a971d9366c
commit
fd58016586
@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
SLACK_BOT_TOKEN=xoxb-9294326441810-9634538323301-TEDMBIwZqA5VJJU1yoRFX6NF
|
SLACK_BOT_TOKEN=xoxb-9294326441810-9634538323301-TEDMBIwZqA5VJJU1yoRFX6NF
|
||||||
SLACK_CHANNEL_ID=C09JKHXS9L3
|
SLACK_CHANNEL_ID=C09JKHXS9L3
|
||||||
#https://bytelets.slack.com/archives/C09JKHXS9L3
|
|
||||||
|
# Perplexity AI API Key for intelligent question answering
|
||||||
|
# Get your API key from: https://www.perplexity.ai/
|
||||||
|
PERPLEXITY_API_KEY=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
|
||||||
@ -1,6 +1,6 @@
|
|||||||
# Slack Two-Way Chat CLI
|
# Slack AI-Powered Two-Way Chat CLI
|
||||||
|
|
||||||
A powerful command-line tool for two-way communication with Slack channels. Send and receive messages in real-time with both CLI and interactive chat modes.
|
A powerful command-line tool for AI-powered two-way communication with Slack channels. Send and receive messages in real-time with intelligent question-answering capabilities using Perplexity AI.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@ -11,9 +11,9 @@ pip install -r requirements.txt
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### Interactive Two-Way Chat Mode (Recommended)
|
### Interactive AI-Powered Two-Way Chat Mode (Recommended)
|
||||||
|
|
||||||
Start an interactive chat session where you can send and receive messages:
|
Start an interactive chat session where you can send and receive messages with AI-powered question answering:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python slack_poster.py --chat
|
python slack_poster.py --chat
|
||||||
@ -22,10 +22,11 @@ python slack_poster.py -i
|
|||||||
|
|
||||||
In chat mode, you can:
|
In chat mode, you can:
|
||||||
- Type messages directly to send them to Slack
|
- Type messages directly to send them to Slack
|
||||||
|
- Ask questions and get AI-powered answers automatically
|
||||||
- Use `/listen` to start receiving messages from others in real-time
|
- Use `/listen` to start receiving messages from others in real-time
|
||||||
- View message history with `/history`
|
- View message history with `/history`
|
||||||
- Use commands to manage your configuration
|
- Use commands to manage your configuration
|
||||||
- Have your token and channel ID automatically saved for future sessions
|
- Have your token, channel ID, and Perplexity API key automatically saved for future sessions
|
||||||
|
|
||||||
### Command Line Mode
|
### Command Line Mode
|
||||||
|
|
||||||
@ -71,14 +72,41 @@ When in chat mode, you can use the following commands:
|
|||||||
- `/quit` or `/q` or `/exit` - Exit the chat
|
- `/quit` or `/q` or `/exit` - Exit the chat
|
||||||
- `/token <token>` - Set or update your Slack token
|
- `/token <token>` - Set or update your Slack token
|
||||||
- `/channel <id>` - Set or update the channel ID
|
- `/channel <id>` - Set or update the channel ID
|
||||||
- `/status` - Show current configuration (token and channel)
|
- `/perplexity <key>` - Set or update your Perplexity API key
|
||||||
|
- `/status` - Show current configuration (token, channel, and AI settings)
|
||||||
- `/clear` - Clear all saved configuration
|
- `/clear` - Clear all saved configuration
|
||||||
- `/test` - Send a test message to verify your configuration
|
- `/test` - Send a test message to verify your configuration
|
||||||
- `/listen` - Start listening for incoming messages in real-time
|
- `/listen` - Start listening for incoming messages in real-time
|
||||||
- `/stop` - Stop listening for messages
|
- `/stop` - Stop listening for messages
|
||||||
- `/history [n]` - Show recent message history (default: 10 messages)
|
- `/history [n]` - Show recent message history (default: 10 messages)
|
||||||
|
- `/ai on/off` - Enable or disable AI responses
|
||||||
- `<message>` - Send any text as a message to the current channel
|
- `<message>` - Send any text as a message to the current channel
|
||||||
|
|
||||||
|
## AI-Powered Question Answering Features
|
||||||
|
|
||||||
|
The tool now includes intelligent question-answering capabilities using Perplexity AI:
|
||||||
|
|
||||||
|
### Automatic Question Detection
|
||||||
|
- AI automatically detects when you ask questions
|
||||||
|
- Supports various question formats: "What is...?", "How do...?", "Why...?", etc.
|
||||||
|
- Responds with intelligent, accurate answers
|
||||||
|
|
||||||
|
### AI Response Examples
|
||||||
|
```
|
||||||
|
> What is the capital of India?
|
||||||
|
[14:30:15] You: What is the capital of India?
|
||||||
|
[OK] Message sent to #C09JKHXS9L3
|
||||||
|
[AI] Thinking...
|
||||||
|
[14:30:18] AI Bot: The capital of India is New Delhi.
|
||||||
|
[OK] AI response sent to #C09JKHXS9L3
|
||||||
|
```
|
||||||
|
|
||||||
|
### AI Configuration
|
||||||
|
- Use `/perplexity <your-api-key>` to set your Perplexity API key
|
||||||
|
- Use `/ai on` to enable automatic AI responses
|
||||||
|
- Use `/ai off` to disable AI responses
|
||||||
|
- AI responses are sent to the Slack channel with 🤖 AI: prefix
|
||||||
|
|
||||||
## Two-Way Communication Features
|
## Two-Way Communication Features
|
||||||
|
|
||||||
The tool now supports full two-way communication with Slack channels:
|
The tool now supports full two-way communication with Slack channels:
|
||||||
@ -117,7 +145,9 @@ The tool handles various error scenarios:
|
|||||||
- Network issues
|
- Network issues
|
||||||
- Empty messages
|
- Empty messages
|
||||||
|
|
||||||
## Getting Slack Credentials
|
## Getting API Credentials
|
||||||
|
|
||||||
|
### Slack Credentials
|
||||||
|
|
||||||
1. Go to https://api.slack.com/apps
|
1. Go to https://api.slack.com/apps
|
||||||
2. Create a new app or select existing one
|
2. Create a new app or select existing one
|
||||||
@ -132,6 +162,15 @@ The tool handles various error scenarios:
|
|||||||
5. Install the app to your workspace
|
5. Install the app to your workspace
|
||||||
6. Copy the Bot User OAuth Token (starts with `xoxb-`)
|
6. Copy the Bot User OAuth Token (starts with `xoxb-`)
|
||||||
|
|
||||||
|
### Perplexity AI Credentials
|
||||||
|
|
||||||
|
1. Go to https://www.perplexity.ai/
|
||||||
|
2. Sign up for an account
|
||||||
|
3. Go to your account settings or API section
|
||||||
|
4. Generate an API key
|
||||||
|
5. Copy the API key (starts with `pplx-`)
|
||||||
|
6. Use `/perplexity <your-api-key>` in the chat to set it
|
||||||
|
|
||||||
## Channel ID
|
## Channel ID
|
||||||
|
|
||||||
To get a channel ID:
|
To get a channel ID:
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
slack_sdk>=3.21.0
|
slack_sdk>=3.21.0
|
||||||
requests>=2.28.0
|
requests>=2.28.0
|
||||||
python-dotenv>=1.0.0
|
python-dotenv>=1.0.0
|
||||||
|
openai>=1.0.0
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import time
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Dict, Any, List
|
from typing import Optional, Dict, Any, List
|
||||||
|
import re
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from slack_sdk import WebClient
|
from slack_sdk import WebClient
|
||||||
@ -23,6 +24,12 @@ except ImportError:
|
|||||||
print("Error: slack_sdk not installed. Run: pip install slack_sdk")
|
print("Error: slack_sdk not installed. Run: pip install slack_sdk")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
import openai
|
||||||
|
except ImportError:
|
||||||
|
print("Warning: openai not installed. AI features will be disabled. Run: pip install openai")
|
||||||
|
openai = None
|
||||||
|
|
||||||
# Try to load environment variables from .env file
|
# Try to load environment variables from .env file
|
||||||
try:
|
try:
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
@ -32,6 +39,58 @@ except ImportError:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AIResponseHandler:
|
||||||
|
"""Handles AI-powered responses using Perplexity API."""
|
||||||
|
|
||||||
|
def __init__(self, api_key: str):
|
||||||
|
"""Initialize the AI response handler."""
|
||||||
|
if openai is None:
|
||||||
|
raise ImportError("OpenAI library not installed")
|
||||||
|
|
||||||
|
self.client = openai.OpenAI(
|
||||||
|
api_key=api_key,
|
||||||
|
base_url="https://api.perplexity.ai"
|
||||||
|
)
|
||||||
|
|
||||||
|
def is_question(self, text: str) -> bool:
|
||||||
|
"""Check if the text is a question."""
|
||||||
|
# Simple question detection patterns
|
||||||
|
question_patterns = [
|
||||||
|
r'\?$', # Ends with question mark
|
||||||
|
r'^(what|where|when|why|how|who|which|can|could|would|should|is|are|was|were|do|does|did)\b', # Starts with question words
|
||||||
|
r'\b(what|where|when|why|how|who|which|can|could|would|should|is|are|was|were|do|does|did)\b', # Contains question words
|
||||||
|
]
|
||||||
|
|
||||||
|
text_lower = text.lower().strip()
|
||||||
|
for pattern in question_patterns:
|
||||||
|
if re.search(pattern, text_lower):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_ai_response(self, question: str) -> str:
|
||||||
|
"""Get AI response for a question."""
|
||||||
|
try:
|
||||||
|
response = self.client.chat.completions.create(
|
||||||
|
model="sonar",
|
||||||
|
messages=[
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": "You are a helpful assistant. Provide concise, accurate answers to questions. Keep responses brief and informative."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": question
|
||||||
|
}
|
||||||
|
],
|
||||||
|
max_tokens=200,
|
||||||
|
temperature=0.7
|
||||||
|
)
|
||||||
|
|
||||||
|
return response.choices[0].message.content.strip()
|
||||||
|
except Exception as e:
|
||||||
|
return f"[AI Error] Failed to get response: {str(e)}"
|
||||||
|
|
||||||
|
|
||||||
class ConfigManager:
|
class ConfigManager:
|
||||||
"""Manages persistent configuration storage."""
|
"""Manages persistent configuration storage."""
|
||||||
|
|
||||||
@ -67,6 +126,10 @@ class ConfigManager:
|
|||||||
"""Get stored channel ID."""
|
"""Get stored channel ID."""
|
||||||
return self.config.get('channel')
|
return self.config.get('channel')
|
||||||
|
|
||||||
|
def get_perplexity_key(self) -> Optional[str]:
|
||||||
|
"""Get stored Perplexity API key."""
|
||||||
|
return self.config.get('perplexity_key')
|
||||||
|
|
||||||
def set_token(self, token: str) -> None:
|
def set_token(self, token: str) -> None:
|
||||||
"""Set and save Slack token."""
|
"""Set and save Slack token."""
|
||||||
self.config['token'] = token
|
self.config['token'] = token
|
||||||
@ -77,6 +140,11 @@ class ConfigManager:
|
|||||||
self.config['channel'] = channel
|
self.config['channel'] = channel
|
||||||
self.save_config()
|
self.save_config()
|
||||||
|
|
||||||
|
def set_perplexity_key(self, api_key: str) -> None:
|
||||||
|
"""Set and save Perplexity API key."""
|
||||||
|
self.config['perplexity_key'] = api_key
|
||||||
|
self.save_config()
|
||||||
|
|
||||||
def clear_config(self) -> None:
|
def clear_config(self) -> None:
|
||||||
"""Clear all stored configuration."""
|
"""Clear all stored configuration."""
|
||||||
self.config = {}
|
self.config = {}
|
||||||
@ -322,20 +390,28 @@ def validate_channel(channel: str) -> bool:
|
|||||||
def print_help():
|
def print_help():
|
||||||
"""Print help information for interactive mode."""
|
"""Print help information for interactive mode."""
|
||||||
print("\n" + "="*70)
|
print("\n" + "="*70)
|
||||||
print("SLACK TWO-WAY CHAT MODE - Available Commands:")
|
print("SLACK AI-POWERED TWO-WAY CHAT MODE - Available Commands:")
|
||||||
print("="*70)
|
print("="*70)
|
||||||
print(" /help, /h - Show this help message")
|
print(" /help, /h - Show this help message")
|
||||||
print(" /quit, /q, /exit - Exit the chat")
|
print(" /quit, /q, /exit - Exit the chat")
|
||||||
print(" /token <token> - Set/update Slack token")
|
print(" /token <token> - Set/update Slack token")
|
||||||
print(" /channel <id> - Set/update channel ID")
|
print(" /channel <id> - Set/update channel ID")
|
||||||
|
print(" /perplexity <key> - Set/update Perplexity API key")
|
||||||
print(" /status - Show current configuration")
|
print(" /status - Show current configuration")
|
||||||
print(" /clear - Clear saved configuration")
|
print(" /clear - Clear saved configuration")
|
||||||
print(" /test - Test current configuration")
|
print(" /test - Test current configuration")
|
||||||
print(" /listen - Start listening for incoming messages")
|
print(" /listen - Start listening for incoming messages")
|
||||||
print(" /stop - Stop listening for messages")
|
print(" /stop - Stop listening for messages")
|
||||||
print(" /history [n] - Show recent message history (default: 10)")
|
print(" /history [n] - Show recent message history (default: 10)")
|
||||||
|
print(" /ai on/off - Enable/disable AI responses")
|
||||||
print(" <message> - Send message to current channel")
|
print(" <message> - Send message to current channel")
|
||||||
print("="*70)
|
print("="*70)
|
||||||
|
print("AI FEATURES:")
|
||||||
|
print(" - Ask questions and get AI-powered answers automatically")
|
||||||
|
print(" - AI detects questions and responds with intelligent answers")
|
||||||
|
print(" - Use /perplexity <key> to set your Perplexity API key")
|
||||||
|
print(" - Use /ai on to enable automatic AI responses")
|
||||||
|
print("="*70)
|
||||||
print("TWO-WAY FEATURES:")
|
print("TWO-WAY FEATURES:")
|
||||||
print(" - Messages sent by others will appear automatically when listening")
|
print(" - Messages sent by others will appear automatically when listening")
|
||||||
print(" - Use /listen to start receiving messages in real-time")
|
print(" - Use /listen to start receiving messages in real-time")
|
||||||
@ -345,13 +421,15 @@ def print_help():
|
|||||||
|
|
||||||
def interactive_chat_mode(config_manager: ConfigManager):
|
def interactive_chat_mode(config_manager: ConfigManager):
|
||||||
"""Run interactive chat mode."""
|
"""Run interactive chat mode."""
|
||||||
print("\n[CHAT] Welcome to Slack Two-Way Interactive Chat Mode!")
|
print("\n[CHAT] Welcome to Slack AI-Powered Two-Way Interactive Chat Mode!")
|
||||||
print("Type your messages to send them to Slack.")
|
print("Type your messages to send them to Slack.")
|
||||||
|
print("Ask questions and get AI-powered answers automatically!")
|
||||||
print("Use /help for available commands.\n")
|
print("Use /help for available commands.\n")
|
||||||
|
|
||||||
# Check if we have stored configuration (try environment variables first, then config file)
|
# Check if we have stored configuration (try environment variables first, then config file)
|
||||||
token = os.getenv('SLACK_BOT_TOKEN') or config_manager.get_token()
|
token = os.getenv('SLACK_BOT_TOKEN') or config_manager.get_token()
|
||||||
channel = os.getenv('SLACK_CHANNEL_ID') or config_manager.get_channel()
|
channel = os.getenv('SLACK_CHANNEL_ID') or config_manager.get_channel()
|
||||||
|
perplexity_key = os.getenv('PERPLEXITY_API_KEY') or config_manager.get_perplexity_key()
|
||||||
|
|
||||||
if not token:
|
if not token:
|
||||||
print("No Slack token found. Please set one using /token <your-token>")
|
print("No Slack token found. Please set one using /token <your-token>")
|
||||||
@ -361,12 +439,19 @@ def interactive_chat_mode(config_manager: ConfigManager):
|
|||||||
print(f"[OK] Using configuration:")
|
print(f"[OK] Using configuration:")
|
||||||
print(f" Channel: {channel}")
|
print(f" Channel: {channel}")
|
||||||
print(f" Token: {token[:10]}...")
|
print(f" Token: {token[:10]}...")
|
||||||
|
if perplexity_key:
|
||||||
|
print(f" Perplexity API: {perplexity_key[:10]}...")
|
||||||
|
else:
|
||||||
|
print(" Perplexity API: Not set (use /perplexity <key>)")
|
||||||
|
|
||||||
print("\nReady to chat! Type your message or use /help for commands.")
|
print("\nReady to chat! Type your message or use /help for commands.")
|
||||||
print("Use /listen to start receiving messages from others.\n")
|
print("Use /listen to start receiving messages from others.")
|
||||||
|
print("Ask questions like 'What is the capital of India?' for AI answers!\n")
|
||||||
|
|
||||||
poster = None
|
poster = None
|
||||||
message_receiver = None
|
message_receiver = None
|
||||||
|
ai_handler = None
|
||||||
|
ai_enabled = False
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
@ -422,6 +507,9 @@ def interactive_chat_mode(config_manager: ConfigManager):
|
|||||||
print(f"\n[STATUS] Current Configuration:")
|
print(f"\n[STATUS] Current Configuration:")
|
||||||
print(f" Token: {token[:10] + '...' if token else 'Not set'}")
|
print(f" Token: {token[:10] + '...' if token else 'Not set'}")
|
||||||
print(f" Channel: {channel if channel else 'Not set'}")
|
print(f" Channel: {channel if channel else 'Not set'}")
|
||||||
|
print(f" Perplexity API: {perplexity_key[:10] + '...' if perplexity_key else 'Not set'}")
|
||||||
|
print(f" AI Responses: {'Enabled' if ai_enabled else 'Disabled'}")
|
||||||
|
print(f" AI Handler: {'Ready' if ai_handler else 'Not initialized'}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
elif command == '/clear':
|
elif command == '/clear':
|
||||||
@ -516,6 +604,56 @@ def interactive_chat_mode(config_manager: ConfigManager):
|
|||||||
print(f"[ERROR] Failed to get message history: {e}")
|
print(f"[ERROR] Failed to get message history: {e}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
elif command == '/perplexity':
|
||||||
|
parts = user_input.split(' ', 1)
|
||||||
|
if len(parts) < 2:
|
||||||
|
print("[ERROR] Usage: /perplexity <your-perplexity-api-key>")
|
||||||
|
continue
|
||||||
|
|
||||||
|
new_key = parts[1].strip()
|
||||||
|
config_manager.set_perplexity_key(new_key)
|
||||||
|
perplexity_key = new_key
|
||||||
|
|
||||||
|
# Initialize AI handler
|
||||||
|
try:
|
||||||
|
ai_handler = AIResponseHandler(perplexity_key)
|
||||||
|
print("[OK] Perplexity API key updated and AI handler initialized!")
|
||||||
|
except ImportError:
|
||||||
|
print("[ERROR] OpenAI library not installed. Run: pip install openai")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ERROR] Failed to initialize AI handler: {e}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif command == '/ai':
|
||||||
|
parts = user_input.split()
|
||||||
|
if len(parts) < 2:
|
||||||
|
print(f"[INFO] AI responses are currently {'enabled' if ai_enabled else 'disabled'}")
|
||||||
|
print("[USAGE] /ai on - Enable AI responses")
|
||||||
|
print("[USAGE] /ai off - Disable AI responses")
|
||||||
|
continue
|
||||||
|
|
||||||
|
action = parts[1].lower()
|
||||||
|
if action == 'on':
|
||||||
|
if not perplexity_key:
|
||||||
|
print("[ERROR] Please set Perplexity API key first using /perplexity <key>")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not ai_handler:
|
||||||
|
try:
|
||||||
|
ai_handler = AIResponseHandler(perplexity_key)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ERROR] Failed to initialize AI handler: {e}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
ai_enabled = True
|
||||||
|
print("[OK] AI responses enabled! Ask questions to get AI answers.")
|
||||||
|
elif action == 'off':
|
||||||
|
ai_enabled = False
|
||||||
|
print("[OK] AI responses disabled.")
|
||||||
|
else:
|
||||||
|
print("[ERROR] Usage: /ai on or /ai off")
|
||||||
|
continue
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(f"[ERROR] Unknown command: {command}. Use /help for available commands.")
|
print(f"[ERROR] Unknown command: {command}. Use /help for available commands.")
|
||||||
continue
|
continue
|
||||||
@ -544,6 +682,23 @@ def interactive_chat_mode(config_manager: ConfigManager):
|
|||||||
print(f"[{formatted_time}] You: {user_input}")
|
print(f"[{formatted_time}] You: {user_input}")
|
||||||
print(f"[OK] Message sent to #{channel}")
|
print(f"[OK] Message sent to #{channel}")
|
||||||
|
|
||||||
|
# Check if AI should respond to this message
|
||||||
|
if ai_enabled and ai_handler and ai_handler.is_question(user_input):
|
||||||
|
try:
|
||||||
|
print("[AI] Thinking...")
|
||||||
|
ai_response = ai_handler.get_ai_response(user_input)
|
||||||
|
|
||||||
|
# Display AI response in terminal first
|
||||||
|
ai_timestamp = datetime.now().strftime('%H:%M:%S')
|
||||||
|
print(f"[{ai_timestamp}] AI Bot: {ai_response}")
|
||||||
|
|
||||||
|
# Then send AI response to Slack
|
||||||
|
poster.post_message(channel, f"🤖 AI: {ai_response}")
|
||||||
|
print(f"[OK] AI response sent to #{channel}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[AI ERROR] Failed to generate AI response: {e}")
|
||||||
|
|
||||||
except SlackApiError as e:
|
except SlackApiError as e:
|
||||||
error_msg = str(e)
|
error_msg = str(e)
|
||||||
if "invalid_auth" in error_msg.lower():
|
if "invalid_auth" in error_msg.lower():
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user