Version 1.21.13

This commit is contained in:
glibsonoran
2024-08-31 15:54:50 -07:00
parent b9bd6f778d
commit d08b457112
7 changed files with 190 additions and 16 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ if jmanager.on_startup(False):
else:
jmanager.log_events("config.json was not updated")
__version__ ="1.21.12"
__version__ ="1.21.13"
print('Plush - Version:', __version__)
+29 -1
View File
@@ -270,6 +270,12 @@ class oai_web_request(Request):
response = None
CGPT_response = ""
self.cFig.lm_url = url
if not self.cFig.is_lm_server_up:
self.j_mngr.log_events("Local or remote server is not responding, may be unable to send data.",
TroubleSgltn.Severity.WARNING,
True)
#if there's an image here
if image and request_type == self.mode.OSSIMPLE:
self.j_mngr.log_events("The AI Service using 'Simplfied Data' can't process an image. The image will be disregarded in generated output.",
@@ -404,6 +410,12 @@ class ooba_web_request(Request):
url = self.utils.validate_and_correct_url(url) #validate v1/chat/completions path
self.cFig.lm_url = url
if not self.cFig.is_lm_server_up:
self.j_mngr.log_events("Local server is not responding, may be unable to send data.",
TroubleSgltn.Severity.WARNING,
True)
#image code is here, but right now none of the tested LLM front ends can handle them
#when using an http POST
if image:
@@ -656,6 +668,7 @@ class dall_e_request(Request):
for _ in range(batch_size):
try:
response = client.images.generate(
model = GPTmodel,
prompt = prompt,
@@ -664,7 +677,7 @@ class dall_e_request(Request):
style = style,
n=1,
response_format = "b64_json",
)
)
# Get the revised_prompt
if response and not 'error' in response:
@@ -716,6 +729,21 @@ class dall_e_request(Request):
is_trouble=True)
self.trbl.pop_header()
return(batched_images, revised_prompt)
def modify_image(self, client, model, image_bytes, prompt, image_size):
"""This is an unused stub to be used if Dall-e-3 ever implements image to image edits"""
image_bytes.seek(0) # Ensure the buffer is at the beginning
response = client.images.edit(
model=model,
image=image_bytes,
prompt=prompt,
n=1,
size=image_size,
response_format = "b64_json"
)
return response
class request_context:
def __init__(self)-> None:
+57 -4
View File
@@ -2,7 +2,9 @@
from abc import ABC, abstractmethod
from enum import Enum
from .mng_json import json_manager, TroubleSgltn #add .
from .utils import CommUtils
import openai
import json
from groq import Groq
class RequestMode(Enum):
@@ -14,11 +16,13 @@ class RequestMode(Enum):
GEMINI = 6
OSSIMPLE = 7
LMSTUDIO = 8
OLLAMA = 9
class ModelFetchStrategy(ABC):
def __init__(self)->None:
self.j_mngr = json_manager()
self.utils = ModelUtils()
@abstractmethod
def fetch_models(self, api_obj, key):
@@ -71,8 +75,6 @@ class FetchGeminiModels(ModelFetchStrategy):
return packaged_models
class FetchByMethod(ModelFetchStrategy):
def fetch_models(self, api_obj, key:str):
@@ -87,6 +89,43 @@ class FetchByMethod(ModelFetchStrategy):
True)
return None
return model_list
class FetchOllama(ModelFetchStrategy):
def __init__(self)->None:
super().__init__() # Ensures common setup from Request
self.comm = CommUtils()
def fetch_models(self, api_obj, key):
"""Parameters are ignored in this method and class as Ollama is a local app that has no
imported api object and doesn't require a key. Ollama is unique among local apps
in that it requires a model name be passed in the request."""
url = self.utils.url_file("urls.json", "ollama_url")
t_response = self.comm.is_lm_server_up(url,1,2)
if t_response:
response = self.comm.get_data(url, retries=2)
else:
response = None
model_list = []
if response is None:
return ModelsContainer(model_list)
try:
data = response.json()
except json.JSONDecodeError as e:
self.j_mngr.log_events(f"Failed to decode Ollama models JSON file: {e}",
TroubleSgltn.Severity.WARNING,
True)
return ModelsContainer(model_list)
for model in data.get('models', []):
model_list.append(model.get('name'))
return ModelsContainer(model_list)
class FetchModels:
def __init__(self):
@@ -94,7 +133,7 @@ class FetchModels:
self.strategy = None
self.api_obj = None
def fetch_models(self, request_type:RequestMode, key: str):
def fetch_models(self, request_type:RequestMode, key: str=""):
if request_type == RequestMode.OPENAI:
self.api_obj = openai
@@ -111,6 +150,9 @@ class FetchModels:
elif request_type == RequestMode.GEMINI:
model_names = ['gemini-1.0-pro', 'gemini-1.0-pro-001', 'gemini-1.0-pro-latest', 'gemini-1.0-pro-vision-latest', 'gemini-1.5-pro-latest', 'gemini-pro', 'gemini-pro-vision']
return ModelsContainer(model_names)
elif request_type == RequestMode.OLLAMA:
self.strategy = FetchOllama()
if self.strategy and self.api_obj:
return self.strategy.fetch_models(self.api_obj, key)
@@ -144,6 +186,13 @@ class ModelUtils:
return prepped_models
def url_file(self, file_name:str, field_name:str) -> str:
url_file_name = self.j_mngr.append_filename_to_path(self.j_mngr.script_dir, file_name)
url_data = self.j_mngr.load_json(url_file_name)
if url_data:
return url_data.get(field_name,'')
return ''
#Create container for models that are generated in non-standard formats
class Model:
def __init__(self, model_id):
@@ -160,7 +209,11 @@ class ModelContainer:
def get_models(self, sort_it:bool=True, with_none:bool=True, filter_str:str="",):
models = ['none'] if with_none else []
models.extend(model for model in self._models if filter_str.lower() in model.lower())
if filter_str:
models.extend(model for model in self._models if filter_str.lower() in model.lower())
else:
models = self._models
if sort_it:
models.sort()
+1 -1
View File
File diff suppressed because one or more lines are too long
+40 -9
View File
@@ -48,6 +48,7 @@ class cFigSingleton:
cls._groq_models = None
cls._claude_models = None
cls._gemini_models = None
cls._ollama_models = None
cls._written_url = ""
cls.j_mngr = json_manager()
cls._model_fetch = FetchModels()
@@ -137,7 +138,7 @@ class cFigSingleton:
self._groq_models = self._model_fetch.fetch_models(RequestMode.GROQ, self._groq_key)
self._claude_models = self._model_fetch.fetch_models(RequestMode.CLAUDE, self._claude_key)
self._gemini_models = self._model_fetch.fetch_models(RequestMode.GEMINI, self._gemini_key)
self._ollama_models = self._model_fetch.fetch_models(RequestMode.OLLAMA, "")
def get_chat_models(self, sort_it:bool=False, filter_str:str="")->list:
return self._model_prep.prep_models_list(self._fig_gpt_models, sort_it, filter_str)
@@ -149,7 +150,10 @@ class cFigSingleton:
return self._model_prep.prep_models_list(self._claude_models, sort_it, filter_str)
def get_gemini_models(self, sort_it:bool=False, filter_str:str="")->list:
return self._model_prep.prep_models_list(self._gemini_models, sort_it, filter_str)
return self._model_prep.prep_models_list(self._gemini_models, sort_it, filter_str)
def get_ollama_models(self, sort_it:bool=False, filter_str:str="")->list:
return self._model_prep.prep_models_list(self._ollama_models, sort_it, filter_str)
def _set_llm_client(self, url:str, request_type:RequestMode=RequestMode.OPENSOURCE)-> bool:
@@ -228,6 +232,7 @@ class cFigSingleton:
#self._lm_models = []
if url: # If the new URL is not empty, update the client
self._set_llm_client(url, self._lm_request_mode)
def is_lm_server_up(self): #should be util in api_requests.py
@@ -243,6 +248,7 @@ class cFigSingleton:
True)
return True
else:
self.write_url(self._lm_url) #Save url to a text file
self.j_mngr.log_events(f"Server returned response code: {response.status_code}",
TroubleSgltn.Severity.INFO,
True)
@@ -647,7 +653,7 @@ class AdvPromptEnhancer:
if connection_type == "Anthropic":
return Anthropic_model
return local_model
return local_model
@classmethod
@@ -662,7 +668,7 @@ class AdvPromptEnhancer:
"ChatGPT_model": (cFig.get_chat_models(True,'gpt'), {"default": ""}),
"Groq_model": (cFig.get_groq_models(True), {"default": ""}),
"Anthropic_model": (cFig.get_claude_models(True), {"default": ""}),
"optional_local_model": ("STRING",{"default": "None"}),
"Ollama_model": (cFig.get_ollama_models(True), {"default": ""}),
"creative_latitude" : ("FLOAT", {"max": 1.901, "min": 0.1, "step": 0.1, "display": "number", "round": 0.1, "default": 0.7}),
"tokens" : ("INT", {"max": 8000, "min": 20, "step": 10, "default": 500, "display": "number"}),
"seed": ("INT", {"default": 9, "min": 0, "max": 0xffffffffffffffff}),
@@ -692,7 +698,7 @@ class AdvPromptEnhancer:
CATEGORY = "Plush/Prompt"
def gogo(self, AI_service, ChatGPT_model, Groq_model, Anthropic_model, optional_local_model, creative_latitude, tokens, seed, examples_delimiter,
def gogo(self, AI_service, ChatGPT_model, Groq_model, Anthropic_model, Ollama_model, creative_latitude, tokens, seed, examples_delimiter,
LLM_URL:str="", Instruction:str="", Prompt:str = "", Examples:str ="",image=None, unique_id=None):
if unique_id:
@@ -710,10 +716,10 @@ class AdvPromptEnhancer:
LLM_URL = Enhancer.undefined_to_none(LLM_URL)
image = Enhancer.undefined_to_none(image)
remote_model = self.get_model(ChatGPT_model, Groq_model, Anthropic_model, optional_local_model, AI_service)
remote_model = self.get_model(ChatGPT_model, Groq_model, Anthropic_model, Ollama_model, AI_service)
if remote_model == "None":
self.j_mngr.log_events("No model selected. If you're using a Local application it will most likely use the loaded model.",
if remote_model == "none":
self.j_mngr.log_events("No model selected. If you're using a local desktop application, most will just use the loaded model.",
TroubleSgltn.Severity.INFO,
True)
@@ -937,6 +943,29 @@ class DalleImage:
return base64_image
@staticmethod
def tensor_to_bytes(tensor: torch.Tensor) -> BytesIO:
"""
Converts a PyTorch tensor to a bytes object.
Args:
tensor (torch.Tensor): The image tensor to convert.
Returns:
BytesIO: BytesIO object containing the image data.
"""
# Convert tensor to PIL Image
if tensor.ndim == 4:
tensor = tensor.squeeze(0) # Remove batch dimension if present
pil_image = Image.fromarray((tensor.numpy() * 255).astype('uint8'))
# Save PIL Image to a buffer
buffer = BytesIO()
pil_image.save(buffer, format="PNG") # Can change to JPEG if preferred
buffer.seek(0)
return buffer
@classmethod
def INPUT_TYPES(cls):
#dall-e-2 API requires differnt input parameters as compared to dall-e-3, at this point I'll just use dall-e-3
@@ -974,6 +1003,7 @@ class DalleImage:
else:
self.trbl.reset('Dall-e Image Node')
_help = self.help_data.dalle_help
self.ctx.request = rqst.dall_e_request()
kwargs = { "model": GPTmodel,
@@ -981,7 +1011,7 @@ class DalleImage:
"image_size": image_size,
"image_quality": image_quality,
"style": style,
"batch_size": batch_size
"batch_size": batch_size,
}
batched_images, revised_prompt = self.ctx.execute_request(**kwargs)
@@ -1305,3 +1335,4 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"DalleImage": "OAI Dall_e Image",
"ImageInfoExtractor": "Exif Wrangler"
}
+3
View File
@@ -0,0 +1,3 @@
{
"ollama_url": "http://localhost:11434/api/tags"
}
+59
View File
@@ -0,0 +1,59 @@
import requests
from requests.adapters import HTTPAdapter, Retry
from .mng_json import json_manager, TroubleSgltn
class CommUtils:
def __init__(self)->None:
self.j_mngr = json_manager()
def is_lm_server_up(self, endpoint:str, comm_retries:int=2, timeout:int=4): #should be util in api_requests.py
session = requests.Session()
retries = Retry(total=comm_retries, backoff_factor=0, status_forcelist=[500, 502, 503, 504])
session.mount('http://', HTTPAdapter(max_retries=retries))
try:
response = session.head(endpoint, timeout=timeout) # Use HEAD to minimize data transfer
if 200 <= response.status_code <= 300:
self.write_url(endpoint) #Save url to a text file
self.j_mngr.log_events(f"Local LLM Server is running with status code: {response.status_code}",
TroubleSgltn.Severity.INFO,
True)
return True
else:
self.j_mngr.log_events(f"Server returned response code: {response.status_code}",
TroubleSgltn.Severity.INFO,
True)
return True
except requests.RequestException as e:
self.j_mngr.log_events(f"Local LLM Server is not running: {e}",
TroubleSgltn.Severity.WARNING,
True)
return False
def get_data(self, endpoint:str="", timeout:int=8, retries:int=1, data_type:str="" )-> requests.Response | None:
session = requests.Session()
gretries = Retry(total=retries, backoff_factor=0, status_forcelist=[500, 502, 503, 504])
session.mount('http://', HTTPAdapter(max_retries=gretries))
stat_code = 0
try:
response = session.get(endpoint, timeout=timeout)
stat_code = response.status_code
response.raise_for_status() # Raises an HTTPError if the response status code indicates an error
return response
except requests.RequestException as e:
self.j_mngr.log_events(f"Unable to fetch data for: {data_type}. Server returned code: {stat_code}. Error: {e} ",
TroubleSgltn.Severity.WARNING,
True)
return None
def write_url(self, url:str) -> bool:
# Save the current open source url for startup retrieval of models
url_file = self.j_mngr.append_filename_to_path(self.j_mngr.script_dir, 'OpenSourceURL.txt')
url_result = self.j_mngr.write_string_to_file(url, url_file)
self._written_url = url
self.j_mngr.log_events("Open source LLM URL saved to file.",
TroubleSgltn.Severity.INFO,
True)
return url_result