Version 1.21.13
This commit is contained in:
+1
-1
@@ -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
@@ -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
@@ -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()
|
||||
|
||||
+40
-9
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user