Compare commits
8 Commits
25e5c6acea
...
0cccd02050
| Author | SHA1 | Date | |
|---|---|---|---|
| 0cccd02050 | |||
| e69a131875 | |||
| d797440288 | |||
| 1b5624018c | |||
| 807a766a63 | |||
| 5245e53954 | |||
| d1b0554748 | |||
| f8c3bcd156 |
@@ -67,7 +67,8 @@ def chat(url_server = "http://localhost:11434/api/generate", model = "phi3:mini"
|
|||||||
# Get the message from the JSON in the request body
|
# Get the message from the JSON in the request body
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
message = data.get('query')
|
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))
|
logger.debug("data = %s\nmessage = %s", str(data), str(message))
|
||||||
try:
|
try:
|
||||||
url = url_server
|
url = url_server
|
||||||
|
|||||||
@@ -14,13 +14,28 @@
|
|||||||
<textarea id="userInput" placeholder="Type your message..." rows="5"></textarea>
|
<textarea id="userInput" placeholder="Type your message..." rows="5"></textarea>
|
||||||
<button onclick="sendMessage()">Send</button>
|
<button onclick="sendMessage()">Send</button>
|
||||||
|
|
||||||
|
<!-- Get the apiEndpoint -->
|
||||||
|
<script>
|
||||||
|
const apiEndpoint = window.apiEndpoint;
|
||||||
|
// Debugging – log messages
|
||||||
|
// if (apiEndpoint) {
|
||||||
|
// console.log("client.html - apiEndpoint: ", apiEndpoint);
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// console.log("client.html - cannot find apiEndpoint");
|
||||||
|
// }
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Get the javascript handling communication with the backene -->
|
||||||
<script src="/js/frontend.js"></script>
|
<script src="/js/frontend.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const chatContainer = document.getElementById('chatbox');
|
const chatContainer = document.getElementById('chatbox');
|
||||||
|
|
||||||
// Handle resize events
|
// Handle resize events
|
||||||
window.addEventListener('resize', function() {
|
window.addEventListener('resize',
|
||||||
chatContainer.style.height = 'auto';
|
function() {
|
||||||
|
chatContainer.style.height = 'auto';
|
||||||
});
|
});
|
||||||
|
|
||||||
const userInputElement = document.getElementById('userInput');
|
const userInputElement = document.getElementById('userInput');
|
||||||
@@ -37,6 +52,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ import yaml
|
|||||||
import json
|
import json
|
||||||
import socket
|
import socket
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
from backend import run_flask
|
||||||
import logging
|
import logging
|
||||||
import utils
|
import utils
|
||||||
from utils import configure_logging
|
from utils import GlobalState
|
||||||
from backend import run_flask
|
|
||||||
|
|
||||||
configure_logging() # Configure root logger. The level will be adjusted later based on config file
|
global_state = GlobalState() # Configure root logger. The level will be adjusted later based on config file
|
||||||
logger = logging.getLogger(__name__) # Logger for this module, inherit properties of the root logger
|
logger = global_state.getLogger(__name__) # Logger for this module, inherit properties of the root logger
|
||||||
|
|
||||||
def configure():
|
def configure():
|
||||||
"""
|
"""
|
||||||
@@ -46,17 +46,10 @@ def configure():
|
|||||||
# Extract global logging level
|
# Extract global logging level
|
||||||
####################################
|
####################################
|
||||||
if isinstance(updated_config.get('logging'), dict): # Look for 'logging' key in config file
|
if isinstance(updated_config.get('logging'), dict): # Look for 'logging' key in config file
|
||||||
# logging.info("found key 'logging' in config file")
|
|
||||||
logging_config = updated_config['logging']
|
logging_config = updated_config['logging']
|
||||||
if isinstance(logging_config.get('level'), str): # Set to value of the yaml file if specified
|
if isinstance(logging_config.get('level'), str): # Set to value of the yaml file if specified
|
||||||
# logging.info("found key 'level' in config file")
|
global_state.set_log_level(logging_config['level'])
|
||||||
utils.log_level = logging_config['level']
|
logger.debug("configure(): This logger now has effective log level %s", logger.getEffectiveLevel())
|
||||||
numeric_log_level = getattr(logging, utils.log_level, None)
|
|
||||||
|
|
||||||
rlogger = logging.getLogger() # Get the root logger
|
|
||||||
rlogger.setLevel(numeric_log_level)
|
|
||||||
# set_local_logger(logger) # Set log level for logger based on log_level
|
|
||||||
logger.info("Global variable utils.log_level set to: {}".format(utils.log_level))
|
|
||||||
|
|
||||||
####################################
|
####################################
|
||||||
# Extract and export API endpoint as
|
# Extract and export API endpoint as
|
||||||
@@ -70,7 +63,7 @@ def configure():
|
|||||||
api = updated_config['backend'].get('api')
|
api = updated_config['backend'].get('api')
|
||||||
backend_api_ep = url+api # Extract API endpoint if defined
|
backend_api_ep = url+api # Extract API endpoint if defined
|
||||||
logger.debug("BE_API_ENDPOINT is set to '{}'".format(backend_api_ep))
|
logger.debug("BE_API_ENDPOINT is set to '{}'".format(backend_api_ep))
|
||||||
os.environ['BE_API_ENDPOINT'] = backend_api_ep
|
os.environ['BE_API_ENDPOINT'] = backend_api_ep # Look into alternative way to share this with backend.py
|
||||||
|
|
||||||
return updated_config
|
return updated_config
|
||||||
|
|
||||||
@@ -113,6 +106,6 @@ def start_backend(config):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
conf = configure() # Read config from file and set up config dict
|
conf = configure() # Read config from file and set up config dict
|
||||||
logger.debug('conf dictionary set to {}'.format(json.dumps(conf, indent=4)))
|
logger.debug('conf dictionary set to {}'.format(json.dumps(conf, indent=4)))
|
||||||
# start_frontend(config=conf)
|
# start_frontend(config=conf) # Not needed as we are using Flask for backend now
|
||||||
start_backend(config=conf)
|
start_backend(config=conf)
|
||||||
|
|
||||||
|
|||||||
@@ -3,17 +3,6 @@
|
|||||||
const chatbox = document.getElementById('chatbox');
|
const chatbox = document.getElementById('chatbox');
|
||||||
const userInput = document.getElementById('userInput');
|
const userInput = document.getElementById('userInput');
|
||||||
|
|
||||||
// Get API endpoint for chat from environment variable
|
|
||||||
|
|
||||||
|
|
||||||
// Handle resize events
|
|
||||||
window.addEventListener('resize', () => {
|
|
||||||
chatbox.style.height = 'auto';
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// ... other code for sending messages ...
|
|
||||||
|
|
||||||
// Define a function to send the user's message to the AI
|
// Define a function to send the user's message to the AI
|
||||||
function sendMessage() {
|
function sendMessage() {
|
||||||
// Get the user's input message and trim any whitespace
|
// Get the user's input message and trim any whitespace
|
||||||
@@ -21,12 +10,12 @@ function sendMessage() {
|
|||||||
|
|
||||||
// Check if the message is not empty
|
// Check if the message is not empty
|
||||||
if (query !== '') {
|
if (query !== '') {
|
||||||
// Send a POST request to the /api/chat endpoint with the message
|
|
||||||
// fetch('http://localhost:5005/api/chat', {
|
|
||||||
fetch(`${apiEndpoint}`, {
|
fetch(`${apiEndpoint}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ query }),
|
body: JSON.stringify({ query, model: "phi3:mini" }), // Add these parameters here
|
||||||
|
// body: JSON.stringify({ query, url_server: "http://your-custom-url", model: "phi3:mini" }), // Add these parameters here
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
@@ -60,22 +49,3 @@ function renderMessage(text, className) {
|
|||||||
// Append the message element to the chatbox
|
// Append the message element to the chatbox
|
||||||
chatbox.appendChild(messageElement);
|
chatbox.appendChild(messageElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function handleIframeLoad() {
|
|
||||||
const clientFrame = document.getElementById('client-frame');
|
|
||||||
|
|
||||||
if (clientFrame) { // Check if the iframe exists
|
|
||||||
|
|
||||||
const apiEndpoint = clientFrame.getAttribute('data-api-endpoint') || clientFrame.srcdoc.split('?')[1].split('=')[1];
|
|
||||||
console.log("The API Endpoint is:", apiEndpoint);
|
|
||||||
|
|
||||||
// Now you can use this 'apiEndpoint' for communication
|
|
||||||
|
|
||||||
} else {
|
|
||||||
setTimeout(handleIframeLoad, 200); // Retry in a short while if iframe not found yet
|
|
||||||
console.log("The iframe with id client-frame not found yet");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('load', handleIframeLoad);
|
|
||||||
|
|||||||
@@ -4,19 +4,25 @@
|
|||||||
<!-- <title>Frontend</title> -->
|
<!-- <title>Frontend</title> -->
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script>
|
|
||||||
// Extract apiEndpoint for use in your frontend code...
|
|
||||||
const apiEndpoint = '{{ api_endpoint }}'; // Templating syntax (Jinja2)
|
|
||||||
console.log("index.html - API Endpoint: ", apiEndpoint);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- This iframe will hold the content from client.html -->
|
<!-- This iframe will hold the content from client.html -->
|
||||||
<!-- Passing the API endpoint as a query parameter to the srcdoc attribute -->
|
<!-- Passing the API endpoint as a query parameter to the srcdoc attribute -->
|
||||||
|
<!-- srcdoc="{{ client_content }}?apiEndpoint={{ api_endpoint }}/"> -->
|
||||||
|
|
||||||
<iframe id="client-frame"
|
<iframe id="client-frame"
|
||||||
style="width: 100%; height: 100vh;"
|
style="width: 100%; height: 100vh;"
|
||||||
srcdoc="{{ client_content }}?apiEndpoint={{ api_endpoint }}/">
|
srcdoc="{{ client_content }}">
|
||||||
</iframe>
|
</iframe>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Extract apiEndpoint for use in your frontend code...
|
||||||
|
const apiEndpoint = '{{ api_endpoint }}'; // Templating syntax (Jinja2)
|
||||||
|
// Tell the iframe about the apiEndpoing
|
||||||
|
document.getElementById('client-frame').contentWindow.apiEndpoint = apiEndpoint;
|
||||||
|
console.log("index.html - API Endpoint: ", apiEndpoint);
|
||||||
|
</script>
|
||||||
|
|
||||||
<!-- Responsive scaling and some padding -->
|
<!-- Responsive scaling and some padding -->
|
||||||
<script>
|
<script>
|
||||||
const clientFrame = document.getElementById('client-frame');
|
const clientFrame = document.getElementById('client-frame');
|
||||||
|
|||||||
+44
-25
@@ -2,36 +2,55 @@
|
|||||||
# imported to more than one other module. The rational for defining these things here
|
# imported to more than one other module. The rational for defining these things here
|
||||||
# is that it is easier to avoid circular imports when they are defined in a central location.
|
# is that it is easier to avoid circular imports when they are defined in a central location.
|
||||||
import logging
|
import logging
|
||||||
global log_level # Remember, in Python globals are only global in the module it is defined in
|
|
||||||
log_level = 'INFO' # Default logging level if not specified in config file
|
|
||||||
|
|
||||||
def configure_logging(level=log_level):
|
class GlobalState:
|
||||||
"""
|
"""
|
||||||
Set up logging for the project. This is the root logger instance.
|
This class holds various variables and methods which are accessible across
|
||||||
All child loggers inherit from this logger.
|
different modules in the Python project using the Singleton design pattern.
|
||||||
|
This ensures that only one instance of the class is created and shared among
|
||||||
|
all modules, preventing circular imports and providing a centralized location
|
||||||
|
for managing shared resources.
|
||||||
"""
|
"""
|
||||||
numeric_level = getattr(logging, level.upper()) # Convert string to numeric level
|
_instance = None # Private class attribute to hold the single instance of the class
|
||||||
|
|
||||||
logger = logging.getLogger() # Get the root logger
|
def __new__(cls):
|
||||||
logger.setLevel(numeric_level)
|
if cls._instance is None:
|
||||||
|
cls._instance = super(GlobalState, cls).__new__(cls)
|
||||||
|
cls._instance.log_level = 'INFO' # Default logging level
|
||||||
|
cls._instance.logger = logging.getLogger() # Get root logger for the caller module
|
||||||
|
handler = logging.StreamHandler() # Or other handler (FileHandler for logs to file)
|
||||||
|
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
||||||
|
handler.setFormatter(formatter)
|
||||||
|
cls._instance.logger.addHandler(handler)
|
||||||
|
cls._instance.logger.setLevel(getattr(logging, cls._instance.log_level)) # Initialize root logger level
|
||||||
|
cls._instance.logger.info(" __new__(cls): Logger in GlobalState created: %s", cls._instance.logger)
|
||||||
|
return cls._instance
|
||||||
|
|
||||||
handler = logging.StreamHandler() # Or other handler (FileHandler for logs to file)
|
def configure_logging(self, level=None):
|
||||||
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
"""Set up logging for the project."""
|
||||||
handler.setFormatter(formatter)
|
if level is None:
|
||||||
logger.addHandler(handler)
|
level = self.log_level
|
||||||
|
# numeric_level = getattr(logging, level.upper()) # Convert string to numeric level
|
||||||
|
numeric_level = getattr(logging, level.upper()) # Convert string to numeric level
|
||||||
|
self.logger.setLevel(numeric_level)
|
||||||
|
self.logger.debug(f"utils.py -- configure_logging(): effective log level is {level} which is {self.logger.getEffectiveLevel()}")
|
||||||
|
|
||||||
# To be removed?
|
def set_log_level(self, level = 'INFO'):
|
||||||
# def set_local_logger(log_instance):
|
"""Set the logging level."""
|
||||||
# """
|
self.log_level = level
|
||||||
# Configure logging based on the global variable log_level
|
self.configure_logging()
|
||||||
# Logging is controlled by integer values, where DEBUG < INFO < WARNING < ERROR < CRITICAL.
|
|
||||||
# To turn off logging completely, set numeric_log_level to at least CRITICAL + 1.
|
|
||||||
# """
|
|
||||||
# global log_level
|
|
||||||
# numeric_log_level = getattr(logging, log_level, None)
|
|
||||||
# if not isinstance(numeric_log_level, int):
|
|
||||||
# raise ValueError('Invalid log level: %s' % log_level)
|
|
||||||
|
|
||||||
# log_instance.basicConfig(level=numeric_log_level) # Set the root logger level to the configured level
|
def get_log_level(self):
|
||||||
# log_instance.info('Current log level set to {}'.format(log_instance.getLogger().getEffectiveLevel())) # Example usage of the logger
|
"""Getter for log_level attribute."""
|
||||||
|
return self.log_level
|
||||||
|
|
||||||
|
def get_effective_log_level(self):
|
||||||
|
"""Getter for effective log level of loggerattribute."""
|
||||||
|
return self.logger.getEffectiveLevel()
|
||||||
|
|
||||||
|
def getLogger(self, module_name=None):
|
||||||
|
"""Return a logger based on the module name."""
|
||||||
|
if module_name is None:
|
||||||
|
module_name = __name__
|
||||||
|
logger = logging.getLogger(module_name)
|
||||||
|
return logger
|
||||||
Reference in New Issue
Block a user