'update'
This commit is contained in:
+30
-1
@@ -60,9 +60,12 @@ class MZ_LLamaCPPModelConfig_ManualSelect:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
gguf_files = Utils.get_gguf_files()
|
||||
|
||||
chat_format = mz_llama_cpp.get_llama_cpp_chat_handlers()
|
||||
return {
|
||||
"required": {
|
||||
"llama_cpp_model": (gguf_files,),
|
||||
"chat_format": (["auto"] + chat_format, {"default": "auto"}),
|
||||
},
|
||||
"optional": {
|
||||
},
|
||||
@@ -82,9 +85,13 @@ class MZ_LLamaCPPModelConfig_ManualSelect:
|
||||
llama_cpp_model = os.path.join(
|
||||
Utils.get_gguf_models_path(), llama_cpp_model)
|
||||
|
||||
chat_format = kwargs.get("chat_format", "auto")
|
||||
if chat_format == "auto":
|
||||
chat_format = None
|
||||
return ({
|
||||
"type": "ManualSelect",
|
||||
"model_path": llama_cpp_model,
|
||||
"chat_format": chat_format,
|
||||
},)
|
||||
|
||||
|
||||
@@ -100,9 +107,11 @@ class MZ_LLamaCPPModelConfig_DownloaderSelect:
|
||||
model_names = [
|
||||
model["model"] for model in optional_models
|
||||
]
|
||||
chat_format = mz_llama_cpp.get_llama_cpp_chat_handlers()
|
||||
return {
|
||||
"required": {
|
||||
"model_name": (model_names,),
|
||||
"chat_format": (["auto"] + chat_format, {"default": "auto"}),
|
||||
},
|
||||
"optional": {
|
||||
},
|
||||
@@ -118,9 +127,13 @@ class MZ_LLamaCPPModelConfig_DownloaderSelect:
|
||||
kwargs = kwargs.copy()
|
||||
|
||||
model_name = kwargs.get("model_name", "")
|
||||
chat_format = kwargs.get("chat_format", "auto")
|
||||
if chat_format == "auto":
|
||||
chat_format = None
|
||||
return ({
|
||||
"type": "DownloaderSelect",
|
||||
"model_name": model_name,
|
||||
"chat_format": chat_format,
|
||||
},)
|
||||
|
||||
|
||||
@@ -211,6 +224,9 @@ class MZ_LLamaCPPOptions:
|
||||
opt = {}
|
||||
for key in kwargs:
|
||||
opt[key] = kwargs[key]
|
||||
|
||||
# if opt.get("chat_format", None) == "auto":
|
||||
# opt["chat_format"] = None
|
||||
return (opt,)
|
||||
|
||||
|
||||
@@ -370,6 +386,7 @@ class MZ_ImageInterrogatorCLIPTextEncode:
|
||||
return {
|
||||
"required": {
|
||||
"resolution": ("INT", {"default": 512, "min": 128, "max": 0xffffffffffffffff}),
|
||||
"post_processing": ([False, True], {"default": True}),
|
||||
"keep_device": ([False, True], {"default": False}),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
},
|
||||
@@ -406,10 +423,12 @@ class MZ_ImageInterrogatorModelConfig_ManualSelect:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
gguf_files = Utils.get_gguf_files()
|
||||
chat_format = mz_llama_cpp.get_llama_cpp_chat_handlers()
|
||||
return {
|
||||
"required": {
|
||||
"llama_cpp_model": (gguf_files,),
|
||||
"mmproj_model": (["auto"] + gguf_files,),
|
||||
"chat_format": (["auto"] + chat_format, {"default": "auto"}),
|
||||
},
|
||||
"optional": {
|
||||
},
|
||||
@@ -434,10 +453,14 @@ class MZ_ImageInterrogatorModelConfig_ManualSelect:
|
||||
mmproj_model = os.path.join(
|
||||
Utils.get_gguf_models_path(), mmproj_model)
|
||||
|
||||
chat_format = kwargs.get("chat_format", "auto")
|
||||
if chat_format == "auto":
|
||||
chat_format = None
|
||||
return ({
|
||||
"type": "ManualSelect",
|
||||
"model_path": llama_cpp_model,
|
||||
"mmproj_model": mmproj_model,
|
||||
"chat_format": chat_format,
|
||||
},)
|
||||
|
||||
|
||||
@@ -459,10 +482,12 @@ class MZ_ImageInterrogatorModelConfig_DownloaderSelect:
|
||||
model["model"] for model in optional_models
|
||||
]
|
||||
|
||||
chat_format = mz_llama_cpp.get_llama_cpp_chat_handlers()
|
||||
return {
|
||||
"required": {
|
||||
"model_name": (model_names,),
|
||||
"mmproj_model_name": (mmproj_model_names,),
|
||||
"mmproj_model_name": (["auto"] + mmproj_model_names,),
|
||||
"chat_format": (["auto"] + chat_format, {"default": "auto"}),
|
||||
},
|
||||
"optional": {
|
||||
},
|
||||
@@ -478,10 +503,14 @@ class MZ_ImageInterrogatorModelConfig_DownloaderSelect:
|
||||
kwargs = kwargs.copy()
|
||||
model_name = kwargs.get("model_name")
|
||||
mmproj_model_name = kwargs.get("mmproj_model_name", "auto")
|
||||
chat_format = kwargs.get("chat_format", "auto")
|
||||
if chat_format == "auto":
|
||||
chat_format = None
|
||||
return ({
|
||||
"type": "DownloaderSelect",
|
||||
"model_name": model_name,
|
||||
"mmproj_model_name": mmproj_model_name,
|
||||
"chat_format": chat_format,
|
||||
},)
|
||||
|
||||
|
||||
|
||||
+349
@@ -0,0 +1,349 @@
|
||||
# coding=utf8
|
||||
import json
|
||||
from typing import Any, List, NamedTuple, Optional, Tuple
|
||||
import json.decoder
|
||||
from json.decoder import JSONDecodeError as PyJSONDecodeError, JSONDecoder, py_scanstring
|
||||
from json.scanner import py_make_scanner
|
||||
from typing import Any, Dict, NamedTuple, Optional, Tuple, Union
|
||||
|
||||
|
||||
class FixResult(NamedTuple):
|
||||
success: bool
|
||||
line: str
|
||||
origin: bool
|
||||
|
||||
|
||||
class JSONFixer:
|
||||
def __init__(self, max_try: int = 20, max_stack: int = 3, *, js_style: bool = False) -> None:
|
||||
self._max_try = max_try
|
||||
self._max_stack = max_stack
|
||||
self._js_style = js_style
|
||||
self.last_fix: Optional[bool] = None
|
||||
self.fix_stack: List[str] = []
|
||||
|
||||
def fix(self, line: str, *, strict: bool = True) -> FixResult:
|
||||
try:
|
||||
json.loads(line, strict=strict)
|
||||
return FixResult(success=True, line=line, origin=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
ok, new_line = self.fixwithtry(line, strict=strict)
|
||||
return FixResult(success=ok, line=new_line, origin=False)
|
||||
|
||||
def fixwithtry(self, line: str, *, strict: bool = True) -> Tuple[bool, str]:
|
||||
if self._max_try <= 0:
|
||||
return False, line
|
||||
|
||||
self.fix_stack = []
|
||||
self.last_fix = None
|
||||
|
||||
ok = False
|
||||
for _ in range(self._max_try):
|
||||
ok, new_line = self.patch_line(line, strict=strict)
|
||||
if ok:
|
||||
return ok, new_line
|
||||
|
||||
self.last_fix = line != new_line
|
||||
if self.last_fix:
|
||||
self.fix_stack.insert(0, new_line)
|
||||
self.fix_stack = self.fix_stack[: self._max_stack]
|
||||
|
||||
line = new_line
|
||||
return ok, line
|
||||
|
||||
def patch_line(self, line: str, *, strict: bool = True) -> Tuple[bool, str]:
|
||||
result = decode_line(line, strict=strict)
|
||||
if result.success:
|
||||
return True, line
|
||||
|
||||
if isinstance(result.exception, ValueError):
|
||||
return self.patch_value_error(line, result.err_info)
|
||||
|
||||
if isinstance(result.exception, StopIteration):
|
||||
return self.patch_stop_iteration(line)
|
||||
|
||||
if result.exception is None:
|
||||
return self.patch_half_parse(line, result.err_info)
|
||||
|
||||
return False, line
|
||||
|
||||
def patch_value_error(self, line: str, err_info: Any) -> Tuple[bool, str]:
|
||||
if err_info["error"] is None:
|
||||
return False, line
|
||||
|
||||
error = err_info["error"]
|
||||
pos = err_info["pos"]
|
||||
nextchar = line[pos: pos + 1]
|
||||
lastchar = line[pos - 1: pos]
|
||||
nextline = line[pos:]
|
||||
lastline = line[:pos]
|
||||
|
||||
if error == errors.StringUnterminatedString:
|
||||
return False, insert_line(line, '"', len(line))
|
||||
if error == errors.ObjectExceptKey:
|
||||
if nextchar == "":
|
||||
return False, insert_line(line, "}", pos)
|
||||
if nextchar == ":":
|
||||
return False, insert_line(line, '""', pos)
|
||||
if lastchar in "{," and nextchar == ",":
|
||||
return False, remove_line(line, pos, pos + 1)
|
||||
if lastchar == "," and nextchar == "}":
|
||||
return False, remove_line(line, pos - 1, pos)
|
||||
if nextchar in "[{":
|
||||
return False, insert_line(line, '"":', pos)
|
||||
if self._js_style:
|
||||
# find 'abc'
|
||||
if nextchar == "'":
|
||||
nextline = remove_line(nextline, 0, 1)
|
||||
idx = nextline.find(":")
|
||||
if idx != -1 and idx != 0 and nextline[idx - 1] == "'":
|
||||
nextline = remove_line(nextline, idx - 1, idx)
|
||||
|
||||
return False, lastline + nextline
|
||||
# abc:1 --> "aabc":1
|
||||
idx = nextline.find(":")
|
||||
if idx != -1:
|
||||
line = lastline + insert_line(nextline, '"', idx)
|
||||
return False, insert_line(line, '"', pos)
|
||||
# TODO process more case "
|
||||
return False, insert_line(line, '"', pos)
|
||||
if error == errors.ObjectExceptColon:
|
||||
return False, insert_line(line, ":", pos)
|
||||
if error == errors.ObjectExceptObject:
|
||||
if nextchar == "":
|
||||
if lastchar == "{":
|
||||
return False, insert_line(line, "}", pos)
|
||||
return False, insert_line(line, "null}", pos)
|
||||
if nextchar == "}":
|
||||
return False, insert_line(line, "null", pos)
|
||||
# TODO guess more
|
||||
return False, insert_line(line, '"', pos)
|
||||
if error == errors.ObjectExceptComma:
|
||||
if nextchar == "":
|
||||
return False, insert_line(line, "}", pos)
|
||||
return False, insert_line(line, ",", pos)
|
||||
if error == errors.ArrayExceptObject:
|
||||
if nextchar == "," and lastchar == "[":
|
||||
return False, remove_line(line, pos, pos + 1)
|
||||
if nextchar == ",":
|
||||
return False, insert_line(line, "null", pos)
|
||||
if nextchar == "]":
|
||||
return False, remove_line(line, pos - 1, pos)
|
||||
if nextchar == "":
|
||||
if lastchar == "[":
|
||||
return False, insert_line(line, "]", pos)
|
||||
return False, insert_line(line, "null]", pos)
|
||||
# TODO guess more?
|
||||
return False, insert_line(line, "{", pos)
|
||||
if error == errors.ArrayExceptComma:
|
||||
if len(line) == pos:
|
||||
return False, insert_line(line, "]", pos)
|
||||
return False, insert_line(line, ",", pos)
|
||||
# TODO unknonwn
|
||||
return False, line
|
||||
|
||||
def patch_stop_iteration(self, line: str) -> Tuple[bool, str]:
|
||||
# TODO clean
|
||||
# TODO fix
|
||||
# 1. }]
|
||||
# 2. ]}
|
||||
# 3. constans
|
||||
# 4. -
|
||||
# 先 patch 完 {[]}
|
||||
# TODO: process number
|
||||
if line.startswith("-."):
|
||||
new_line = "-0." + line[2:]
|
||||
return False, new_line
|
||||
# patch
|
||||
left = patch_lastest_left_object_and_array(line)
|
||||
if left == "":
|
||||
if not self.last_fix:
|
||||
left = patch_guess_left(line)
|
||||
|
||||
new_line = left + line
|
||||
return False, new_line
|
||||
|
||||
def patch_half_parse(self, line: str, err_info: Any) -> Tuple[bool, str]:
|
||||
obj, end = err_info
|
||||
nextline = line[end:].strip()
|
||||
nextchar = nextline[:1]
|
||||
left = patch_lastest_left_object_and_array(nextline)
|
||||
# ??
|
||||
if left == "":
|
||||
if nextchar == ",":
|
||||
left = "["
|
||||
elif nextchar == ":" and isinstance(obj, str):
|
||||
left = "{"
|
||||
else:
|
||||
if not self.last_fix:
|
||||
left = patch_guess_left(nextline)
|
||||
|
||||
new_line = left + line[:end] + nextline
|
||||
return False, new_line
|
||||
|
||||
|
||||
# TODO better name
|
||||
def patch_lastest_left_object_and_array(line: str) -> str:
|
||||
# '}]{[' --> '[{}]{['
|
||||
pairs = {"}": "{", "]": "["}
|
||||
breaks = "{["
|
||||
left = ""
|
||||
for char in line:
|
||||
if char in breaks:
|
||||
break
|
||||
if char in pairs:
|
||||
left = pairs[char] + left
|
||||
|
||||
return left
|
||||
|
||||
|
||||
# TODO better name
|
||||
# TODO 改成 lastest
|
||||
# TODO {}}]]]] --> { not [
|
||||
def patch_guess_left(line: str) -> str:
|
||||
miss_object = line.count("}") - line.count("{")
|
||||
miss_array = line.count("]") - line.count("[")
|
||||
if miss_object == miss_array == 0:
|
||||
if line[-1:] == '"' and line.count('"') == 1:
|
||||
return '"'
|
||||
elif miss_object >= miss_array:
|
||||
return "{"
|
||||
else:
|
||||
return "["
|
||||
return ""
|
||||
|
||||
|
||||
def insert_line(line: str, value: str, pos: int) -> str:
|
||||
return line[:pos] + value + line[pos:]
|
||||
|
||||
|
||||
def remove_line(line: str, start: int, end: int) -> str:
|
||||
return line[:start] + line[end:]
|
||||
|
||||
|
||||
class JSONDecodeError:
|
||||
def __init__(self, parser, message):
|
||||
self.message = message
|
||||
self.parser = parser
|
||||
|
||||
def __eq__(self, err):
|
||||
return err.parser == self.parser and self.message in err.message
|
||||
|
||||
|
||||
class errors:
|
||||
StringInvalidUXXXXEscape = JSONDecodeError(
|
||||
"py_scanstring", "Invalid \\uXXXX escape")
|
||||
# 2 different case
|
||||
StringUnterminatedString = JSONDecodeError(
|
||||
"py_scanstring", "Unterminated string starting at")
|
||||
StringInvalidControlCharacter = JSONDecodeError(
|
||||
"py_scanstring", "Invalid control character")
|
||||
StringInvalidEscape = JSONDecodeError("py_scanstring", "Invalid \\escape")
|
||||
ObjectExceptColon = JSONDecodeError(
|
||||
"JSONObject", "Expecting ':' delimiter")
|
||||
ObjectExceptObject = JSONDecodeError("JSONObject", "Expecting value")
|
||||
# 2 different case
|
||||
ObjectExceptKey = JSONDecodeError(
|
||||
"JSONObject", "Expecting property name enclosed in double quotes")
|
||||
ObjectExceptComma = JSONDecodeError(
|
||||
"JSONObject", "Expecting ',' delimiter")
|
||||
ArrayExceptObject = JSONDecodeError("JSONArray", "Expecting value")
|
||||
ArrayExceptComma = JSONDecodeError("JSONArray", "Expecting ',' delimiter")
|
||||
|
||||
@classmethod
|
||||
def get_decode_error(cls, parser, message):
|
||||
err = JSONDecodeError(parser, message)
|
||||
for _, value in cls.__dict__.items():
|
||||
if isinstance(value, JSONDecodeError):
|
||||
if err == value:
|
||||
return value
|
||||
return None
|
||||
|
||||
"""
|
||||
01 先不看,不研究
|
||||
02 badcase: " --> "" success
|
||||
03 控制符 pass
|
||||
04 unicode \\u 的 pass
|
||||
05 同上
|
||||
06 object 后面没有跟随 " , badcase: {abc":1} --> {"abc":1}
|
||||
07 object key 后面没有 : , badcase: {"abc"1} --> {"abc":1}
|
||||
08 object 开始检测 Value 收到 StopIteration
|
||||
08.1 要么后面没有了
|
||||
08.2 要么后面不是 "/{/[/n[ull]/t[rue]/f[alse]/number/NaN/Infinity/-Infinity 开头的东西
|
||||
-- 08.1 后面补上 null}
|
||||
-- 08.2 无脑补一个 "
|
||||
09 object 解析完一个 pair 后,下一个不是}, 期待一个 ','
|
||||
badcase {"k":1"s":2}
|
||||
10 在 09 的基础上解析完{"k":1, 发现下一个不是 ", 这个后面再优化(暂时和 06 一致)
|
||||
badcase {"k":1,x":2}
|
||||
11 array 开始检测 Value 收到 StopIteration
|
||||
11.1 要么后面没有了,补上]
|
||||
11.2 同 08.2,无脑补一个{ 看看
|
||||
12 array 解析完前一个 object, 需要一个 ,
|
||||
这里 nextchar 既不是 ] 也不是, 代表这个 nextchar 的 end 也已经+1 了,所以减 2
|
||||
"""
|
||||
|
||||
|
||||
def errmsg_inv(e: ValueError) -> Dict[str, Any]:
|
||||
assert isinstance(e, PyJSONDecodeError)
|
||||
parser = e.__dict__.get("parser", "")
|
||||
errmsg = e.msg
|
||||
localerr = errors.get_decode_error(parser, errmsg)
|
||||
return {
|
||||
"parsers": e.__dict__.get("parsers", []),
|
||||
"error": localerr,
|
||||
"lineno": e.lineno,
|
||||
"colno": e.colno,
|
||||
"pos": e.pos,
|
||||
}
|
||||
|
||||
|
||||
def record_parser_name(parser: Any) -> Any:
|
||||
def new_parser(*args: Any, **kwargs: Any) -> Any:
|
||||
try:
|
||||
return parser(*args, **kwargs)
|
||||
except Exception as e:
|
||||
if "parser" not in e.__dict__:
|
||||
e.__dict__["parser"] = parser.__name__
|
||||
if "parsers" not in e.__dict__:
|
||||
e.__dict__["parsers"] = []
|
||||
e.__dict__["parsers"].append(parser.__name__)
|
||||
raise e
|
||||
|
||||
return new_parser
|
||||
|
||||
|
||||
def make_decoder(*, strict: bool = True) -> JSONDecoder:
|
||||
json.decoder.scanstring = record_parser_name(py_scanstring)
|
||||
|
||||
decoder = JSONDecoder(strict=strict)
|
||||
decoder.parse_object = record_parser_name(decoder.parse_object)
|
||||
decoder.parse_array = record_parser_name(decoder.parse_array)
|
||||
decoder.parse_string = record_parser_name(py_scanstring)
|
||||
decoder.parse_object = record_parser_name(decoder.parse_object)
|
||||
|
||||
decoder.scan_once = py_make_scanner(decoder)
|
||||
return decoder
|
||||
|
||||
|
||||
decoder = make_decoder()
|
||||
decoder_unstrict = make_decoder(strict=False)
|
||||
|
||||
|
||||
class DecodeResult(NamedTuple):
|
||||
success: bool
|
||||
exception: Optional[Exception]
|
||||
err_info: Optional[Union[Dict[str, Any], Tuple[Any, Any]]]
|
||||
|
||||
|
||||
def decode_line(line: str, *, strict: bool = True) -> DecodeResult:
|
||||
try:
|
||||
obj, end = (decoder if strict else decoder_unstrict).scan_once(line, 0)
|
||||
ok = end == len(line)
|
||||
return DecodeResult(success=ok, exception=None, err_info=(obj, end))
|
||||
except StopIteration as e:
|
||||
return DecodeResult(success=False, exception=e, err_info=None)
|
||||
except ValueError as e:
|
||||
err_info = errmsg_inv(e)
|
||||
return DecodeResult(success=False, exception=e, err_info=err_info)
|
||||
@@ -35,6 +35,7 @@ ZH_Replace_Map = {
|
||||
"ModelConfigManualSelect": "手动模型选择器",
|
||||
"ModelConfigDownloaderSelect": "预设模型下载器",
|
||||
"captioner_config": "打标器配置",
|
||||
"post_processing": "后处理",
|
||||
}
|
||||
|
||||
|
||||
|
||||
+141
-10
@@ -56,16 +56,23 @@ def get_style_presets():
|
||||
def llama_cpp_node_encode(args_dict):
|
||||
importlib.reload(mz_prompts)
|
||||
importlib.reload(mz_llama_cpp)
|
||||
# importlib.reload(mz_prompt_utils)
|
||||
|
||||
model_config = args_dict.get("llama_cpp_model", {})
|
||||
mz_prompt_utils.Utils.print_log(f"model_config: {model_config}")
|
||||
|
||||
chat_format = model_config.get("chat_format", None)
|
||||
|
||||
select_model_type = model_config.get("type", "ManualSelect")
|
||||
if select_model_type == "ManualSelect":
|
||||
model_file = model_config.get("model_path", "auto")
|
||||
if model_file == "auto":
|
||||
model_file = mz_prompt_utils.Utils.get_auto_model_fullpath(
|
||||
"Meta-Llama-3-8B-Instruct.Q4_K_M")
|
||||
|
||||
if "llama-3" in mz_llama_cpp.get_llama_cpp_chat_handlers():
|
||||
chat_format = "llama-3"
|
||||
|
||||
elif select_model_type == "DownloaderSelect":
|
||||
model_name = model_config.get("model_name", "")
|
||||
model_file = mz_prompt_utils.Utils.get_auto_model_fullpath(
|
||||
@@ -81,6 +88,7 @@ def llama_cpp_node_encode(args_dict):
|
||||
keep_device = args_dict.get("keep_device", False)
|
||||
seed = args_dict.get("seed", -1)
|
||||
options["seed"] = seed
|
||||
options["chat_format"] = chat_format
|
||||
|
||||
customize_instruct = args_dict.get("customize_instruct", None)
|
||||
mz_prompt_utils.Utils.print_log(
|
||||
@@ -136,8 +144,19 @@ def llama_cpp_node_encode(args_dict):
|
||||
schema=schema,
|
||||
options=options,
|
||||
)
|
||||
try:
|
||||
response_json = json.loads(response_text)
|
||||
except Exception as e:
|
||||
from . import half_json
|
||||
print("json.loads failed, try fix response_text: ", response_text)
|
||||
json_fixer = half_json.JSONFixer()
|
||||
fix_resp = json_fixer.fix(response_text)
|
||||
if fix_resp.success:
|
||||
print("fix success, use fixed response_text: ", fix_resp.line)
|
||||
response_json = json.loads(fix_resp.line)
|
||||
else:
|
||||
raise e
|
||||
|
||||
response_json = json.loads(response_text)
|
||||
mz_prompt_utils.Utils.print_log(
|
||||
f"response_json: {json.dumps(response_json, indent=2)}")
|
||||
|
||||
@@ -322,6 +341,8 @@ def image_interrogator_node_encode(args_dict):
|
||||
"图片批量反推任务已完成 ; Image batch reverse push task completed")
|
||||
|
||||
model_config = args_dict.get("image_interrogator_model", {})
|
||||
|
||||
chat_format = model_config.get("chat_format", None)
|
||||
llama_cpp_model = model_config.get("llama_cpp_model", "auto")
|
||||
mmproj_model = model_config.get("mmproj_model", "auto")
|
||||
|
||||
@@ -401,13 +422,20 @@ def image_interrogator_node_encode(args_dict):
|
||||
seed = args_dict.get("seed", -1)
|
||||
options = args_dict.get("llama_cpp_options", {})
|
||||
options["seed"] = seed
|
||||
options["chat_format"] = chat_format
|
||||
|
||||
image = mz_prompt_utils.Utils.resize_max(image, resolution, resolution)
|
||||
|
||||
customize_instruct = args_dict.get("customize_instruct", None)
|
||||
if customize_instruct is None:
|
||||
system_prompt = mz_prompts.M_ImageCaptioner_System
|
||||
question = mz_prompts.M_ImageCaptioner_Prompt
|
||||
# system_prompt = mz_prompts.GPT4VImageCaptioner_System
|
||||
# question = mz_prompts.GPT4VImageCaptioner_Prompt
|
||||
|
||||
# system_prompt = mz_prompts.M_ImageCaptioner2_System
|
||||
# question = mz_prompts.M_ImageCaptioner2_Prompt
|
||||
|
||||
system_prompt = "You are an assistant who perfectly describes images."
|
||||
question = "Describe this image in detail please."
|
||||
else:
|
||||
system_prompt = customize_instruct.get("system", "")
|
||||
question = customize_instruct.get("instruct", "")
|
||||
@@ -421,13 +449,116 @@ def image_interrogator_node_encode(args_dict):
|
||||
system=system_prompt,
|
||||
question=question,
|
||||
)
|
||||
if response is not None:
|
||||
response = response.strip()
|
||||
if customize_instruct is None:
|
||||
# 去除开头的In the image,
|
||||
start_text = "In the image, "
|
||||
if response.startswith(start_text):
|
||||
response = response[len(start_text):]
|
||||
response = response.strip()
|
||||
if response is not None and response != "":
|
||||
|
||||
if args_dict.get("post_processing", False):
|
||||
|
||||
# 双引号换成空格
|
||||
response = response.replace("\"", " ")
|
||||
# 中括号换成空格
|
||||
response = response.replace("[", " ")
|
||||
response = response.replace("]", " ")
|
||||
|
||||
# 括号换成空格
|
||||
response = response.replace("(", " ")
|
||||
response = response.replace(")", " ")
|
||||
|
||||
# 去除多余空格
|
||||
while response.find(" ") != -1:
|
||||
response = response.replace(" ", " ")
|
||||
|
||||
# 从第一个为英文字母的地方开始截取
|
||||
for i in range(len(response)):
|
||||
if response[i].isalpha():
|
||||
response = response[i:]
|
||||
break
|
||||
|
||||
response = response.strip()
|
||||
schema = get_schema_obj(
|
||||
keys_type={
|
||||
"short_describes": get_schema_base_type("string"),
|
||||
"subject_tags": get_schema_array("string"),
|
||||
"action_tags": get_schema_array("string"),
|
||||
"light_tags": get_schema_array("string"),
|
||||
"scene_tags": get_schema_array("string"),
|
||||
"mood_tags": get_schema_array("string"),
|
||||
"style_tags": get_schema_array("string"),
|
||||
"object_tags": get_schema_array("string"),
|
||||
},
|
||||
required=[
|
||||
"short_describes",
|
||||
"subject_tags",
|
||||
"action_tags",
|
||||
"lights_tags",
|
||||
"scenes_tags",
|
||||
"moods_tags",
|
||||
"styles_tags",
|
||||
"objects_tags",
|
||||
]
|
||||
)
|
||||
response_json_str = mz_llama_cpp.llama_cpp_simple_interrogator_to_json(
|
||||
model_file=llama_cpp_model,
|
||||
system=mz_prompts.ImageCaptionerPostProcessing_System,
|
||||
question=f"Content: {response}",
|
||||
schema=schema,
|
||||
options=options,
|
||||
)
|
||||
|
||||
try:
|
||||
response_json = json.loads(response_json_str)
|
||||
except Exception as e:
|
||||
from . import half_json
|
||||
print("json.loads failed, try fix response_json_str: ",
|
||||
response_json_str)
|
||||
json_fixer = half_json.JSONFixer()
|
||||
fix_resp = json_fixer.fix(response_json_str)
|
||||
if fix_resp.success:
|
||||
print("fix success, use fixed response_json_str: ",
|
||||
fix_resp.line)
|
||||
response_json = json.loads(fix_resp.line)
|
||||
else:
|
||||
raise e
|
||||
|
||||
responses = []
|
||||
|
||||
def pure_words(text: str) -> bool:
|
||||
number_of_spaces = text.count(" ")
|
||||
if number_of_spaces > 2:
|
||||
return False
|
||||
for c in text:
|
||||
if not c.isalpha() and c != "-" and c != "_" and c != " ":
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
for key, value in response_json.items():
|
||||
if type(value) == list:
|
||||
|
||||
# 去除开头.和空格
|
||||
value = [v.strip().lstrip(".") for v in value]
|
||||
# 去除空字符串
|
||||
value = [v for v in value if v != ""]
|
||||
|
||||
# 去除带有空格和标点符号的字符串
|
||||
value = [
|
||||
v for v in value if pure_words(v)]
|
||||
|
||||
# 空格换成下划线
|
||||
value = [v.replace(" ", "_") for v in value]
|
||||
|
||||
# 首字母小写
|
||||
value = [v.lower() for v in value]
|
||||
|
||||
if len(value) > 0:
|
||||
responses.append(f"{', '.join(value)}")
|
||||
|
||||
description = response_json.get("short_describes", "")
|
||||
if description != "":
|
||||
responses.append(f"{description}")
|
||||
|
||||
# 对response进行去重
|
||||
response = ", ".join(responses)
|
||||
|
||||
if keep_device is False:
|
||||
mz_llama_cpp.freed_gpu_memory(model_file=llama_cpp_model)
|
||||
|
||||
+42
-1
@@ -1,3 +1,4 @@
|
||||
import copy
|
||||
import importlib
|
||||
import json
|
||||
import os
|
||||
@@ -109,8 +110,19 @@ def check_llama_cpp_requirements():
|
||||
print("llama_cpp installed successfully. (llama_cpp安装成功)")
|
||||
|
||||
|
||||
def get_llama_cpp_chat_handlers():
|
||||
check_llama_cpp_requirements()
|
||||
from llama_cpp import llama_chat_format
|
||||
chat_handlers = llama_chat_format.LlamaChatCompletionHandlerRegistry()._chat_handlers
|
||||
chat_handlers = list(chat_handlers.keys())
|
||||
|
||||
return chat_handlers
|
||||
|
||||
|
||||
def LlamaCppOptions():
|
||||
# chat_handlers = ["auto"] + get_llama_cpp_chat_handlers()
|
||||
return {
|
||||
# "chat_format": chat_handlers,
|
||||
"n_ctx": 2048,
|
||||
"n_batch": 2048,
|
||||
"n_threads": 0,
|
||||
@@ -170,6 +182,9 @@ def llama_cpp_messages(model_file, mmproj_file=None, messages=[], options={}):
|
||||
|
||||
is_opts_changed = False
|
||||
|
||||
mz_prompt_utils.Utils.print_log(
|
||||
f"llama_cpp_messages chat_format: {options.get('chat_format', None)}")
|
||||
|
||||
if model_and_opt is not None:
|
||||
for opt in init_opts:
|
||||
if model_and_opt.get("options").get(opt) != options.get(opt):
|
||||
@@ -259,6 +274,25 @@ def llama_cpp_messages(model_file, mmproj_file=None, messages=[], options={}):
|
||||
mirostat_mode = 1
|
||||
elif options.get("mirostat_mode", "none") == "mirostat_v2":
|
||||
mirostat_mode = 2
|
||||
|
||||
try:
|
||||
debuf_messages = copy.deepcopy(messages)
|
||||
for dindex in range(len(debuf_messages)):
|
||||
if debuf_messages[dindex].get("role") == "user":
|
||||
debuf_messages_content = debuf_messages[dindex].get(
|
||||
"content", [])
|
||||
if type(debuf_messages_content) != list:
|
||||
continue
|
||||
for ccindex in range(len(debuf_messages_content)):
|
||||
if debuf_messages_content[ccindex].get("type") == "image_url":
|
||||
debuf_messages[dindex]["content"][ccindex]["image_url"] = debuf_messages[
|
||||
dindex]["content"][ccindex]["image_url"] = None
|
||||
|
||||
mz_prompt_utils.Utils.print_log(
|
||||
f"LLAMA_CPP messages: {json.dumps(debuf_messages, indent=4, ensure_ascii=False)}")
|
||||
except Exception as e:
|
||||
mz_prompt_utils.Utils.print_log(
|
||||
f"LLAMA_CPP messages: {messages}")
|
||||
output = model.create_chat_completion(
|
||||
messages=messages,
|
||||
response_format=response_format,
|
||||
@@ -276,6 +310,8 @@ def llama_cpp_messages(model_file, mmproj_file=None, messages=[], options={}):
|
||||
mirostat_mode=mirostat_mode,
|
||||
mirostat_tau=options.get("mirostat_tau", 5.0),
|
||||
mirostat_eta=options.get("mirostat_eta", 0.1),
|
||||
tools=options.get("tools", None),
|
||||
tool_choice=options.get("tool_choice", None),
|
||||
)
|
||||
mz_prompt_utils.Utils.print_log(f"LLAMA_CPP: \n{output}")
|
||||
choices = output.get("choices", [])
|
||||
@@ -330,7 +366,9 @@ def llama_cpp_simple_interrogator_to_json(model_file, use_system=True, system=No
|
||||
}
|
||||
|
||||
options["response_format"] = response_format
|
||||
options["chat_format"] = "chatml"
|
||||
|
||||
# if options.get("chat_format", None) is None:
|
||||
# options["chat_format"] = "llama-2"
|
||||
|
||||
result = llama_cpp_messages(model_file, None, messages, options=options)
|
||||
result = result.replace("\n", " ")
|
||||
@@ -385,6 +423,9 @@ def llava_cpp_messages(model_file, mmproj_file, messages, options={}):
|
||||
options = options.copy()
|
||||
options["logits_all"] = True
|
||||
options["n_ctx"] = max(4096, options.get("n_ctx", 4096))
|
||||
|
||||
# if options.get("chat_format", None) is None:
|
||||
# options["chat_format"] = "llama-2"
|
||||
return llama_cpp_messages(model_file, mmproj_file, messages, options)
|
||||
|
||||
|
||||
|
||||
+74
-31
@@ -172,41 +172,81 @@ class Utils:
|
||||
os.makedirs(models_path, exist_ok=True)
|
||||
return models_path
|
||||
|
||||
def translate_text(text, from_code, to_code):
|
||||
def get_translate_object(from_code, to_code):
|
||||
try:
|
||||
import argostranslate
|
||||
from argostranslate import translate
|
||||
except ImportError:
|
||||
subprocess.run([
|
||||
sys.executable, "-m",
|
||||
"pip", "install", "argostranslate"], check=True)
|
||||
import argostranslate
|
||||
from argostranslate import translate
|
||||
is_disabel_argostranslate = Utils.cache_get(
|
||||
"is_disabel_argostranslate")
|
||||
|
||||
try:
|
||||
translation = translate.get_translation_from_codes(
|
||||
from_code, to_code)
|
||||
if translation is None:
|
||||
raise Exception("Translation not found")
|
||||
if is_disabel_argostranslate is not None:
|
||||
return None
|
||||
|
||||
try:
|
||||
import argostranslate
|
||||
from argostranslate import translate, package
|
||||
except ImportError:
|
||||
subprocess.run([
|
||||
sys.executable, "-m",
|
||||
"pip", "install", "argostranslate"], check=True)
|
||||
|
||||
try:
|
||||
import argostranslate
|
||||
from argostranslate import translate, package
|
||||
except ImportError:
|
||||
Utils.cache_set("is_disabel_argostranslate", True)
|
||||
print(
|
||||
"argostranslate not found and install failed , will disable it")
|
||||
return None
|
||||
|
||||
packages = package.get_installed_packages()
|
||||
installed_packages = {}
|
||||
for p in packages:
|
||||
installed_packages[f"{p.from_code}_{p.to_code}"] = p
|
||||
|
||||
argosmodel_dir = os.path.join(
|
||||
Utils.get_models_path(), "argosmodel")
|
||||
if not os.path.exists(argosmodel_dir):
|
||||
os.makedirs(argosmodel_dir)
|
||||
|
||||
model_name = None
|
||||
if from_code == "zh" and to_code == "en":
|
||||
model_name = "zh_en"
|
||||
elif from_code == "en" and to_code == "zh":
|
||||
model_name = "en_zh"
|
||||
else:
|
||||
return None
|
||||
|
||||
if Utils.cache_get(f"argostranslate_{model_name}") is not None:
|
||||
return Utils.cache_get(f"argostranslate_{model_name}")
|
||||
|
||||
if installed_packages.get(model_name, None) is None:
|
||||
if not os.path.exists(os.path.join(argosmodel_dir, f"translate-{model_name}-1_9.argosmodel")):
|
||||
argosmodel_file = Utils.download_file(
|
||||
url=f"https://www.modelscope.cn/api/v1/models/wailovet/MinusZoneAIModels/repo?Revision=master&FilePath=argosmodel%2Ftranslate-{model_name}-1_9.argosmodel",
|
||||
filepath=os.path.join(
|
||||
argosmodel_dir, f"translate-{model_name}-1_9.argosmodel"),
|
||||
)
|
||||
else:
|
||||
argosmodel_file = os.path.join(
|
||||
argosmodel_dir, f"translate-{model_name}-1_9.argosmodel")
|
||||
package.install_from_path(argosmodel_file)
|
||||
|
||||
translate_object = translate.get_translation_from_codes(
|
||||
from_code=from_code, to_code=to_code)
|
||||
|
||||
Utils.cache_set(f"argostranslate_{model_name}", translate_object)
|
||||
|
||||
return translate_object
|
||||
except Exception as e:
|
||||
print(e)
|
||||
argostranslate.package.update_package_index()
|
||||
available_packages = argostranslate.package.get_available_packages()
|
||||
package_to_install = next(
|
||||
filter(
|
||||
lambda x: (x.from_code == from_code and x.to_code ==
|
||||
to_code), available_packages,
|
||||
)
|
||||
)
|
||||
download_path = package_to_install.download()
|
||||
print("package_to_install.download():", download_path)
|
||||
argostranslate.package.install_from_path(download_path)
|
||||
Utils.cache_set("is_disabel_argostranslate", True)
|
||||
print(
|
||||
"argostranslate not found and install failed , will disable it")
|
||||
print(f"get_translate_object error: {e}")
|
||||
return None
|
||||
|
||||
translation = translate.get_translation_from_codes(
|
||||
from_code, to_code)
|
||||
if translation is None:
|
||||
return text
|
||||
def translate_text(text, from_code, to_code):
|
||||
translation = Utils.get_translate_object(from_code, to_code)
|
||||
if translation is None:
|
||||
return text
|
||||
|
||||
# Translate
|
||||
translatedText = translation.translate(
|
||||
@@ -677,6 +717,9 @@ class Utils:
|
||||
def to_debug_prompt(p):
|
||||
if p is None:
|
||||
return ""
|
||||
zh = Utils.en2zh(p)
|
||||
if p == zh:
|
||||
return p
|
||||
zh = Utils.split_en_to_zh(p)
|
||||
p = p.strip()
|
||||
return f"""
|
||||
@@ -766,7 +809,7 @@ class Utils:
|
||||
cache_value = Utils.get_cache_by_local(cache_key)
|
||||
if cache_value is not None:
|
||||
return cache_value
|
||||
|
||||
|
||||
sha256 = Utils.file_hash(file_path, hashlib.sha256)
|
||||
Utils.set_cache_by_local(cache_key, sha256)
|
||||
return sha256
|
||||
|
||||
@@ -47,3 +47,23 @@ Describe this image in detail please.
|
||||
The language of reply is English only!!!
|
||||
Starts with "In the image,"
|
||||
"""
|
||||
|
||||
|
||||
M_ImageCaptioner2_System = """
|
||||
You are an assistant who perfectly describes images.
|
||||
"""
|
||||
|
||||
M_ImageCaptioner2_Prompt = """
|
||||
Describe this image in detail please.
|
||||
The language of reply is English only!!!
|
||||
Starts with "In the image,"
|
||||
"""
|
||||
|
||||
|
||||
ImageCaptionerPostProcessing_System = """
|
||||
I want you to write me a detailed list of tips for Content.
|
||||
Write a very short description of the scene and put it in the 'short_describes' field
|
||||
Write complete [moods, styles, lights, elements, objects] of the word array and put it in the '$_tags' field
|
||||
Don't include anything that isn't in Content.
|
||||
The language of reply is English only!!!
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user