Setting up the chat client functionality using SocketIO - Start
This commit is contained in:
@@ -5,6 +5,7 @@ from flask_security import Security
|
|||||||
from flask_mailman import Mail
|
from flask_mailman import Mail
|
||||||
from flask_login import LoginManager
|
from flask_login import LoginManager
|
||||||
from flask_cors import CORS
|
from flask_cors import CORS
|
||||||
|
from flask_socketio import SocketIO
|
||||||
|
|
||||||
|
|
||||||
# Create extensions
|
# Create extensions
|
||||||
@@ -15,3 +16,4 @@ security = Security()
|
|||||||
mail = Mail()
|
mail = Mail()
|
||||||
login_manager = LoginManager()
|
login_manager = LoginManager()
|
||||||
cors = CORS()
|
cors = CORS()
|
||||||
|
socketio = SocketIO()
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
from ..extensions import db
|
||||||
|
from .user import User, Tenant
|
||||||
|
|
||||||
|
|
||||||
|
class ChatSession(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
user_id = db.Column(db.Integer, db.ForeignKey('public.user.id'), nullable=True)
|
||||||
|
session_start = db.Column(db.DateTime, nullable=False)
|
||||||
|
session_end = db.Column(db.DateTime, nullable=True)
|
||||||
|
|
||||||
|
# Relations
|
||||||
|
chat_interactions = db.relationship('Interaction', backref='chat_session', lazy=True)
|
||||||
|
user = db.relationship('User', backref='chat_sessions', lazy=True)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<ChatSession {self.id} by {self.user_id}>"
|
||||||
|
|
||||||
|
|
||||||
|
class Interaction(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
chat_session_id = db.Column(db.Integer, db.ForeignKey('public.chat_session.id'), nullable=False)
|
||||||
|
question = db.Column(db.Text, nullable=False)
|
||||||
|
answer = db.Column(db.Text, nullable=True)
|
||||||
|
language = db.Column(db.String(2), nullable=False)
|
||||||
|
appreciation = db.Column(db.Integer, nullable=True, default=100)
|
||||||
|
|
||||||
|
# Timing information
|
||||||
|
question_at = db.Column(db.DateTime, nullable=False)
|
||||||
|
answer_at = db.Column(db.DateTime, nullable=True)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<Interaction {self.id}>"
|
||||||
|
|
||||||
|
|
||||||
|
class InteractionEmbedding(db.Model):
|
||||||
|
interaction_id = db.Column(db.Integer, db.ForeignKey('interaction.id', ondelete='CASCADE'), primary_key=True)
|
||||||
|
embedding_id = db.Column(db.Integer, db.ForeignKey('embedding.id', ondelete='CASCADE'), primary_key=True)
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ class Config(object):
|
|||||||
Text is delimited between triple backquotes.
|
Text is delimited between triple backquotes.
|
||||||
```{text}```"""
|
```{text}```"""
|
||||||
|
|
||||||
|
# SocketIO settings
|
||||||
|
SOCKETIO_ASYNC_MODE = 'gevent'
|
||||||
|
|
||||||
|
|
||||||
class DevConfig(Config):
|
class DevConfig(Config):
|
||||||
DEVELOPMENT = True
|
DEVELOPMENT = True
|
||||||
@@ -92,6 +95,17 @@ class DevConfig(Config):
|
|||||||
UNSTRUCTURED_BASE_URL = 'https://flowitbv-16c4us0m.api.unstructuredapp.io'
|
UNSTRUCTURED_BASE_URL = 'https://flowitbv-16c4us0m.api.unstructuredapp.io'
|
||||||
UNSTRUCTURED_FULL_URL = 'https://flowitbv-16c4us0m.api.unstructuredapp.io/general/v0/general'
|
UNSTRUCTURED_FULL_URL = 'https://flowitbv-16c4us0m.api.unstructuredapp.io/general/v0/general'
|
||||||
|
|
||||||
|
# SocketIO settings
|
||||||
|
SOCKETIO_MESSAGE_QUEUE = 'redis://localhost:6379/1'
|
||||||
|
SOCKETIO_CORS_ALLOWED_ORIGINS = '*'
|
||||||
|
SOCKETIO_LOGGER = True
|
||||||
|
SOCKETIO_ENGINEIO_LOGGER = True
|
||||||
|
|
||||||
|
# Google Cloud settings
|
||||||
|
GC_PROJECT_NAME = 'EveAI'
|
||||||
|
GC_KEY_RING = 'eveai-chat'
|
||||||
|
GC_CRYPTO_KEY = 'envelope-encryption-key'
|
||||||
|
|
||||||
|
|
||||||
class ProdConfig(Config):
|
class ProdConfig(Config):
|
||||||
DEVELOPMENT = False
|
DEVELOPMENT = False
|
||||||
|
|||||||
@@ -18,6 +18,14 @@ LOGGING = {
|
|||||||
'backupCount': 10,
|
'backupCount': 10,
|
||||||
'formatter': 'standard',
|
'formatter': 'standard',
|
||||||
},
|
},
|
||||||
|
'file_chat': {
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'class': 'logging.handlers.RotatingFileHandler',
|
||||||
|
'filename': 'logs/eveai_chat.log',
|
||||||
|
'maxBytes': 1024*1024*5, # 5MB
|
||||||
|
'backupCount': 10,
|
||||||
|
'formatter': 'standard',
|
||||||
|
},
|
||||||
'console': {
|
'console': {
|
||||||
'class': 'logging.StreamHandler',
|
'class': 'logging.StreamHandler',
|
||||||
'level': 'DEBUG',
|
'level': 'DEBUG',
|
||||||
@@ -40,6 +48,11 @@ LOGGING = {
|
|||||||
'level': 'DEBUG',
|
'level': 'DEBUG',
|
||||||
'propagate': False
|
'propagate': False
|
||||||
},
|
},
|
||||||
|
'eveai_chat': { # logger for the eveai_chat
|
||||||
|
'handlers': ['file_chat', 'console'],
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'propagate': False
|
||||||
|
},
|
||||||
'': { # root logger
|
'': { # root logger
|
||||||
'handlers': ['console'],
|
'handlers': ['console'],
|
||||||
'level': 'WARNING', # Set higher level for root to minimize noise
|
'level': 'WARNING', # Set higher level for root to minimize noise
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
|
|||||||
import logging.config
|
import logging.config
|
||||||
|
|
||||||
from common.extensions import db, migrate, bootstrap, security, mail, login_manager, cors
|
from common.extensions import db, migrate, bootstrap, security, mail, login_manager, cors
|
||||||
from common.models.user import User, Role
|
from common.models.user import User, Role, Tenant, TenantDomain
|
||||||
from config.logging_config import LOGGING
|
from config.logging_config import LOGGING
|
||||||
from common.utils.security import set_tenant_session_data
|
from common.utils.security import set_tenant_session_data
|
||||||
from .errors import register_error_handlers
|
from .errors import register_error_handlers
|
||||||
|
|||||||
33
eveai_chat/__init__.py
Normal file
33
eveai_chat/__init__.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import logging
|
||||||
|
import logging.config
|
||||||
|
from flask import Flask
|
||||||
|
from flask_socketio import emit
|
||||||
|
|
||||||
|
from common.extensions import db, socketio
|
||||||
|
from config.logging_config import LOGGING
|
||||||
|
|
||||||
|
|
||||||
|
def create_app(config_file=None):
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
if config_file is None:
|
||||||
|
app.config.from_object('config.config.DevConfig')
|
||||||
|
else:
|
||||||
|
app.config.from_object(config_file)
|
||||||
|
|
||||||
|
logging.config.dictConfig(LOGGING)
|
||||||
|
register_extensions(app)
|
||||||
|
|
||||||
|
return app
|
||||||
|
|
||||||
|
|
||||||
|
def register_extensions(app):
|
||||||
|
db.init_app(app)
|
||||||
|
socketio.init_app(app,
|
||||||
|
message_queue=app.config.get('SOCKETIO_MESSAGE_QUEUE'),
|
||||||
|
cors_allowed_origins=app.config.get('SOCKETIO_CORS_ALLOWED_ORIGINS'),
|
||||||
|
async_mode=app.config.get('SOCKETIO_ASYNC_MODE'),
|
||||||
|
logger=app.config.get('SOCKETIO_LOGGER'),
|
||||||
|
engineio_logger=app.config.get('SOCKETIO_ENGINEIO_LOGGER'),
|
||||||
|
)
|
||||||
|
|
||||||
34
eveai_chat/views/chat_views.py
Normal file
34
eveai_chat/views/chat_views.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# from . import user_bp
|
||||||
|
import uuid
|
||||||
|
from datetime import datetime as dt, timezone as tz
|
||||||
|
from flask import request, redirect, url_for, flash, render_template, Blueprint, session, current_app
|
||||||
|
from flask_security import hash_password, roles_required, roles_accepted
|
||||||
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
|
|
||||||
|
from common.models.user import User, Tenant
|
||||||
|
from common.models.interaction import ChatSession, Interaction, InteractionEmbedding
|
||||||
|
from common.models.document import Embedding
|
||||||
|
from common.extensions import db, socketio
|
||||||
|
from common.utils.database import Database
|
||||||
|
|
||||||
|
chat_bp = Blueprint('chat_bp', __name__, url_prefix='/chat')
|
||||||
|
|
||||||
|
|
||||||
|
@chat_bp.route('/', methods=['GET', 'POST'])
|
||||||
|
def chat():
|
||||||
|
return render_template('chat.html')
|
||||||
|
|
||||||
|
|
||||||
|
@chat.record_once
|
||||||
|
def on_register(state):
|
||||||
|
# TODO: write initialisation code when the blueprint is registered (only once)
|
||||||
|
# socketio.init_app(state.app)
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@socketio.on('message', namespace='/chat')
|
||||||
|
def handle_message(message):
|
||||||
|
# TODO: write message handling code to actually realise chat
|
||||||
|
# print('Received message:', message)
|
||||||
|
# socketio.emit('response', {'data': message}, namespace='/chat')
|
||||||
|
pass
|
||||||
@@ -9,4 +9,5 @@ celery~=5.4.0
|
|||||||
kombu~=5.3.7
|
kombu~=5.3.7
|
||||||
langchain~=0.1.17
|
langchain~=0.1.17
|
||||||
requests~=2.31.0
|
requests~=2.31.0
|
||||||
beautifulsoup4~=4.12.3
|
beautifulsoup4~=4.12.3
|
||||||
|
google~=3.0.0
|
||||||
14
scripts/run_eveai_chat.py
Normal file
14
scripts/run_eveai_chat.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
from eveai_chat import create_app
|
||||||
|
from gevent.pywsgi import WSGIServer
|
||||||
|
from geventwebsocket.handler import WebSocketHandler
|
||||||
|
|
||||||
|
|
||||||
|
app = create_app()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print("Server starting on port 5001")
|
||||||
|
http_server = WSGIServer(('0.0.0.0', 5001), app, handler_class=WebSocketHandler)
|
||||||
|
http_server.serve_forever() # Continuously listens for incoming requests
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
15
scripts/start_eveai_chat.sh
Executable file
15
scripts/start_eveai_chat.sh
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
cd "/Volumes/OWC4M2_1/Dropbox/Josako's Dev/Josako/EveAI/Development/eveAI/" || exit 1
|
||||||
|
source "/Volumes/OWC4M2_1/Dropbox/Josako's Dev/Josako/EveAI/Development/eveAI/.venv/bin/activate"
|
||||||
|
|
||||||
|
export PYTHONPATH="$PYTHONPATH:/Volumes/OWC4M2_1/Dropbox/Josako's Dev/Josako/EveAI/Development/eveAI/"
|
||||||
|
|
||||||
|
# Set flask environment variables
|
||||||
|
export FLASK_ENV=development # Use 'production' as appropriate
|
||||||
|
export FLASK_DEBUG=1 # Use 0 for production
|
||||||
|
|
||||||
|
# Start Flask app
|
||||||
|
python scripts/run_eveai_chat.py
|
||||||
|
|
||||||
|
deactivate
|
||||||
Reference in New Issue
Block a user