diff --git a/smartassist/src/backend.py b/smartassist/src/backend.py index e98261b..6c9222a 100644 --- a/smartassist/src/backend.py +++ b/smartassist/src/backend.py @@ -1,7 +1,7 @@ # Import the necessary functions from ollama, Flask, requests, threading from ollama import Client -from flask import Flask, request, jsonify, send_from_directory, render_template +from flask import Flask, request, jsonify, send_from_directory, render_template, session from flask_cors import CORS, cross_origin # CORS stands for Cross-Origin Resource Sharing. This is necessary to allow the frontend to make requests to our backend. import requests import json @@ -11,11 +11,8 @@ import utils from utils import GlobalState # Create a logger for this module -# logger = logging.getLogger(__name__) # This logger will be used to log messages from this module -# logger.debug("Logging level of backend logger has been configured") global_state = GlobalState() # Import the singleton that holds global states (e.g., logger) logger = global_state.getLogger(__name__) # Logger for this module, inherit properties of the root logger -# llm = global_state.get_llm() # Find out the path to current directory according to the Python interpreter (venv) @@ -25,6 +22,15 @@ logger.debug("Current working directory: %s", os.getcwd()) app = Flask(__name__) app.config['STATIC_FOLDER'] = 'static' # Adjust if needed +# Set the secret key for session management +secret_key = os.urandom(24) +app.config['SECRET_KEY'] = secret_key # When do I need this. How is it retained between sessions? + +# Optionally set other configuration options +app.config['SESSION_PERMANENT'] = False # Session will expire after each request +app.config['SESSION_TYPE'] = 'filesystem' # Store sessions on the filesystem + + logger.debug("flask app template folder: %s", app.template_folder) @app.route('/') @@ -33,6 +39,7 @@ def index(): This route serves index.html to connecting clients """ + session['chat_history'] = [] # The session object (actually, a dictonary) holds the chat session logger.debug("Entering route '/'") api_endpoint = os.environ['BE_API_ENDPOINT'] # Retrieve the environment variable logger.debug("API endpoint: %s", api_endpoint) @@ -44,6 +51,17 @@ def index(): return render_template('index.html', api_endpoint=api_endpoint, use_model = use_model, client_content=client_html) +@app.route('/profile') +def profile(): + # Retrieve data from the session + user_id = session.get('user_id') + + if user_id: + return f'User ID: {user_id}' + else: + return 'No user ID found' + + @app.route('/') def serve_static(filename): return send_from_directory(app.config['STATIC_FOLDER'], filename) @@ -62,6 +80,50 @@ CORS(app, resources={ } }) +# @app.route('/api/memfree_chat', methods=['POST']) +# def chat(url_server = "http://localhost:11434/api/generate", model = "phi3:mini"): +# """ +# This function handles the chat. The frontend client (web browser) calls the +# backend server through this endpoint (/api/chat) that manage queries +# to the LLM (Large Language Model) server and it also manages the response +# from the LLM server. +# """ +# # Get the message from the JSON in the request body +# data = request.get_json() +# message = data.get('query') +# url_server = data.get('url_server', url_server) # Use provided URL or default +# model = data.get('model', model) # Use provided model or default +# logger.debug("data = %s\nmessage = %s", str(data), str(message)) +# try: +# url = url_server +# model_to_use = model +# data = { +# "model": model_to_use, +# 'prompt': message, +# "stream": False +# } +# headers = { +# "Content-Type": "application/json", +# } +# # With API key +# # headers = { +# # "Content-Type": "application/json", +# # "Authorization": "Bearer YOUR_API_KEY" # Replace with your API key +# # } + +# response = requests.post(url, +# headers=headers, +# data=json.dumps(data)) +# response.raise_for_status() # Raise an exception for bad status codes +# return response.json() +# except requests.exceptions.RequestException as e: +# logger.error("Request Exception: %s", str(e)) +# return jsonify({'error': 'Failed to process request'}), 500 +# except json.JSONDecodeError as e: +# logger.error("JSON Decode Error: %s", str(e)) # Corresponds to print(f"JSON Decode Error: {e}") +# return jsonify({'error': 'Invalid JSON response from server'}), 500 + + @app.route('/api/chat', methods=['POST']) def chat(url_server = "http://localhost:11434/api/generate", model = "phi3:mini"): """ @@ -75,28 +137,35 @@ def chat(url_server = "http://localhost:11434/api/generate", model = "phi3:mini" message = data.get('query') url_server = data.get('url_server', url_server) # Use provided URL or default model = data.get('model', model) # Use provided model or default - logger.debug("data = %s\nmessage = %s", str(data), str(message)) + + # Get chat history from session storage (e.g., a dictionary) + chat_history = session.get('chat_history', []) + + # Add the new message to the chat history + chat_history.append({'role': 'user', 'message': message}) + logger.debug(f"Chat History: {chat_history}") + + # Update the session with the new chat history + session['chat_history'] = chat_history + + # Create the data dictionary with chat history + data_to_send = { + "model": model, + 'prompt': '\n'.join([f"{item['role']}: {item['message']}" for item in chat_history]), + "stream": False + } + try: url = url_server - model_to_use = model - data = { - "model": model_to_use, - 'prompt': message, - "stream": False - } headers = { "Content-Type": "application/json", } - # With API key - # headers = { - # "Content-Type": "application/json", - # "Authorization": "Bearer YOUR_API_KEY" # Replace with your API key - # } - + response = requests.post(url, headers=headers, - data=json.dumps(data)) + data=json.dumps(data_to_send)) response.raise_for_status() # Raise an exception for bad status codes + return response.json() except requests.exceptions.RequestException as e: logger.error("Request Exception: %s", str(e)) @@ -106,6 +175,7 @@ def chat(url_server = "http://localhost:11434/api/generate", model = "phi3:mini" return jsonify({'error': 'Invalid JSON response from server'}), 500 + @app.route('/smartassist', methods=["POST"]) def smartassist(): # Extract the query from the incoming JSON data