From 5daa71e6c1966d31064f048f5169a1fb3ae1d59d Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Tue, 3 Sep 2024 22:52:27 -0700 Subject: [PATCH 01/23] llmLocationAware enhance with local data to the AI --- mesh_bot.py | 4 +++- modules/llm.py | 2 +- modules/locationdata.py | 19 +++++++++++++------ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/mesh_bot.py b/mesh_bot.py index b6f2071..25b62f3 100755 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -107,6 +107,8 @@ def handle_wiki(message): def handle_llm(message_from_id, channel_number, deviceID, message, publicChannel): global llmRunCounter, llmTotalRuntime + location = get_node_location(message_from_id, deviceID) + location_name = where_am_i(str(location[0]), str(location[1], short=True)) if "ask:" in message.lower(): user_input = message.split(":")[1] elif "askai" in message.lower(): @@ -137,7 +139,7 @@ def handle_llm(message_from_id, channel_number, deviceID, message, publicChannel start = time.time() #response = asyncio.run(llm_query(user_input, message_from_id)) - response = llm_query(user_input, message_from_id) + response = llm_query(user_input, message_from_id, location_name) # handle the runtime counter end = time.time() diff --git a/modules/llm.py b/modules/llm.py index 0e8dc67..e75a040 100644 --- a/modules/llm.py +++ b/modules/llm.py @@ -58,7 +58,7 @@ ollama_model = OllamaLLM(model=llmModel) model_prompt = ChatPromptTemplate.from_template(meshBotAI) chain_prompt_model = model_prompt | ollama_model -def llm_query(input, nodeID=0): +def llm_query(input, nodeID=0, location_name=None): global antiFloodLLM, llmChat_history googleResults = [] diff --git a/modules/locationdata.py b/modules/locationdata.py index 7eb21d1..c6ea9cc 100644 --- a/modules/locationdata.py +++ b/modules/locationdata.py @@ -11,7 +11,7 @@ from modules.log import * trap_list_location = ("whereami", "tide", "moon", "wx", "wxc", "wxa", "wxalert") -def where_am_i(lat=0, lon=0): +def where_am_i(lat=0, lon=0, short=False): whereIam = "" grid = mh.to_maiden(float(lat), float(lon)) @@ -32,11 +32,18 @@ def where_am_i(lat=0, lon=0): whereIam += " Grid: " + grid return whereIam else: - location = geolocator.reverse(lat + ", " + lon) - address = location.raw['address'] - address_components = ['house_number', 'road', 'city', 'state', 'postcode', 'county', 'country'] - whereIam += ' '.join([address.get(component, '') for component in address_components if component in address]) - whereIam += " Grid: " + grid + if short: + location = geolocator.reverse(lat + ", " + lon) + address = location.raw['address'] + address_components = ['city', 'state', 'county', 'country'] + whereIam += ' '.join([address.get(component, '') for component in address_components if component in address]) + return whereIam + else: + location = geolocator.reverse(lat + ", " + lon) + address = location.raw['address'] + address_components = ['house_number', 'road', 'city', 'state', 'postcode', 'county', 'country'] + whereIam += ' '.join([address.get(component, '') for component in address_components if component in address]) + whereIam += " Grid: " + grid return whereIam def get_tide(lat=0, lon=0): From 9b0261170060cfe35da9580336bffc536bd04bdb Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Tue, 3 Sep 2024 23:02:04 -0700 Subject: [PATCH 02/23] LocationAware --- mesh_bot.py | 7 ++++++- modules/llm.py | 18 ++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/mesh_bot.py b/mesh_bot.py index 25b62f3..29cfd58 100755 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -107,8 +107,13 @@ def handle_wiki(message): def handle_llm(message_from_id, channel_number, deviceID, message, publicChannel): global llmRunCounter, llmTotalRuntime + location = get_node_location(message_from_id, deviceID) - location_name = where_am_i(str(location[0]), str(location[1], short=True)) + if location_enabled: + location_name = where_am_i(str(location[0]), str(location[1], short=True)) + else: + location_name = "Unknown" + if "ask:" in message.lower(): user_input = message.split(":")[1] elif "askai" in message.lower(): diff --git a/modules/llm.py b/modules/llm.py index e75a040..7585f90 100644 --- a/modules/llm.py +++ b/modules/llm.py @@ -33,15 +33,24 @@ PROMPT {input} user={userID} - """ if llmContext_fromGoogle: meshBotAI = meshBotAI + """ CONTEXT + The following is the location the user + {location_name} + The following is for context around the prompt to help guide your response. {context} + """ +else: + meshBotAI = meshBotAI + """ + CONTEXT + The following is the location the user + {location_name} + """ if llmEnableHistory: @@ -80,10 +89,10 @@ def llm_query(input, nodeID=0, location_name=None): # SearchResult object has url= title= description= just grab title and description googleResults.append(f"{result.title} {result.description}") else: - googleResults = ['no context provided'] + googleResults = ['no other context provided'] except Exception as e: logger.debug(f"System: LLM Query: context gathering error: {e}") - googleResults = ['no context provided'] + googleResults = ['no other context provided'] if googleResults: @@ -93,7 +102,8 @@ def llm_query(input, nodeID=0, location_name=None): response = "" result = "" - result = chain_prompt_model.invoke({"input": input, "llmModel": llmModel, "userID": nodeID, "history": llmChat_history, "context": googleResults}) + result = chain_prompt_model.invoke({"input": input, "llmModel": llmModel, "userID": nodeID, \ + "history": llmChat_history, "context": googleResults, "location_name": location_name}) #logger.debug(f"System: LLM Response: " + result.strip().replace('\n', ' ')) response = result.strip().replace('\n', ' ') From 0869b19408708c75bf657d109f15ae04352012b5 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Tue, 3 Sep 2024 23:05:00 -0700 Subject: [PATCH 03/23] addTimeAware include the current date in the awareness of location --- modules/llm.py | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/llm.py b/modules/llm.py index 7585f90..3a44767 100644 --- a/modules/llm.py +++ b/modules/llm.py @@ -102,6 +102,7 @@ def llm_query(input, nodeID=0, location_name=None): response = "" result = "" + location_name = location_name + f" at the current time of {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" result = chain_prompt_model.invoke({"input": input, "llmModel": llmModel, "userID": nodeID, \ "history": llmChat_history, "context": googleResults, "location_name": location_name}) #logger.debug(f"System: LLM Response: " + result.strip().replace('\n', ' ')) From 4f74677d1407ebce596907e58fe4bf0c58f59f2f Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Tue, 3 Sep 2024 23:05:34 -0700 Subject: [PATCH 04/23] Update mesh_bot.py --- mesh_bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesh_bot.py b/mesh_bot.py index 29cfd58..e9a84a1 100755 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -112,7 +112,7 @@ def handle_llm(message_from_id, channel_number, deviceID, message, publicChannel if location_enabled: location_name = where_am_i(str(location[0]), str(location[1], short=True)) else: - location_name = "Unknown" + location_name = "no location provided " if "ask:" in message.lower(): user_input = message.split(":")[1] From 098c344047f14aacd2a0fa02a7aa6fc4c0940ae7 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Tue, 3 Sep 2024 23:08:37 -0700 Subject: [PATCH 05/23] Update llm.py --- modules/llm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/llm.py b/modules/llm.py index 3a44767..653f0ce 100644 --- a/modules/llm.py +++ b/modules/llm.py @@ -102,7 +102,7 @@ def llm_query(input, nodeID=0, location_name=None): response = "" result = "" - location_name = location_name + f" at the current time of {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" + location_name += f" at the current time of {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" result = chain_prompt_model.invoke({"input": input, "llmModel": llmModel, "userID": nodeID, \ "history": llmChat_history, "context": googleResults, "location_name": location_name}) #logger.debug(f"System: LLM Response: " + result.strip().replace('\n', ' ')) From 297930c4d1039b3ab6ed094c5574e5b181f8a2a8 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Tue, 3 Sep 2024 23:09:45 -0700 Subject: [PATCH 06/23] Update llm.py --- modules/llm.py | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/llm.py b/modules/llm.py index 653f0ce..80e75e6 100644 --- a/modules/llm.py +++ b/modules/llm.py @@ -82,6 +82,7 @@ def llm_query(input, nodeID=0, location_name=None): if llmContext_fromGoogle: # grab some context from the internet using google search hits (if available) + # localization details at https://pypi.org/project/googlesearch-python/ try: googleSearch = search(input, advanced=True, num_results=5) if googleSearch: From 63c3e35064189f6b6cbf865ca72a4b424a6685b6 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Tue, 3 Sep 2024 23:12:32 -0700 Subject: [PATCH 07/23] Update llm.py --- modules/llm.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/llm.py b/modules/llm.py index 80e75e6..4316504 100644 --- a/modules/llm.py +++ b/modules/llm.py @@ -70,6 +70,8 @@ chain_prompt_model = model_prompt | ollama_model def llm_query(input, nodeID=0, location_name=None): global antiFloodLLM, llmChat_history googleResults = [] + if not location_name: + location_name = "no location provided " # add the naughty list here to stop the function before we continue # add a list of allowed nodes only to use the function From 15dc50804f1c742a408b9462dfdb1172d524755e Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Tue, 3 Sep 2024 23:17:34 -0700 Subject: [PATCH 08/23] Update mesh_bot.py --- mesh_bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesh_bot.py b/mesh_bot.py index e9a84a1..a691012 100755 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -109,7 +109,7 @@ def handle_llm(message_from_id, channel_number, deviceID, message, publicChannel global llmRunCounter, llmTotalRuntime location = get_node_location(message_from_id, deviceID) - if location_enabled: + if location_enabled and not NO_DATA_NOGPS in location: location_name = where_am_i(str(location[0]), str(location[1], short=True)) else: location_name = "no location provided " From d6ad0b5e94dcfdd4263bb56f40376926dfcb13e7 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Tue, 3 Sep 2024 23:20:13 -0700 Subject: [PATCH 09/23] Update mesh_bot.py --- mesh_bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesh_bot.py b/mesh_bot.py index a691012..2a02483 100755 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -110,7 +110,7 @@ def handle_llm(message_from_id, channel_number, deviceID, message, publicChannel location = get_node_location(message_from_id, deviceID) if location_enabled and not NO_DATA_NOGPS in location: - location_name = where_am_i(str(location[0]), str(location[1], short=True)) + location_name = where_am_i(str(location[0]), str(location[1]), short = True)) else: location_name = "no location provided " From 9fa9da5e74d9ffcac9cff4dee3ea7d6f9b7e71bb Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Tue, 3 Sep 2024 23:20:23 -0700 Subject: [PATCH 10/23] Update mesh_bot.py --- mesh_bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesh_bot.py b/mesh_bot.py index 2a02483..84765a3 100755 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -110,7 +110,7 @@ def handle_llm(message_from_id, channel_number, deviceID, message, publicChannel location = get_node_location(message_from_id, deviceID) if location_enabled and not NO_DATA_NOGPS in location: - location_name = where_am_i(str(location[0]), str(location[1]), short = True)) + location_name = where_am_i(str(location[0]), str(location[1]), short = True) else: location_name = "no location provided " From 2fc3930b4327d74aeabcc515ab5863677cfbf3a6 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Tue, 3 Sep 2024 23:22:02 -0700 Subject: [PATCH 11/23] Update mesh_bot.py --- mesh_bot.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesh_bot.py b/mesh_bot.py index 84765a3..6937744 100755 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -109,8 +109,10 @@ def handle_llm(message_from_id, channel_number, deviceID, message, publicChannel global llmRunCounter, llmTotalRuntime location = get_node_location(message_from_id, deviceID) - if location_enabled and not NO_DATA_NOGPS in location: + if location_enabled: location_name = where_am_i(str(location[0]), str(location[1]), short = True) + if NO_DATA_NOGPS in location_name: + location_name = "no location provided " else: location_name = "no location provided " From 1ce394c7a1b59ed085236f5771dc719e0f7d3648 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Wed, 4 Sep 2024 00:20:06 -0700 Subject: [PATCH 12/23] Update for LLM --- modules/locationdata.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/modules/locationdata.py b/modules/locationdata.py index c6ea9cc..4937adc 100644 --- a/modules/locationdata.py +++ b/modules/locationdata.py @@ -23,6 +23,13 @@ def where_am_i(lat=0, lon=0, short=False): geolocator = Nominatim(user_agent="mesh-bot") # Nomatim API call to get address + if short: + location = geolocator.reverse(lat + ", " + lon) + address = location.raw['address'] + address_components = ['city', 'state', 'county', 'country'] + whereIam = f"City: {address.get('city', '')} State: {address.get('state', '')} County: {address.get('county', '')} Country: {address.get('country', '')}" + return whereIam + if float(lat) == latitudeValue and float(lon) == longitudeValue: # redacted address when no GPS and using default location location = geolocator.reverse(lat + ", " + lon) @@ -30,21 +37,13 @@ def where_am_i(lat=0, lon=0, short=False): address_components = ['city', 'state', 'postcode', 'county', 'country'] whereIam += ' '.join([address.get(component, '') for component in address_components if component in address]) whereIam += " Grid: " + grid - return whereIam else: - if short: - location = geolocator.reverse(lat + ", " + lon) - address = location.raw['address'] - address_components = ['city', 'state', 'county', 'country'] - whereIam += ' '.join([address.get(component, '') for component in address_components if component in address]) - return whereIam - else: - location = geolocator.reverse(lat + ", " + lon) - address = location.raw['address'] - address_components = ['house_number', 'road', 'city', 'state', 'postcode', 'county', 'country'] - whereIam += ' '.join([address.get(component, '') for component in address_components if component in address]) - whereIam += " Grid: " + grid - return whereIam + location = geolocator.reverse(lat + ", " + lon) + address = location.raw['address'] + address_components = ['house_number', 'road', 'city', 'state', 'postcode', 'county', 'country'] + whereIam += ' '.join([address.get(component, '') for component in address_components if component in address]) + whereIam += " Grid: " + grid + return whereIam def get_tide(lat=0, lon=0): station_id = "" From ec078666aeb3a61a22d8a419c682f1b412553157 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Wed, 4 Sep 2024 00:50:57 -0700 Subject: [PATCH 13/23] saveSomeAPIcalls --- mesh_bot.py | 14 ++++++++++---- modules/settings.py | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/mesh_bot.py b/mesh_bot.py index 6937744..d108714 100755 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -106,11 +106,17 @@ def handle_wiki(message): return "Please add a search term example:wiki: travelling gnome" def handle_llm(message_from_id, channel_number, deviceID, message, publicChannel): - global llmRunCounter, llmTotalRuntime - - location = get_node_location(message_from_id, deviceID) + global llmRunCounter, llmTotalRuntime, llmLocationTable + if location_enabled: - location_name = where_am_i(str(location[0]), str(location[1]), short = True) + location = get_node_location(message_from_id, deviceID) + # if message_from_id is is the llmLocationTable use the location from the table to save on API calls + if message_from_id in llmLocationTable: + location = llmLocationTable[message_from_id] + else: + location_name = where_am_i(str(location[0]), str(location[1]), short = True) + llmLocationTable.append({message_from_id: location_name}) + if NO_DATA_NOGPS in location_name: location_name = "no location provided " else: diff --git a/modules/settings.py b/modules/settings.py index 6c6b3e8..46c5ea6 100644 --- a/modules/settings.py +++ b/modules/settings.py @@ -28,6 +28,7 @@ scheduler_enabled = False # enable the scheduler currently config via code only wiki_return_limit = 3 # limit the number of sentences returned off the first paragraph first hit llmRunCounter = 0 llmTotalRuntime = [] +llmLocationTable = [] # Read the config file, if it does not exist, create basic config file config = configparser.ConfigParser() From 081566b5d950f7aa04ae5d4cb2be4062af93d813 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Wed, 4 Sep 2024 09:40:04 -0700 Subject: [PATCH 14/23] lower value to speed up query --- modules/llm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/llm.py b/modules/llm.py index 4316504..81666d3 100644 --- a/modules/llm.py +++ b/modules/llm.py @@ -86,7 +86,7 @@ def llm_query(input, nodeID=0, location_name=None): # grab some context from the internet using google search hits (if available) # localization details at https://pypi.org/project/googlesearch-python/ try: - googleSearch = search(input, advanced=True, num_results=5) + googleSearch = search(input, advanced=True, num_results=3) if googleSearch: for result in googleSearch: # SearchResult object has url= title= description= just grab title and description From e546866f78e12d177178d532957324687ecd28c2 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Wed, 4 Sep 2024 09:40:57 -0700 Subject: [PATCH 15/23] Update llm.py --- modules/llm.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/llm.py b/modules/llm.py index 81666d3..da70150 100644 --- a/modules/llm.py +++ b/modules/llm.py @@ -12,6 +12,7 @@ from googlesearch import search # pip install googlesearch-python # LLM System Variables llmEnableHistory = False llmContext_fromGoogle = True +googleSearchResults = 3 llm_history_limit = 6 # limit the history to 3 messages (come in pairs) antiFloodLLM = [] llmChat_history = [] @@ -86,7 +87,7 @@ def llm_query(input, nodeID=0, location_name=None): # grab some context from the internet using google search hits (if available) # localization details at https://pypi.org/project/googlesearch-python/ try: - googleSearch = search(input, advanced=True, num_results=3) + googleSearch = search(input, advanced=True, num_results=googleSearchResults) if googleSearch: for result in googleSearch: # SearchResult object has url= title= description= just grab title and description From f6c6c58c1711fcac93b47d896b2efbecb20a13e5 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Wed, 4 Sep 2024 11:06:09 -0700 Subject: [PATCH 16/23] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2c2d8a4..977e50e 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ Optionally: - `launch.sh` will activate and launch the app in the venv if built. For Docker: +Check you have serial port properly shared and the GPU if using LLM with [NVidia](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/docker-specialized.html) - `git clone https://github.com/spudgunman/meshing-around` - `cd meshing-around && docker build -t meshing-around` - `docker run meshing-around` From 469e76c50b4cb6ad147937bd2140b500e07a137a Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Wed, 4 Sep 2024 13:14:28 -0700 Subject: [PATCH 17/23] Update llm.py --- modules/llm.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/modules/llm.py b/modules/llm.py index da70150..9632346 100644 --- a/modules/llm.py +++ b/modules/llm.py @@ -126,3 +126,15 @@ def llm_query(input, nodeID=0, location_name=None): antiFloodLLM.remove(nodeID) return response + +# import subprocess +# def get_ollama_cpu(): +# try: +# psOutput = subprocess.run(['ollama', 'ps'], capture_output=True, text=True) +# if "GPU" in psOutput.stdout: +# logger.debug(f"System: Ollama process with GPU") +# else: +# logger.debug(f"System: Ollama process with CPU, query time will be slower") +# except Exception as e: +# logger.debug(f"System: Ollama process not found, {e}") +# return False From 510a5c5007dae871178dc8f6328278d56818e523 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Wed, 4 Sep 2024 14:42:23 -0700 Subject: [PATCH 18/23] Update llm.py --- modules/llm.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/llm.py b/modules/llm.py index 9632346..72a72e6 100644 --- a/modules/llm.py +++ b/modules/llm.py @@ -107,9 +107,15 @@ def llm_query(input, nodeID=0, location_name=None): response = "" result = "" location_name += f" at the current time of {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" - result = chain_prompt_model.invoke({"input": input, "llmModel": llmModel, "userID": nodeID, \ - "history": llmChat_history, "context": googleResults, "location_name": location_name}) - #logger.debug(f"System: LLM Response: " + result.strip().replace('\n', ' ')) + + try: + result = chain_prompt_model.invoke({"input": input, "llmModel": llmModel, "userID": nodeID, \ + "history": llmChat_history, "context": googleResults, "location_name": location_name}) + #logger.debug(f"System: LLM Response: " + result.strip().replace('\n', ' ')) + except Exception as e: + logger.warning(f"System: LLM failure: {e}") + return "I am having trouble processing your request, please try again later." + response = result.strip().replace('\n', ' ') From 9031704b9b3be811d503a4c902c08796bb3db6f4 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Wed, 4 Sep 2024 14:51:50 -0700 Subject: [PATCH 19/23] Update llm.py --- modules/llm.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/llm.py b/modules/llm.py index 72a72e6..0c67aa1 100644 --- a/modules/llm.py +++ b/modules/llm.py @@ -12,8 +12,8 @@ from googlesearch import search # pip install googlesearch-python # LLM System Variables llmEnableHistory = False llmContext_fromGoogle = True -googleSearchResults = 3 -llm_history_limit = 6 # limit the history to 3 messages (come in pairs) +googleSearchResults = 3 # number of google search results to include in the context more results = more compute time +llm_history_limit = 6 # limit the history to 3 messages (come in pairs) more results = more compute time antiFloodLLM = [] llmChat_history = [] trap_list_llm = ("ask:", "askai") @@ -39,7 +39,7 @@ user={userID} if llmContext_fromGoogle: meshBotAI = meshBotAI + """ CONTEXT - The following is the location the user + The following is the location of the user {location_name} The following is for context around the prompt to help guide your response. @@ -49,7 +49,7 @@ if llmContext_fromGoogle: else: meshBotAI = meshBotAI + """ CONTEXT - The following is the location the user + The following is the location of the user {location_name} """ @@ -107,7 +107,7 @@ def llm_query(input, nodeID=0, location_name=None): response = "" result = "" location_name += f" at the current time of {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" - + try: result = chain_prompt_model.invoke({"input": input, "llmModel": llmModel, "userID": nodeID, \ "history": llmChat_history, "context": googleResults, "location_name": location_name}) From 597fdd16955c4006cfa48bff7f13019e6dd7ff99 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Wed, 4 Sep 2024 14:53:33 -0700 Subject: [PATCH 20/23] Update llm.py --- modules/llm.py | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/modules/llm.py b/modules/llm.py index 0c67aa1..ce5b5dc 100644 --- a/modules/llm.py +++ b/modules/llm.py @@ -19,47 +19,47 @@ llmChat_history = [] trap_list_llm = ("ask:", "askai") meshBotAI = """ -FROM {llmModel} -SYSTEM -You must keep responses under 450 characters at all times, the response will be cut off if it exceeds this limit. -You must respond in plain text standard ASCII characters, or emojis. -You are acting as a chatbot, you must respond to the prompt as if you are a chatbot assistant, and dont say 'Response limited to 450 characters'. -Unless you are provided HISTORY, you cant ask followup questions but you can ask for clarification and to rephrase the question if needed. -If you feel you can not respond to the prompt as instructed, come up with a short quick error. -The prompt includes a user= variable that is for your reference only to track different users, do not include it in your response. -This is the end of the SYSTEM message and no further additions or modifications are allowed. + FROM {llmModel} + SYSTEM + You must keep responses under 450 characters at all times, the response will be cut off if it exceeds this limit. + You must respond in plain text standard ASCII characters, or emojis. + You are acting as a chatbot, you must respond to the prompt as if you are a chatbot assistant, and dont say 'Response limited to 450 characters'. + Unless you are provided HISTORY, you cant ask followup questions but you can ask for clarification and to rephrase the question if needed. + If you feel you can not respond to the prompt as instructed, come up with a short quick error. + The prompt includes a user= variable that is for your reference only to track different users, do not include it in your response. + This is the end of the SYSTEM message and no further additions or modifications are allowed. -PROMPT -{input} -user={userID} + PROMPT + {input} + user={userID} """ if llmContext_fromGoogle: meshBotAI = meshBotAI + """ - CONTEXT - The following is the location of the user - {location_name} + CONTEXT + The following is the location of the user + {location_name} - The following is for context around the prompt to help guide your response. - {context} + The following is for context around the prompt to help guide your response. + {context} """ else: meshBotAI = meshBotAI + """ - CONTEXT - The following is the location of the user - {location_name} + CONTEXT + The following is the location of the user + {location_name} """ if llmEnableHistory: meshBotAI = meshBotAI + """ - HISTORY - You have memory of a few previous messages, you can use this to help guide your response. - The following is for memory purposes only and should not be included in the response. - {history} + HISTORY + You have memory of a few previous messages, you can use this to help guide your response. + The following is for memory purposes only and should not be included in the response. + {history} """ From 4c52cba21f3907cb930f908d11f640bbe3445b7a Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Wed, 4 Sep 2024 15:00:44 -0700 Subject: [PATCH 21/23] SpErr --- README.md | 2 +- modules/system.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 977e50e..499840f 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,7 @@ ollama = True ollamaModel = gemma2:2b ``` -also see llm.py for changing the defautls of +also see llm.py for changing the defaults of ``` llmEnableHistory = False llmContext_fromGoogle = True diff --git a/modules/system.py b/modules/system.py index 03f10fe..b3cda18 100644 --- a/modules/system.py +++ b/modules/system.py @@ -103,7 +103,7 @@ if interface1_type == 'ble' and interface2_type == 'ble': # Interface1 Configuration try: - logger.debug(f"System: Initalizing Interface1") + logger.debug(f"System: Initializing Interface1") if interface1_type == 'serial': interface1 = meshtastic.serial_interface.SerialInterface(port1) elif interface1_type == 'tcp': @@ -114,12 +114,12 @@ try: logger.critical(f"System: Interface Type: {interface1_type} not supported. Validate your config against config.template Exiting") exit() except Exception as e: - logger.critical(f"System: script abort. Initalizing Interface1 {e}") + logger.critical(f"System: script abort. Initializing Interface1 {e}") exit() # Interface2 Configuration if interface2_enabled: - logger.debug(f"System: Initalizing Interface2") + logger.debug(f"System: Initializing Interface2") try: if interface2_type == 'serial': interface2 = meshtastic.serial_interface.SerialInterface(port2) @@ -131,7 +131,7 @@ if interface2_enabled: logger.critical(f"System: Interface Type: {interface2_type} not supported. Validate your config against config.template Exiting") exit() except Exception as e: - logger.critical(f"System: script abort. Initalizing Interface2 {e}") + logger.critical(f"System: script abort. Initializing Interface2 {e}") exit() #Get the node number of the device, check if the device is connected From d627f694df70d99a8d0dab6f5174199f23b31892 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Wed, 4 Sep 2024 15:05:15 -0700 Subject: [PATCH 22/23] typo --- modules/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/settings.py b/modules/settings.py index 46c5ea6..e5363ee 100644 --- a/modules/settings.py +++ b/modules/settings.py @@ -93,7 +93,7 @@ try: urlTimeoutSeconds = config['general'].getint('urlTimeout', 10) # default 10 seconds store_forward_enabled = config['general'].getboolean('StoreForward', True) storeFlimit = config['general'].getint('StoreLimit', 3) # default 3 messages for S&F - welcome_message = config['general'].get(f'welcome_message', WELCOME_MSG) + welcome_message = config['general'].get('welcome_message', WELCOME_MSG) welcome_message = (f"{welcome_message}").replace('\\n', '\n') # allow for newlines in the welcome message motd_enabled = config['general'].getboolean('motdEnabled', True) dad_jokes_enabled = config['general'].getboolean('DadJokes', False) From 1677b69363fa2e90b49a565d9a87da8148861b6a Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Wed, 4 Sep 2024 15:10:38 -0700 Subject: [PATCH 23/23] comments# --- README.md | 7 +++++-- modules/llm.py | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 499840f..7efb5aa 100644 --- a/README.md +++ b/README.md @@ -168,8 +168,11 @@ ollamaModel = gemma2:2b also see llm.py for changing the defaults of ``` -llmEnableHistory = False -llmContext_fromGoogle = True +# LLM System Variables +llmEnableHistory = False # enable history for the LLM model to use in responses adds to compute time +llmContext_fromGoogle = True # enable context from google search results adds to compute time but really helps with responses accuracy +googleSearchResults = 3 # number of google search results to include in the context more results = more compute time +llm_history_limit = 6 # limit the history to 3 messages (come in pairs) more results = more compute time ``` Logging messages to disk or Syslog to disk uses the python native logging function. Take a look at the [/modules/log.py](/modules/log.py) you can set the file logger for syslog to INFO for example to not log DEBUG messages to file log, or modify the stdOut level. diff --git a/modules/llm.py b/modules/llm.py index ce5b5dc..8808cd7 100644 --- a/modules/llm.py +++ b/modules/llm.py @@ -10,8 +10,8 @@ from langchain_core.messages import AIMessage, HumanMessage from googlesearch import search # pip install googlesearch-python # LLM System Variables -llmEnableHistory = False -llmContext_fromGoogle = True +llmEnableHistory = False # enable history for the LLM model to use in responses adds to compute time +llmContext_fromGoogle = True # enable context from google search results adds to compute time but really helps with responses accuracy googleSearchResults = 3 # number of google search results to include in the context more results = more compute time llm_history_limit = 6 # limit the history to 3 messages (come in pairs) more results = more compute time antiFloodLLM = []