help@rskworld.in +91 93305 39277
RSK World
  • Home
  • Development
    • Web Development
    • Mobile Apps
    • Software
    • Games
    • Project
  • Technologies
    • Data Science
    • AI Development
    • Cloud Development
    • Blockchain
    • Cyber Security
    • Dev Tools
    • Testing Tools
  • Blog
  • About
  • Contact

Theme Settings

Color Scheme
Display Options
Font Size
100%
Back to Project
RSK World
anthropic-claude-chatbot
RSK World
anthropic-claude-chatbot
Anthropic Claude Chatbot - Python + Flask + Claude API + JavaScript + AI Chatbot + Conversational AI
anthropic-claude-chatbot
  • __pycache__
  • .env578 B
  • .gitignore669 B
  • ADVANCED_FEATURES.md6.6 KB
  • CHECKLIST.md3 KB
  • GITHUB_RELEASE_GUIDE.md4.6 KB
  • LICENSE1.3 KB
  • PROJECT_INFO.md2.2 KB
  • QUICK_START.md2.8 KB
  • README.md8.5 KB
  • RELEASE_NOTES.md6.6 KB
  • SETUP_ENV.md1.9 KB
  • TROUBLESHOOTING.md5.1 KB
  • advanced-features.js24.9 KB
  • app.py9.7 KB
  • config.py2.4 KB
  • env.example550 B
  • index.html11.4 KB
  • requirements.txt440 B
  • run.bat782 B
  • run.sh713 B
  • script.js21.2 KB
  • setup.py2.5 KB
  • start-frontend.bat683 B
  • start.bat1.6 KB
  • styles.css20.2 KB
PROJECT_INFO.mdscript.jsapp.py.envenv.example
PROJECT_INFO.md
Raw Download

PROJECT_INFO.md

# Project Information

## Anthropic Claude Chatbot

### Project Details
- **ID:** 7
- **Title:** Anthropic Claude Chatbot
- **Category:** OpenAI Integration
- **Difficulty:** Intermediate
- **Year:** 2026

### Description
Chatbot integration with Anthropic Claude API for advanced conversational AI.

### Full Description
This project integrates Anthropic Claude API to create intelligent chatbots with advanced reasoning capabilities. Features include long context handling, complex reasoning, and safe AI interactions.

### Technologies
- Anthropic API
- Python
- Claude
- JavaScript

### Features
- Claude API integration
- Long context support
- Advanced reasoning
- Safe AI interactions
- Multi-modal support

### Developer Information
- **Website:** https://rskworld.in
- **Email:** help@rskworld.in, support@rskworld.in
- **Phone:** +91 93305 39277
- **Organization:** RSK World
- **Founder:** Molla Samser
- **Designer & Tester:** Rima Khatun

### Project Structure
```
anthropic-claude-chatbot/
├── index.html # Main HTML interface
├── styles.css # CSS styling
├── script.js # Frontend JavaScript
├── app.py # Flask backend server
├── config.py # Configuration file
├── setup.py # Setup helper script
├── requirements.txt # Python dependencies
├── env.example # Environment variables template
├── .gitignore # Git ignore rules
├── README.md # Project documentation
├── LICENSE # MIT License
├── run.bat # Windows start script
├── run.sh # Linux/Mac start script
└── PROJECT_INFO.md # This file
```

### Quick Start
1. Install Python dependencies: `pip install -r requirements.txt`
2. Copy `env.example` to `.env` and add your Anthropic API key
3. Run the server: `python app.py` (or use `run.bat` / `run.sh`)
4. Open `index.html` in your browser

### API Endpoints
- `GET /api/health` - Health check
- `POST /api/chat` - Chat endpoint
- `GET /api/models` - List available models

---

© 2026 RSK World. All rights reserved.

script.js
Raw Download
Find: Go to:
/*
    Anthropic Claude Chatbot - Client-Side JavaScript
    Project: Anthropic Claude Chatbot
    Category: OpenAI Integration
    Year: 2026
    
    Developer Details:
    - Website: https://rskworld.in
    - Email: help@rskworld.in, support@rskworld.in
    - Phone: +91 93305 39277
    - Organization: RSK World
    - Founder: Molla Samser
    - Designer & Tester: Rima Khatun
*/

// API Configuration
const API_BASE_URL = 'http://localhost:5000/api';

// DOM Elements
const chatMessages = document.getElementById('chatMessages');
const messageInput = document.getElementById('messageInput');
const sendBtn = document.getElementById('sendBtn');
const attachBtn = document.getElementById('attachBtn');
const settingsBtn = document.getElementById('settingsBtn');
const closeSidebar = document.getElementById('closeSidebar');
const sidebar = document.getElementById('sidebar');
const clearChatBtn = document.getElementById('clearChat');
const loadingOverlay = document.getElementById('loadingOverlay');
const charCount = document.getElementById('charCount');
const statusIndicator = document.getElementById('statusIndicator');

// Settings Elements
const modelSelect = document.getElementById('modelSelect');
const maxTokens = document.getElementById('maxTokens');
const temperature = document.getElementById('temperature');
const temperatureValue = document.getElementById('temperatureValue');
const streamResponse = document.getElementById('streamResponse');

// Application State
let conversationHistory = [];

// Initialize
document.addEventListener('DOMContentLoaded', () => {
    setupEventListeners();
    loadSettings();
    checkServerConnection();
    messageInput.focus();
});

// Check Server Connection
async function checkServerConnection() {
    try {
        const response = await fetch(`${API_BASE_URL}/health`);
        if (response.ok) {
            const data = await response.json();
            if (data.anthropic_configured) {
                statusIndicator.innerHTML = '<i class="fas fa-circle"></i> Ready';
                statusIndicator.querySelector('i').style.color = 'var(--success-color)';
            } else {
                statusIndicator.innerHTML = '<i class="fas fa-circle"></i> API Key Missing';
                statusIndicator.querySelector('i').style.color = 'var(--warning-color)';
                if (window.advancedFeatures) {
                    window.advancedFeatures.showToast('API key not configured in backend', 'error');
                }
            }
        }
    } catch (error) {
        statusIndicator.innerHTML = '<i class="fas fa-circle"></i> Server Offline';
        statusIndicator.querySelector('i').style.color = 'var(--danger-color)';
        console.warn('Server connection check failed:', error);
        
        // Show helpful message
        if (window.advancedFeatures) {
            const welcomeMsg = document.querySelector('.welcome-message');
            if (welcomeMsg) {
                const warning = document.createElement('div');
                warning.style.cssText = 'background: #fee; border: 1px solid #fcc; padding: 1rem; border-radius: 0.5rem; margin-top: 1rem; color: #c33;';
                warning.innerHTML = `
                    <strong><i class="fas fa-exclamation-triangle"></i> Server Not Running</strong><br>
                    Please start the Flask server first:<br>
                    <code style="background: #fff; padding: 0.25rem 0.5rem; border-radius: 0.25rem; display: inline-block; margin-top: 0.5rem;">python app.py</code>
                `;
                welcomeMsg.appendChild(warning);
            }
        }
    }
}

// Event Listeners Setup
function setupEventListeners() {
    // Send message
    sendBtn.addEventListener('click', sendMessage);
    messageInput.addEventListener('keydown', (e) => {
        if (e.key === 'Enter' && !e.shiftKey) {
            e.preventDefault();
            sendMessage();
        }
    });

    // Auto-resize textarea
    messageInput.addEventListener('input', () => {
        messageInput.style.height = 'auto';
        messageInput.style.height = messageInput.scrollHeight + 'px';
        updateCharCount();
    });

    // Settings sidebar
    settingsBtn.addEventListener('click', () => {
        sidebar.classList.add('active');
    });
    closeSidebar.addEventListener('click', () => {
        sidebar.classList.remove('active');
    });

    // Temperature slider
    temperature.addEventListener('input', (e) => {
        temperatureValue.textContent = e.target.value;
    });

    // Clear chat
    clearChatBtn.addEventListener('click', clearChat);

    // Attach file (placeholder)
    attachBtn.addEventListener('click', () => {
        alert('File attachment feature coming soon!');
    });
}

// Update character count
function updateCharCount() {
    const count = messageInput.value.length;
    charCount.textContent = `${count} characters`;
}

// Send Message Function
async function sendMessage() {
    const message = messageInput.value.trim();
    const fileInput = document.getElementById('fileInput');
    let fileData = null;
    let fileType = null;

    // Handle file if selected
    if (fileInput && fileInput.files.length > 0 && window.advancedFeatures && window.advancedFeatures.selectedFile) {
        const file = window.advancedFeatures.selectedFile;
        fileType = file.type;
        
        // Convert file to base64
        try {
            fileData = await new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.onload = (e) => {
                    // Remove data URL prefix
                    const base64 = e.target.result.split(',')[1];
                    resolve(base64);
                };
                reader.onerror = reject;
                reader.readAsDataURL(file);
            });
        } catch (error) {
            console.error('Error reading file:', error);
            if (window.advancedFeatures) {
                window.advancedFeatures.showToast('Error reading file', 'error');
            }
            return;
        }
    }

    if (!message && !fileData) return;

    // Store user content for history (needed in multiple places)
    const userContent = message || (fileData ? `[File: ${fileInput?.files[0]?.name || 'attachment'}]` : '');

    // Add user message to UI
    addMessage('user', userContent);
    
    // Clear input and file
    messageInput.value = '';
    messageInput.style.height = 'auto';
    updateCharCount();
    if (fileInput) fileInput.value = '';
    if (window.advancedFeatures) window.advancedFeatures.selectedFile = null;
    
    // Disable send button
    sendBtn.disabled = true;
    
    // Show loading
    showLoading(true);

    try {
        // Prepare request
        const requestData = {
            message: message || '',
            model: modelSelect.value,
            max_tokens: parseInt(maxTokens.value),
            temperature: parseFloat(temperature.value),
            stream: streamResponse.checked,
            conversation_history: conversationHistory
        };

        // Add file data if available
        if (fileData) {
            requestData.file_data = fileData;
            requestData.file_type = fileType;
        }

        // Make API call
        const response = await fetch(`${API_BASE_URL}/chat`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(requestData)
        });

        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }

        // Handle streaming vs non-streaming
        const streamingIndicator = document.getElementById('streamingIndicator');
        if (streamResponse.checked && response.body && !response.headers.get('content-type')?.includes('application/json')) {
            // Streaming response
            showLoading(false);
            if (streamingIndicator) streamingIndicator.style.display = 'block';

            const reader = response.body.getReader();
            const decoder = new TextDecoder();
            let assistantMessage = '';
            let messageElement = null;

            try {
                while (true) {
                    const { done, value } = await reader.read();
                    if (done) break;

                    const chunk = decoder.decode(value);
                    const lines = chunk.split('\n');

                    for (const line of lines) {
                        if (line.startsWith('data: ')) {
                            const data = line.slice(6);
                            if (data === '[DONE]') continue;
                            
                            try {
                                const json = JSON.parse(data);
                                if (json.response) {
                                    assistantMessage += json.response;
                                    if (!messageElement) {
                                        messageElement = addMessage('assistant', assistantMessage, true);
                                    } else {
                                        const messageText = messageElement.querySelector('.message-text');
                                        if (messageText && typeof marked !== 'undefined') {
                                            messageText.innerHTML = marked.parse(assistantMessage);
                                            if (typeof hljs !== 'undefined') {
                                                messageText.querySelectorAll('pre code').forEach((block) => {
                                                    hljs.highlightElement(block);
                                                });
                                            }
                                        } else {
                                            messageText.textContent = assistantMessage;
                                        }
                                        chatMessages.scrollTop = chatMessages.scrollHeight;
                                    }
                                }
                            } catch (e) {
                                // Skip invalid JSON
                            }
                        }
                    }
                }
            } catch (error) {
                console.error('Streaming error:', error);
                if (window.advancedFeatures) {
                    window.advancedFeatures.showToast('Streaming error occurred', 'error');
                }
            } finally {
                // Remove streaming class and indicator
                if (messageElement) {
                    messageElement.classList.remove('streaming');
                }
                if (streamingIndicator) streamingIndicator.style.display = 'none';
            }

            // Update conversation history
            conversationHistory.push(
                { role: 'user', content: userContent },
                { role: 'assistant', content: assistantMessage }
            );

            // Update API usage if available
            if (window.advancedFeatures) {
                window.advancedFeatures.updateAPIUsage(0, assistantMessage.split(' ').length * 1.3);
            }
        } else {
            // Non-streaming response
            const data = await response.json();
            
            // Add assistant response to UI
            addMessage('assistant', data.response);
            
            // Update conversation history
            conversationHistory.push(
                { role: 'user', content: userContent },
                { role: 'assistant', content: data.response }
            );

            // Update API usage
            if (data.usage && window.advancedFeatures) {
                window.advancedFeatures.updateAPIUsage(data.usage.input_tokens, data.usage.output_tokens);
            }
        }

    } catch (error) {
        console.error('Error:', error);
        let errorMessage = 'Sorry, I encountered an error. ';
        
        if (error.message.includes('Failed to fetch') || error.message.includes('NetworkError')) {
            errorMessage += 'The backend server is not running or not accessible.\n\n';
            errorMessage += 'Please:\n';
            errorMessage += '1. Make sure Flask server is running: `python app.py`\n';
            errorMessage += '2. Check that the server is running on http://localhost:5000\n';
            errorMessage += '3. If opening HTML directly, use a local server instead\n';
            errorMessage += '4. Check your firewall settings';
        } else if (error.message.includes('404')) {
            errorMessage += 'API endpoint not found. Please check the server is running correctly.';
        } else if (error.message.includes('500')) {
            errorMessage += 'Server error. Please check:\n';
            errorMessage += '1. ANTHROPIC_API_KEY is set in .env file\n';
            errorMessage += '2. API key is valid\n';
            errorMessage += '3. Check server logs for details';
        } else {
            errorMessage += error.message;
        }
        
        addMessage('assistant', errorMessage);
        
        // Show toast notification
        if (window.advancedFeatures) {
            window.advancedFeatures.showToast('Connection error - Check server', 'error');
        }
    } finally {
        showLoading(false);
        sendBtn.disabled = false;
        messageInput.focus();
    }
}

// Add Message to UI with Markdown and Code Highlighting
function addMessage(role, content, isStreaming = false) {
    // Remove welcome message if exists
    const welcomeMsg = chatMessages.querySelector('.welcome-message');
    if (welcomeMsg) {
        welcomeMsg.remove();
    }

    // Check if we're updating an existing streaming message
    let messageDiv = chatMessages.querySelector('.message.streaming');
    let messageText, messageContent;

    if (!messageDiv || !isStreaming) {
        messageDiv = document.createElement('div');
        messageDiv.className = `message ${role}`;
        if (isStreaming) messageDiv.classList.add('streaming');
        
        const avatar = document.createElement('div');
        avatar.className = 'message-avatar';
        avatar.innerHTML = role === 'user' 
            ? '<i class="fas fa-user"></i>' 
            : '<i class="fas fa-robot"></i>';
        
        messageContent = document.createElement('div');
        messageContent.className = 'message-content';
        
        messageText = document.createElement('div');
        messageText.className = 'message-text';
        
        const messageActions = document.createElement('div');
        messageActions.className = 'message-actions';
        if (role === 'assistant') {
            messageActions.innerHTML = `
                <button class="action-btn" onclick="copyMessage(this)" title="Copy">
                    <i class="fas fa-copy"></i>
                </button>
                <button class="action-btn" onclick="readMessage(this)" title="Read">
                    <i class="fas fa-volume-up"></i>
                </button>
                <button class="action-btn" onclick="likeMessage(this)" title="Like">
                    <i class="fas fa-thumbs-up"></i>
                </button>
            `;
        }
        
        const messageTime = document.createElement('span');
        messageTime.className = 'message-time';
        messageTime.textContent = new Date().toLocaleTimeString();
        
        messageContent.appendChild(messageText);
        messageContent.appendChild(messageActions);
        messageContent.appendChild(messageTime);
        
        messageDiv.appendChild(avatar);
        messageDiv.appendChild(messageContent);
        
        chatMessages.appendChild(messageDiv);
    } else {
        messageText = messageDiv.querySelector('.message-text');
        messageContent = messageDiv.querySelector('.message-content');
    }

    // Render markdown for assistant messages
    if (role === 'assistant' && typeof marked !== 'undefined') {
        // Configure marked options
        marked.setOptions({
            breaks: true,
            gfm: true,
            highlight: function(code, lang) {
                if (lang && typeof hljs !== 'undefined') {
                    try {
                        return hljs.highlight(code, { language: lang }).value;
                    } catch (err) {
                        return hljs.highlightAuto(code).value;
                    }
                }
                return code;
            }
        });
        
        messageText.innerHTML = marked.parse(content);
        
        // Highlight code blocks
        if (typeof hljs !== 'undefined') {
            messageText.querySelectorAll('pre code').forEach((block) => {
                hljs.highlightElement(block);
            });
        }
    } else {
        messageText.textContent = content;
    }
    
    chatMessages.scrollTop = chatMessages.scrollHeight;
    
    // Auto voice output if enabled
    if (role === 'assistant' && !isStreaming) {
        const autoVoice = document.getElementById('autoVoiceOutput')?.checked;
        if (autoVoice && window.advancedFeatures) {
            setTimeout(() => window.advancedFeatures.readLastMessage(), 500);
        }
    }

    return messageDiv;
}

// Copy Message Function
function copyMessage(btn) {
    const message = btn.closest('.message');
    const text = message.querySelector('.message-text').textContent;
    navigator.clipboard.writeText(text).then(() => {
        btn.innerHTML = '<i class="fas fa-check"></i>';
        setTimeout(() => {
            btn.innerHTML = '<i class="fas fa-copy"></i>';
        }, 2000);
        if (window.advancedFeatures) {
            window.advancedFeatures.showToast('Message copied!', 'success');
        }
    });
}

// Read Message Function
function readMessage(btn) {
    if (window.advancedFeatures) {
        window.advancedFeatures.readLastMessage();
    }
}

// Like Message Function
function likeMessage(btn) {
    btn.classList.toggle('liked');
    const icon = btn.querySelector('i');
    if (btn.classList.contains('liked')) {
        icon.className = 'fas fa-thumbs-up';
        if (window.advancedFeatures) {
            window.advancedFeatures.showToast('Thanks for the feedback!', 'success');
        }
    } else {
        icon.className = 'fas fa-thumbs-up';
    }
}

// Show/Hide Loading Overlay
function showLoading(show) {
    loadingOverlay.style.display = show ? 'flex' : 'none';
    if (show) {
        statusIndicator.innerHTML = '<i class="fas fa-circle"></i> Processing...';
        statusIndicator.querySelector('i').style.color = 'var(--warning-color)';
    } else {
        statusIndicator.innerHTML = '<i class="fas fa-circle"></i> Ready';
        statusIndicator.querySelector('i').style.color = 'var(--success-color)';
    }
}

// Clear Chat
function clearChat() {
    if (confirm('Are you sure you want to clear the chat history?')) {
        conversationHistory = [];
        chatMessages.innerHTML = `
            <div class="welcome-message">
                <div class="welcome-icon">
                    <i class="fas fa-comments"></i>
                </div>
                <h2>Welcome to Claude Chatbot</h2>
                <p>Experience advanced conversational AI with Anthropic Claude. Ask me anything!</p>
                <div class="feature-list">
                    <span class="feature-tag"><i class="fas fa-check"></i> Long Context Support</span>
                    <span class="feature-tag"><i class="fas fa-check"></i> Advanced Reasoning</span>
                    <span class="feature-tag"><i class="fas fa-check"></i> Safe AI Interactions</span>
                </div>
            </div>
        `;
    }
}

// Load Settings from LocalStorage
function loadSettings() {
    const savedModel = localStorage.getItem('claude_model');
    const savedMaxTokens = localStorage.getItem('claude_max_tokens');
    const savedTemperature = localStorage.getItem('claude_temperature');
    const savedStream = localStorage.getItem('claude_stream');

    if (savedModel) modelSelect.value = savedModel;
    if (savedMaxTokens) maxTokens.value = savedMaxTokens;
    if (savedTemperature) {
        temperature.value = savedTemperature;
        temperatureValue.textContent = savedTemperature;
    }
    if (savedStream) streamResponse.checked = savedStream === 'true';
}

// Save Settings to LocalStorage
function saveSettings() {
    localStorage.setItem('claude_model', modelSelect.value);
    localStorage.setItem('claude_max_tokens', maxTokens.value);
    localStorage.setItem('claude_temperature', temperature.value);
    localStorage.setItem('claude_stream', streamResponse.checked);
}

// Save settings on change
modelSelect.addEventListener('change', saveSettings);
maxTokens.addEventListener('change', saveSettings);
temperature.addEventListener('change', saveSettings);
streamResponse.addEventListener('change', saveSettings);

552 lines•21.2 KB
javascript
app.py
Raw Download
Find: Go to:
"""
Anthropic Claude Chatbot - Flask Backend
Project: Anthropic Claude Chatbot
Category: OpenAI Integration
Year: 2026

Developer Details:
- Website: https://rskworld.in
- Email: help@rskworld.in, support@rskworld.in
- Phone: +91 93305 39277
- Organization: RSK World
- Founder: Molla Samser
- Designer & Tester: Rima Khatun
"""

from flask import Flask, request, jsonify, Response, stream_with_context
from flask_cors import CORS
from anthropic import Anthropic
import os
from dotenv import load_dotenv
import logging
import base64
import json

# Load environment variables
load_dotenv()

# Initialize Flask app
app = Flask(__name__)
CORS(app)  # Enable CORS for frontend

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Initialize Anthropic client
anthropic_client = None
try:
    api_key = os.getenv('ANTHROPIC_API_KEY')
    if api_key:
        anthropic_client = Anthropic(api_key=api_key)
        logger.info("Anthropic client initialized successfully")
    else:
        logger.warning("ANTHROPIC_API_KEY not found in environment variables")
except Exception as e:
    logger.error(f"Error initializing Anthropic client: {e}")


@app.route('/api/health', methods=['GET'])
def health_check():
    """
    Health check endpoint to verify API status
    """
    return jsonify({
        'status': 'healthy',
        'anthropic_configured': anthropic_client is not None
    }), 200


@app.route('/api/chat', methods=['POST'])
def chat():
    """
    Main chat endpoint that handles conversations with Claude
    """
    try:
        if not anthropic_client:
            return jsonify({
                'error': 'Anthropic API key not configured. Please set ANTHROPIC_API_KEY in your .env file.'
            }), 500

        # Get request data
        data = request.get_json()
        message = data.get('message', '')
        model = data.get('model', 'claude-3-5-sonnet-20241022')
        max_tokens = data.get('max_tokens', 1024)
        temperature = data.get('temperature', 0.7)
        conversation_history = data.get('conversation_history', [])
        stream = data.get('stream', False)

        # Validate input
        if not message and not data.get('file_data'):
            return jsonify({'error': 'Message or file is required'}), 400

        # Prepare messages for Claude API
        messages = []
        
        # Add conversation history
        for msg in conversation_history:
            msg_content = msg.get('content', '')
            # Handle both string and list content formats
            if isinstance(msg_content, list):
                messages.append({
                    'role': msg.get('role', 'user'),
                    'content': msg_content
                })
            else:
                messages.append({
                    'role': msg.get('role', 'user'),
                    'content': msg_content
                })
        
        # Prepare current message content
        current_content = []
        if message:
            current_content.append({
                'type': 'text',
                'text': message
            })
        
        # Handle file uploads (images)
        file_data = data.get('file_data')
        if file_data:
            try:
                # file_data should be base64 encoded
                file_type = data.get('file_type', 'image/png')
                current_content.append({
                    'type': 'image',
                    'source': {
                        'type': 'base64',
                        'media_type': file_type,
                        'data': file_data
                    }
                })
            except Exception as e:
                logger.error(f"Error processing file: {e}")
                return jsonify({'error': f'Error processing file: {str(e)}'}), 400
        
        # Add current message
        if len(current_content) > 1 or file_data:
            messages.append({
                'role': 'user',
                'content': current_content
            })
        elif current_content and len(current_content) > 0:
            messages.append({
                'role': 'user',
                'content': current_content[0]['text']
            })
        else:
            messages.append({
                'role': 'user',
                'content': message
            })

        # Create message with Claude API
        try:
            # Handle streaming
            if stream:
                def generate():
                    try:
                        with anthropic_client.messages.stream(
                            model=model,
                            max_tokens=max_tokens,
                            temperature=temperature,
                            messages=messages,
                            system="You are a helpful, harmless, and honest AI assistant. Provide clear and accurate responses."
                        ) as stream_obj:
                            for text_block in stream_obj.text_stream:
                                yield f"data: {json.dumps({'response': text_block})}\n\n"
                            # Get final usage stats
                            try:
                                final_message = stream_obj.get_final_message()
                                usage = {
                                    'input_tokens': final_message.usage.input_tokens,
                                    'output_tokens': final_message.usage.output_tokens
                                }
                                yield f"data: {json.dumps({'usage': usage, 'done': True})}\n\n"
                            except:
                                pass
                        yield "data: [DONE]\n\n"
                    except Exception as e:
                        yield f"data: {json.dumps({'error': str(e)})}\n\n"
                
                return Response(
                    stream_with_context(generate()),
                    mimetype='text/event-stream',
                    headers={
                        'Cache-Control': 'no-cache',
                        'Connection': 'keep-alive',
                        'X-Accel-Buffering': 'no',
                        'Access-Control-Allow-Origin': '*'
                    }
                )
            
            # Non-streaming response
            response = anthropic_client.messages.create(
                model=model,
                max_tokens=max_tokens,
                temperature=temperature,
                messages=messages,
                system="You are a helpful, harmless, and honest AI assistant. Provide clear and accurate responses."
            )

            # Extract response text
            response_text = ""
            if response.content:
                for block in response.content:
                    if hasattr(block, 'text'):
                        response_text += block.text

            logger.info(f"Successfully processed chat request with model {model}")

            return jsonify({
                'response': response_text,
                'model': model,
                'usage': {
                    'input_tokens': response.usage.input_tokens,
                    'output_tokens': response.usage.output_tokens
                }
            }), 200

        except Exception as api_error:
            logger.error(f"Anthropic API error: {api_error}")
            return jsonify({
                'error': f'Anthropic API error: {str(api_error)}'
            }), 500

    except Exception as e:
        logger.error(f"Error in chat endpoint: {e}")
        return jsonify({
            'error': f'Internal server error: {str(e)}'
        }), 500


@app.route('/api/models', methods=['GET'])
def get_models():
    """
    Get available Claude models
    """
    models = [
        {
            'id': 'claude-3-5-sonnet-20241022',
            'name': 'Claude 3.5 Sonnet',
            'description': 'Latest and most capable model with advanced reasoning'
        },
        {
            'id': 'claude-3-opus-20240229',
            'name': 'Claude 3 Opus',
            'description': 'Most powerful model for complex tasks'
        },
        {
            'id': 'claude-3-sonnet-20240229',
            'name': 'Claude 3 Sonnet',
            'description': 'Balanced performance and speed'
        },
        {
            'id': 'claude-3-haiku-20240307',
            'name': 'Claude 3 Haiku',
            'description': 'Fastest and most cost-effective model'
        }
    ]
    return jsonify({'models': models}), 200


if __name__ == '__main__':
    port = int(os.getenv('PORT', 5000))
    debug = os.getenv('FLASK_ENV') == 'development'
    
    logger.info("=" * 50)
    logger.info("Anthropic Claude Chatbot Server")
    logger.info("=" * 50)
    logger.info(f"Starting server on http://0.0.0.0:{port}")
    logger.info(f"API Health Check: http://localhost:{port}/api/health")
    logger.info(f"Debug mode: {debug}")
    logger.info("=" * 50)
    
    if not anthropic_client:
        logger.warning("⚠️  WARNING: ANTHROPIC_API_KEY not configured!")
        logger.warning("   Please set ANTHROPIC_API_KEY in .env file")
    else:
        logger.info("✅ Anthropic API client initialized successfully")
    
    try:
        app.run(host='0.0.0.0', port=port, debug=debug)
    except OSError as e:
        if "Address already in use" in str(e):
            logger.error(f"❌ Port {port} is already in use!")
            logger.error(f"   Please use a different port or stop the other application")
        else:
            logger.error(f"❌ Error starting server: {e}")

282 lines•9.7 KB
python
.env
Raw Download
Find: Go to:
# Anthropic Claude Chatbot - Environment Variables
# Project: Anthropic Claude Chatbot
# Year: 2026
#
# Developer Details:
# - Website: https://rskworld.in
# - Email: help@rskworld.in, support@rskworld.in
# - Phone: +91 93305 39277
# - Organization: RSK World

# REQUIRED: Anthropic API Key
# Get your API key from: https://console.anthropic.com/
ANTHROPIC_API_KEY=your_anthropic_api_key_here

# Flask Configuration
FLASK_ENV=development
PORT=5000
HOST=0.0.0.0

# CORS Configuration
CORS_ORIGINS=*

# API Configuration
API_BASE_URL=http://localhost:5000
25 lines•578 B
text
env.example
Raw Download
Find: Go to:
# Anthropic Claude Chatbot - Environment Variables
# Project: Anthropic Claude Chatbot
# Category: OpenAI Integration
# Year: 2026
#
# Developer Details:
# - Website: https://rskworld.in
# - Email: help@rskworld.in, support@rskworld.in
# - Phone: +91 93305 39277
# - Organization: RSK World
# - Founder: Molla Samser
# - Designer & Tester: Rima Khatun

# Anthropic API Key - Get your API key from https://console.anthropic.com/
ANTHROPIC_API_KEY=your_anthropic_api_key_here

# Flask Configuration
FLASK_ENV=development
PORT=5000

21 lines•550 B
text
🚀 Support RSK World

Subscribe to our YouTube channel for latest tutorials & updates!



Click subscribe & support our work ❤️

About RSK World

Founded by Molla Samser, with Designer & Tester Rima Khatun, RSK World is your one-stop destination for free programming resources, source code, and development tools.

Founder: Molla Samser
Designer & Tester: Rima Khatun

Development

  • Game Development
  • Web Development
  • Mobile Development
  • AI Development
  • Development Tools

Legal

  • Terms & Conditions
  • Privacy Policy
  • Disclaimer

Contact Info

Nutanhat, Mongolkote
Purba Burdwan, West Bengal
India, 713147

+91 93305 39277

hello@rskworld.in
support@rskworld.in

© 2026 RSK World. All rights reserved.

Content used for educational purposes only. View Disclaimer