| import os |
| import logging |
| import asyncio |
| import uvicorn |
| import torch |
| import random |
| from transformers import AutoModelForCausalLM, AutoTokenizer |
| from fastapi import FastAPI, Query, HTTPException |
| from fastapi.responses import HTMLResponse |
| from typing import List |
| import concurrent.futures |
|
|
| |
| logging.basicConfig(level=logging.DEBUG) |
| logger = logging.getLogger(__name__) |
|
|
| |
| app = FastAPI() |
|
|
| |
| model_dict = {} |
| model_lock = asyncio.Lock() |
|
|
| |
| message_history = [] |
|
|
| |
| models_to_load = ["gpt2-medium", "gpt2-large", "gpt2"] |
| for model_name in models_to_load: |
| model = AutoModelForCausalLM.from_pretrained(model_name) |
| tokenizer = AutoTokenizer.from_pretrained(model_name) |
| model_dict[model_name] = (model, tokenizer) |
| logger.info(f"Successfully loaded {model_name} model") |
|
|
|
|
| |
| @app.get('/') |
| async def main(): |
| html_code = """ |
| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>ChatGPT Chatbot</title> |
| <style> |
| body, html { |
| height: 100%; |
| margin: 0; |
| padding: 0; |
| font-family: Arial, sans-serif; |
| } |
| .container { |
| height: 100%; |
| display: flex; |
| flex-direction: column; |
| justify-content: center; |
| align-items: center; |
| } |
| .chat-container { |
| border-radius: 10px; |
| overflow: hidden; |
| box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); |
| width: 100%; |
| height: 100%; |
| animation: fadeIn 1s ease; |
| } |
| .chat-box { |
| height: calc(100% - 60px); |
| overflow-y: auto; |
| padding: 10px; |
| } |
| .chat-input { |
| width: calc(100% - 100px); |
| padding: 10px; |
| border: none; |
| border-top: 1px solid #ccc; |
| font-size: 16px; |
| flex-grow: 1; |
| box-sizing: border-box; |
| } |
| .input-container { |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| padding: 10px; |
| background-color: #f5f5f5; |
| border-top: 1px solid #ccc; |
| width: 100%; |
| box-sizing: border-box; |
| } |
| button { |
| padding: 10px; |
| border: none; |
| cursor: pointer; |
| background-color: #007bff; |
| color: #fff; |
| font-size: 16px; |
| flex-shrink: 0; |
| } |
| .user-message { |
| background-color: #cce5ff; |
| border-radius: 5px; |
| align-self: flex-end; |
| max-width: 70%; |
| margin-left: auto; |
| margin-right: 10px; |
| margin-bottom: 10px; |
| animation: slideInFromRight 0.5s ease; |
| } |
| .bot-message { |
| background-color: #d1ecf1; |
| border-radius: 5px; |
| align-self: flex-start; |
| max-width: 70%; |
| margin-bottom: 10px; |
| animation: slideInFromLeft 0.5s ease; |
| } |
| |
| @keyframes fadeIn { |
| 0% { |
| opacity: 0; |
| } |
| 100% { |
| opacity: 1; |
| } |
| } |
| |
| @keyframes slideInFromRight { |
| 0% { |
| transform: translateX(100%); |
| } |
| 100% { |
| transform: translateX(0); |
| } |
| } |
| |
| @keyframes slideInFromLeft { |
| 0% { |
| transform: translateX(-100%); |
| } |
| 100% { |
| transform: translateX(0); |
| } |
| } |
| </style> |
| </head> |
| <body> |
| <div class="container"> |
| <div class="chat-container"> |
| <div class="chat-box" id="chat-box"></div> |
| <div class="input-container"> |
| <input type="text" class="chat-input" id="user-input" placeholder="Escribe un mensaje..."> |
| <button onclick="sendMessage()">Enviar</button> |
| </div> |
| </div> |
| </div> |
| <script> |
| const chatBox = document.getElementById('chat-box'); |
| const userInput = document.getElementById('user-input'); |
| |
| async function sendMessage() { |
| const userMessage = userInput.value.trim(); |
| if (!userMessage) return; |
| |
| saveMessage('user', userMessage); |
| |
| fetch(`/autocomplete?q=${userMessage}`) |
| .then(response => response.text()) |
| .then(data => { |
| saveMessage('bot', data); |
| chatBox.scrollTop = chatBox.scrollHeight; |
| }) |
| .catch(error => { |
| console.error('Error:', error); |
| }); |
| } |
| |
| function saveMessage(sender, message) { |
| const messageElement = document.createElement('div'); |
| messageElement.textContent = `${sender}: ${message}`; |
| messageElement.classList.add(`${sender}-message`); |
| chatBox.appendChild(messageElement); |
| userInput.value = ''; |
| } |
| |
| userInput.addEventListener("keyup", function(event) { |
| if (event.keyCode === 13) { |
| event.preventDefault(); |
| sendMessage(); |
| } |
| }); |
| </script> |
| </body> |
| </html> |
| """ |
| return HTMLResponse(content=html_code, status_code=200) |
|
|
| |
| @app.get('/autocomplete') |
| async def autocomplete(q: str = Query(...)): |
| global model_dict, message_history |
|
|
| |
| async def generate_response(model, tokenizer, q): |
| input_ids = tokenizer.encode(q, return_tensors="pt") |
| output = model.generate(input_ids, max_length=150, num_return_sequences=1) |
| response_text = tokenizer.decode(output[0], skip_special_tokens=True) |
| return response_text |
|
|
| responses = [] |
| for model_name, (model, tokenizer) in model_dict.items(): |
| responses.append(generate_response(model, tokenizer, q)) |
|
|
| responses = await asyncio.gather(*responses) |
|
|
| |
| coherent_response = max(responses, key=lambda x: len(x.split())) |
| message_history.append(coherent_response) |
|
|
| sorted_responses = sorted(responses, key=lambda x: len(x.split())) |
|
|
| |
| best_responses = sorted_responses[-min(3, len(sorted_responses)):] |
| response_text = random.choice(best_responses) |
|
|
| |
| message_history.append(q) |
| message_history.append(response_text) |
|
|
| return response_text |
|
|
| |
| def run_app(): |
| uvicorn.run(app, host='0.0.0.0', port=7860) |
|
|
| |
| if __name__ == "__main__": |
| run_app() |
|
|
|
|