import sys import os parent_dir = os.path.abspath(os.path.join(__file__, "..", "..")) sys.path.append(parent_dir) import koboldcpp def extract_loras_from_prompt(*args, **kwargs): """ >>> prompt = "no it could look like it" >>> clean, data = extract_loras_from_prompt(prompt) >>> clean 'no it could look like it' >>> data [] >>> prompt = "even after a tag, an unending >> clean, data = extract_loras_from_prompt(prompt) >>> clean 'even after a tag, an unending >> data [{'name': 'valid', 'multiplier': 1.0}] >>> prompt = "A portrait with soft lighting" >>> clean, data = extract_loras_from_prompt(prompt) >>> clean 'A portrait with soft lighting' >>> data [{'name': 'models/face', 'multiplier': 0.8}] >>> prompt = " start end" >>> clean, data = extract_loras_from_prompt(prompt) >>> clean ' start end' >>> data [{'name': 'foo', 'multiplier': 1.0}, {'name': 'bar', 'multiplier': 0.5, 'is_high_noise': True}] >>> prompt = "bad good " >>> clean, data = extract_loras_from_prompt(prompt) >>> clean 'bad good ' >>> data [{'name': 'good', 'multiplier': 2.0}] >>> prompt = "xyz" >>> clean, data = extract_loras_from_prompt(prompt) >>> clean 'xyz' >>> data [{'name': 'a', 'multiplier': 0.15}, {'name': 'b', 'multiplier': 0.2}] """ return koboldcpp.extract_loras_from_prompt(*args, **kwargs) def mk_lora_info(imgloras, multipliers): """ >>> pre, path, name = mk_lora_info(['/x/lora1.safetensors', '/y/lora2.gguf'], []) fake filesystem access fake filesystem access >>> pre [{'fullpath': '/x/lora1.safetensors', 'name': 'lora1', 'path': 'lora1.safetensors', 'multiplier': 1.0, 'preloaded': True, 'fixed': True}, {'fullpath': '/y/lora2.gguf', 'name': 'lora2', 'path': 'lora2.gguf', 'multiplier': 1.0, 'preloaded': True, 'fixed': True}] >>> path {} >>> name {} >>> pre, path, name = mk_lora_info(['/x/lora1.safetensors', '/y/lora2.gguf'], [0.]) fake filesystem access fake filesystem access >>> pre [{'fullpath': '/x/lora1.safetensors', 'name': 'lora1', 'path': 'lora1.safetensors', 'multiplier': 0.0, 'preloaded': True}, {'fullpath': '/y/lora2.gguf', 'name': 'lora2', 'path': 'lora2.gguf', 'multiplier': 0.0, 'preloaded': True}] >>> path {'lora1.safetensors': {'fullpath': '/x/lora1.safetensors', 'name': 'lora1', 'path': 'lora1.safetensors', 'multiplier': 0.0, 'preloaded': True}, 'lora2.gguf': {'fullpath': '/y/lora2.gguf', 'name': 'lora2', 'path': 'lora2.gguf', 'multiplier': 0.0, 'preloaded': True}} >>> name {'lora1': 'lora1.safetensors', 'lora2': 'lora2.gguf'} >>> pre, path, name = mk_lora_info(['/x/lora1.safetensors', '/y/lora1.safetensors'], [0.3]) fake filesystem access fake filesystem access >>> pre [{'fullpath': '/x/lora1.safetensors', 'name': 'lora1', 'path': 'lora1.safetensors', 'multiplier': 0.3, 'preloaded': True, 'fixed': True}, {'fullpath': '/y/lora1.safetensors', 'name': 'lora1_2', 'path': 'lora1_2.safetensors', 'multiplier': 0.3, 'preloaded': True, 'fixed': True}] >>> path {} >>> pre, path, name = mk_lora_info(['/lora/dir/'], [0.3]) fake filesystem access Scanning /lora/dir/ for LoRAs... fake directory scan found 2 files under /lora/dir/ >>> pre [] >>> expected = { ... 'lora1_makebelieve.gguf': { ... 'fullpath': '/lora/dir/lora1_makebelieve.gguf', ... 'name': 'lora1_makebelieve', ... 'path': 'lora1_makebelieve.gguf', ... 'multiplier': 0.0}, ... 'lora2/makebelieve.gguf': { ... 'fullpath': '/lora/dir/lora2/makebelieve.gguf', ... 'name': 'lora2/makebelieve', ... 'path': 'lora2/makebelieve.gguf', ... 'multiplier': 0.0}} >>> path == expected True >>> name {'lora1_makebelieve': 'lora1_makebelieve.gguf', 'lora2/makebelieve': 'lora2/makebelieve.gguf'} """ return koboldcpp.mk_lora_info(imgloras, multipliers, True) def sanitize_lora_multipliers(*args, **kwargs): """ >>> sanitize_lora_multipliers(None) [1.0] >>> sanitize_lora_multipliers(0.75) [0.75] >>> sanitize_lora_multipliers("2") [2.0] >>> sanitize_lora_multipliers([0.5, "1.2", 3]) [0.5, 1.2, 3.0] >>> sanitize_lora_multipliers([]) [] >>> sanitize_lora_multipliers(["bad", None, ""]) [0.0, 0.0, 0.0] """ return koboldcpp.sanitize_lora_multipliers(*args, **kwargs) def prepare_lora_multipliers(req_list, imglora_bypath): """ >>> req = [ ... {"path": "a.gguf", "multiplier": "0.5"}, ... {"path": "a.gguf", "multiplier": 1.0}, ... ] >>> imglora = {"a.gguf": {"fullpath": "/abs/a.gguf"}} >>> paths, mults = prepare_lora_multipliers(req, imglora) >>> paths == [b"/abs/a.gguf"], mults == [1.5] (True, True) >>> req = [ ... {"path": "b.gguf", "multiplier": "2"}, ... {"path": "c.gguf"}, ... "not a dict", ... {"path": "", "multiplier": "3"}, ... {"path": "b.gguf", "multiplier": 0}, ... ] >>> imglora = {"b.gguf": {"fullpath": "/abs/b.gguf"}, ... "c.gguf": {"fullpath": "/abs/c.gguf"}} >>> paths, mults = prepare_lora_multipliers(req, imglora) >>> paths == [b"/abs/b.gguf"], mults == [2.0] (True, True) >>> req = [{"path": "missing.gguf", "multiplier": "5"}] >>> imglora = {} >>> paths, mults = prepare_lora_multipliers(req, imglora) >>> paths == [], mults == [] (True, True) >>> req = [ ... {"path": "x.gguf", "multiplier": 1}, ... {"path": "y.gguf", "multiplier": 2}, ... ] >>> imglora = { ... "x.gguf": {"fullpath": "/abs/x.gguf", "path": "x.gguf", "multiplier": 0.0}, ... "y.gguf": {"fullpath": "/abs/y.gguf", "path": "y.gguf", "multiplier": 0.0}, ... } >>> paths, mults = prepare_lora_multipliers(req, imglora) >>> paths == [b'/abs/x.gguf', b'/abs/y.gguf'] True >>> mults == [1.0, 2.0] True """ return koboldcpp.prepare_lora_multipliers_backend(req_list, imglora_bypath) def mk_sdapi_lora_list(imglora_bypath): ''' >>> imglora_bypath = { ... 'lora_a.safetensors': {'name': 'lora_a', 'path': 'lora_a.safetensors', 'multiplier': 0.0}, ... 'lora_b.gguf' : {'name': 'lora_b', 'path': 'lora_b.gguf', 'multiplier': 0.0}, ... 'lora_c.safetensors': {'name': 'lora_c', 'path': 'lora_c.safetensors', 'multiplier': 1.0}, ... 'lora_d.safetensors': {'name': 'lora_d', 'path': 'lora_d.safetensors', 'multiplier': 1.0, 'fixed': True}, ... 'chars/waifu.gguf' : {'name': 'chars/waifu', 'path': 'chars/waifu.gguf', 'multiplier': 0.0} ... } >>> expected = [ ... {'name': 'lora_a', 'path': 'lora_a.safetensors'}, ... {'name': 'lora_b', 'path': 'lora_b.gguf'}, ... {'name': 'lora_c', 'path': 'lora_c.safetensors'}, ... {'name': 'chars/waifu', 'path': 'chars/waifu.gguf'} ... ] >>> mk_sdapi_lora_list(imglora_bypath) == expected True >>> empty_data = {} >>> mk_sdapi_lora_list(empty_data) [] ''' return koboldcpp.mk_sdapi_lora_list(imglora_bypath) def gendefaults_parse_meta_field(*args, **kwargs): ''' >>> [gendefaults_parse_meta_field(x) for x in [{}, None, '', "invalid json", ' ', 4]] Warning: gendefaults field - not a JSON object. Warning: couldn't parse gendefaults field. Warning: gendefaults field - not a JSON object. [{}, {}, {}, {}, {}, {}] >>> [gendefaults_parse_meta_field(x) for x in ['["valid", "json"]', 'but', '1']] Warning: gendefaults field - not a JSON object. Warning: couldn't parse gendefaults field. Warning: gendefaults field - not a JSON object. [{}, {}, {}] >>> gendefaults_parse_meta_field({"key": "value"}) {'key': 'value'} >>> gendefaults_parse_meta_field(' "scheduler": "default", "steps": 10 ') {'scheduler': 'default', 'steps': 10} >>> gendefaults_parse_meta_field('{"cfg-scale": 0.5, "cfg_scale": 0.7}') {'cfg-scale': 0.5, 'cfg_scale': 0.7} >>> gendefaults_parse_meta_field('{"guidance": 1.2, "sampler": "ddim"}') {'distilled_guidance': 1.2, 'sampler_name': 'ddim', 'guidance': 1.2, 'sampler': 'ddim'} ''' return koboldcpp.gendefaults_parse_meta_field(*args, **kwargs) if __name__ == '__main__': import doctest failures, _ = doctest.testmod() if failures: raise SystemExit(f"{failures} doctest{'s' if failures != 1 else ''} failed")