diff --git a/README.md b/README.md index 1d21292..8836de5 100644 --- a/README.md +++ b/README.md @@ -144,10 +144,8 @@ StoreForward = False The history command shows the last commands the user ran, and [`lheard`] reflects the last users on the bot. ```ini -# history command -enableCmdHistory = True -# command history ignore list ex: 2813308004,4258675309 -lheardCmdIgnoreNodes = +enableCmdHistory = True # history command enabler +lheardCmdIgnoreNodes = # command history ignore list ex: 2813308004,4258675309 ``` ### Sentry Settings @@ -155,24 +153,18 @@ lheardCmdIgnoreNodes = Sentry Bot detects anyone coming close to the bot-node. ```ini -# detect anyone close to the bot -SentryEnabled = True -# radius in meters to detect someone close to the bot -SentryRadius = 100 -# holdoff time multiplied by seconds(20) of the watchdog -SentryChannel = 9 -# channel to send a message to when the watchdog is triggered -SentryHoldoff = 2 -# list of ignored nodes numbers ex: 2813308004,4258675309 -sentryIgnoreList = +SentryEnabled = True # detect anyone close to the bot +SentryRadius = 100 # radius in meters to detect someone close to the bot +SentryChannel = 9 # holdoff time multiplied by seconds(20) of the watchdog +SentryHoldoff = 2 # channel to send a message to when the watchdog is triggered +sentryIgnoreList = # list of ignored nodes numbers ex: 2813308004,4258675309 ``` ### Repeater Settings A repeater function for two different nodes and cross-posting messages. The [`repeater_channels`] is a list of repeater channels that will be consumed and rebroadcast on the same number channel on the other device, node, or interface. Each node should have matching channel numbers. The channel names and PSK do not need to be the same on the nodes. Use this feature responsibly to avoid creating a feedback loop. ```ini -# repeater module -[repeater] +[repeater] # repeater module enabled = True repeater_channels = [2, 3] ``` @@ -184,36 +176,30 @@ A module allowing a Hamlib compatible radio to connect to the bot. When function [radioMon] enabled = False rigControlServerAddress = localhost:4532 -# channel to broadcast to can be 2,3 -sigWatchBroadcastCh = 2 -# minimum SNR as reported by radio via hamlib -signalDetectionThreshold = -10 -# hold time for high SNR -signalHoldTime = 10 -# the following are combined to reset the monitor -signalCooldown = 5 +sigWatchBroadcastCh = 2 # channel to broadcast to can be 2,3 +signalDetectionThreshold = -10 # minimum SNR as reported by radio via hamlib +signalHoldTime = 10 # hold time for high SNR +signalCooldown = 5 # the following are combined to reset the monitor signalCycleLimit = 5 ``` ### Ollama (LLM/AI) Settings -For Ollama to work, the command line `ollama run 'model'` needs to work properly. Ensure you have enough RAM and your GPU is working as expected. The default model for this project is set to `gemma2:2b`. +For Ollama to work, the command line `ollama run 'model'` needs to work properly. Ensure you have enough RAM and your GPU is working as expected. The default model for this project is set to `gemma2:2b`. Ollama can be remote [Ollama Server](https://github.com/ollama/ollama/blob/main/docs/faq.md#how-do-i-configure-ollama-server) ```ini # Enable ollama LLM see more at https://ollama.com -ollama = True -# Ollama model to use (defaults to gemma2:2b) -ollamaModel = gemma2 -#ollamaModel = llama3.1 +ollama = True # Ollama model to use (defaults to gemma2:2b) +ollamaModel = gemma2 #ollamaModel = llama3.1 +ollamaHostName = http://localhost:11434 # server instance to use (defaults to local machine install) ``` Also see `llm.py` for changing the defaults of: ```ini # 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 +llmEnableHistory = True # enable history for the LLM model to use in responses adds to compute time +llmContext_fromGoogle = True # enable context from google search results 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 ``` ### Scheduler @@ -260,8 +246,6 @@ pip install numpy For the Ollama LLM: ```sh -pip install langchain -pip install langchain-ollama pip install ollama pip install googlesearch-python ``` diff --git a/config.template b/config.template index 591dda1..342ffab 100644 --- a/config.template +++ b/config.template @@ -44,6 +44,8 @@ wikipedia = True ollama = False # Ollama model to use (defaults to gemma2:2b) # ollamaModel = llama3.1 +# server instance to use (defaults to local machine install) +ollamaHostName = http://localhost:11434 # StoreForward Enabled and Limits StoreForward = True StoreLimit = 3 diff --git a/modules/llm.py b/modules/llm.py index a3cca99..fdfdf94 100644 --- a/modules/llm.py +++ b/modules/llm.py @@ -4,29 +4,26 @@ # K7MHI Kelly Keeton 2024 from modules.log import * -from langchain_ollama import OllamaLLM # pip install ollama langchain-ollama -from langchain_core.prompts import ChatPromptTemplate # pip install langchain -from langchain_core.messages import AIMessage, HumanMessage +# old langchain stuff, if needed for older/other models +# from langchain_ollama import OllamaLLM # pip install ollama langchain-ollama +# from langchain_core.prompts import ChatPromptTemplate # pip install langchain +# from langchain_core.messages import AIMessage, HumanMessage from googlesearch import search # pip install googlesearch-python -# Ollama Client -enableOllamaClient = False -if enableOllamaClient: - # for cutsom remote host models - # https://github.com/ollama/ollama/blob/main/docs/faq.md#how-do-i-configure-ollama-server - from ollama import Client as OllamaClient - OllamaClient(host='http://localhost:11434') - ollamaClient = OllamaClient() - # LLM System Variables -llmEnableHistory = False # enable history for the LLM model to use in responses adds to compute time +llmEnableHistory = True # enable last message history for the LLM model 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 = [] -llmChat_history = [] +llmChat_history = {} trap_list_llm = ("ask:", "askai") +# Ollama Client +# https://github.com/ollama/ollama/blob/main/docs/faq.md#how-do-i-configure-ollama-server +from ollama import Client as OllamaClient +OllamaClient(host=ollamaHostName) +ollamaClient = OllamaClient() + meshBotAI = """ FROM {llmModel} SYSTEM @@ -38,44 +35,40 @@ meshBotAI = """ 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} """ 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 + the following is memory of previous query in format ['prompt', 'response'], you can use this to help guide your response. + {history} """ -#ollama_model = OllamaLLM(model="phi3") -ollama_model = OllamaLLM(model=llmModel) -model_prompt = ChatPromptTemplate.from_template(meshBotAI) -chain_prompt_model = model_prompt | ollama_model +# ollama_model = OllamaLLM(model=llmModel) +# model_prompt = ChatPromptTemplate.from_template(meshBotAI) +# chain_prompt_model = model_prompt | ollama_model def llm_query(input, nodeID=0, location_name=None): global antiFloodLLM, llmChat_history @@ -112,6 +105,7 @@ def llm_query(input, nodeID=0, location_name=None): logger.debug(f"System: LLM Query: context gathering failed, likely due to network issues") googleResults = ['no other context provided'] + history = llmChat_history.get(nodeID, ["", ""]) if googleResults: logger.debug(f"System: Google-Enhanced LLM Query: {input} From:{nodeID}") @@ -123,32 +117,27 @@ def llm_query(input, nodeID=0, location_name=None): location_name += f" at the current time of {datetime.now().strftime('%Y-%m-%d %H:%M:%S %Z')}" try: - if enableOllamaClient: - result = ollamaClient.generate(model=llmModel, prompt=input) - result = result.get("response") - else: - result = chain_prompt_model.invoke({"input": input, "llmModel": llmModel, "userID": nodeID, \ - "history": llmChat_history, "context": googleResults, "location_name": location_name}) + # Build the query from the template + modelPrompt = meshBotAI.format(input=input, context='\n'.join(googleResults), location_name=location_name, llmModel=llmModel, history=history) + print(modelPrompt) + result = ollamaClient.generate(model=llmModel, prompt=modelPrompt) + result = result.get("response") + + #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." - + # cleanup for message output response = result.strip().replace('\n', ' ') - - # Store history of the conversation, with limit to prevent template growing too large causing speed issues - if len(llmChat_history) > llm_history_limit: - # remove the oldest two messages - llmChat_history.pop(0) - llmChat_history.pop(1) - inputWithUserID = input + f" user={nodeID}" - llmChat_history.append(HumanMessage(content=inputWithUserID)) - llmChat_history.append(AIMessage(content=response)) - # done with the query, remove the user from the anti flood list antiFloodLLM.remove(nodeID) + if llmEnableHistory: + llmChat_history[nodeID] = [input, response] + return response # import subprocess diff --git a/modules/settings.py b/modules/settings.py index fc00b76..cda97d2 100644 --- a/modules/settings.py +++ b/modules/settings.py @@ -113,6 +113,7 @@ try: wikipedia_enabled = config['general'].getboolean('wikipedia', False) llm_enabled = config['general'].getboolean('ollama', False) # https://ollama.com llmModel = config['general'].get('ollamaModel', 'gemma2:2b') # default gemma2:2b + ollamaHostName = config['general'].get('ollamaHostName', 'http://localhost:11434') # default localhost # sentry sentry_enabled = config['sentry'].getboolean('SentryEnabled', False) # default False diff --git a/requirements.txt b/requirements.txt index bf9657b..34e227e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,5 @@ numpy geopy schedule wikipedia -langchain -langchain-ollama ollama googlesearch-python