原始模型:https://huggingface.co/SicariusSicariiStuff/Phi-3.5-mini-instruct_Uncensored
所有量化版本均使用 imatrix 选项,并基于 此处 的数据集制作。
可在 LM Studio 中运行它们。
<s><|system|> {system_prompt}<|end|><|user|> {prompt}<|end|><|assistant|><|end|>import os
import time
import argparse
import torch
import numpy as np
import logging
def set_logging(model_name):
log_filename = os.path.join(os.getcwd(), f"{model_name}_inference_{time.strftime('%Y%m%d_%H%M%S')}.log")
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
handlers=[
logging.FileHandler(log_filename),
logging.StreamHandler(),
],
)
def parse_args():
parser = argparse.ArgumentParser(description="NPU Inference for Text Generation Model")
parser.add_argument(
"--model_name_or_path",
"-m",
type=str,
help="Path to model",
default=".",
)
parser.add_argument(
"--inference_mode",
"-i",
type=str,
help="Inference mode",
default="gguf",
)
parser.add_argument(
"--debug",
action="store_true",
help="Debug mode",
)
parser.add_argument(
"--gguf_file",
"-g",
type=str,
help="Path to GGUF file",
default="Phi-3.5-mini-instruct_Uncensored-Q4_K_L.gguf",
)
return parser.parse_args()
args = parse_args()
model_path = args.model_name_or_path
abs_model_path = os.path.abspath(model_path)
model_name = os.path.basename(abs_model_path)
set_logging(model_name)
if args.debug:
logging.info("Debug mode enabled, using transformers package from source.")
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline, is_torch_npu_available
else:
logging.info("Debug mode disabled, using openmind package.")
from openmind import AutoTokenizer, AutoModelForCausalLM, pipeline, is_torch_npu_available
def load_model_from_gguf(model_path: str, device_map="auto"):
gguf_filename = args.gguf_file
tokenizer = AutoTokenizer.from_pretrained(model_path, gguf_file=gguf_filename)
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(model_path, gguf_file=gguf_filename, device_map=device_map)
return tokenizer, model
def load_model_from_local(model_path: str, device_map="auto"):
tokenizer = AutoTokenizer.from_pretrained(model_path)
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(model_path, device_map=device_map)
return tokenizer, model
def load_model_from_pipeline(model_path: str, device_map="auto", task="text-generation"):
pipeline_pt = pipeline(
task=task,
model=model_path,
device_map=device_map,
framework="pt",
truncation=True,
)
return pipeline_pt.tokenizer, pipeline_pt
def load_model(mode: str, *args, **kwargs):
if mode == "gguf":
return load_model_from_gguf(*args, **kwargs)
elif mode == "model":
return load_model_from_local(*args, **kwargs)
elif mode == "pipeline":
return load_model_from_pipeline(*args, **kwargs)
else:
raise ValueError(f"load_model Unknown mode: {mode}")
def generate_text_form_model(tokenizer, model, prompt, max_new_tokens=50):
inputs = tokenizer(prompt, return_tensors="pt", padding=True).to(model.device)
output = model.generate(
input_ids=inputs['input_ids'],
attention_mask=inputs['attention_mask'],
max_new_tokens=max_new_tokens,
)
return tokenizer.decode(output[0], skip_special_tokens=True)
def generate_text_from_pipeline(tokenizer, pipeline, prompt, max_new_tokens=50):
results = pipeline(
prompt,
max_new_tokens=max_new_tokens,
)
return results[0]["generated_text"]
def generate_text(mode: str, *args, **kwargs):
if mode == "model" or mode == "gguf":
return generate_text_form_model(*args, **kwargs)
elif mode == "pipeline":
return generate_text_from_pipeline(*args, **kwargs)
else:
raise ValueError(f"generate_text Unknown mode: {mode}")
def apply_chat_template(tokenizer, tokenize=False):
if tokenizer.chat_template is None:
print("Chat template is not defined, use default template.")
tokenizer.chat_template = "{% if not add_generation_prompt is defined %}{% set add_generation_prompt = false %}{% endif %}{% for message in messages %}{{'<|im_start|>' + message['role'] + '\n' + message['content'] + '<|im_end|>' + '\n'}}{% endfor %}{% if add_generation_prompt %}{{ '<|im_start|>assistant\n' }}{% endif %}"
chat = [
{
"role": "system",
"content": "You are a helpful assistant who always responds in a friendly manner",
},
{
"role": "user",
"content": "Why does the ocean appear blue?",
},
]
chat_input = tokenizer.apply_chat_template(chat, tokenize=tokenize)
return chat_input
def main():
model_path = args.model_name_or_path
abs_model_path = os.path.abspath(model_path)
model_name = os.path.basename(abs_model_path)
logging.info(f"测试模型: {model_name}")
logging.info(f"模型路径: {model_path}")
logging.info(f"绝对路径: {abs_model_path}")
inference_mode = args.inference_mode
logging.info(f"推理模式: {inference_mode}")
# 确保使用 NPU 设备
device_map = "auto" if is_torch_npu_available() else "cpu"
logging.info(f"NPU {'available' if device_map == 'auto' else 'not available'}, use device_map='{device_map}'.")
# 加载模型
tokenizer, task_pipeline = load_model(mode=inference_mode, model_path=model_path, device_map=device_map)
prompt = apply_chat_template(tokenizer, tokenize=False)
# 推理性能测试
inference_times = []
num_runs = 10
logging.info(f"\n=== NPU {model_name} 性能测试 ===")
for i in range(num_runs):
input_text = prompt
start_time = time.time()
results = generate_text(inference_mode, tokenizer, task_pipeline, input_text)
torch.npu.synchronize()
inference_time = time.time() - start_time
inference_times.append(inference_time)
if i == 0:
logging.info(f"输入文本: {input_text}")
logging.info("生成结果:")
logging.info(f" {results}")
avg_time = np.mean(inference_times)
std_time = np.std(inference_times)
logging.info("\n性能分析:")
logging.info(f"NPU平均推理时间: {avg_time:.4f} 秒")
logging.info(f"NPU推理时间标准差: {std_time:.4f} 秒")
logging.info(f"推理时间列表: {inference_times}")
if __name__ == "__main__":
main()部分量化版本(如 Q3_K_XL、Q4_K_L 等)采用标准量化方法,但将嵌入和输出权重量化为 Q8_0,而非其通常默认的量化方式。
有人认为这种方式能提升模型质量,也有人未察觉任何差异。如果您使用这些模型,请务必留言分享您的使用体验。我希望能收到反馈,了解这些模型是否确实被使用且有用,这样我就不会继续上传无人问津的量化版本了。
感谢!
感谢 kalomaze 和 Dampf 在创建 imatrix 校准数据集方面提供的帮助。
感谢 ZeroWw 启发我对嵌入/输出权重进行实验。
首先,请确保已安装 hugginface-cli:
pip install -U "huggingface_hub[cli]"然后,您可以定位到您想要的特定文件:
huggingface-cli download bartowski/Phi-3.5-mini-instruct_Uncensored-GGUF --include "Phi-3.5-mini-instruct_Uncensored-Q4_K_M.gguf" --local-dir ./如果模型大于50GB,它会被分割成多个文件。要将所有文件下载到本地文件夹,请运行:
huggingface-cli download bartowski/Phi-3.5-mini-instruct_Uncensored-GGUF --include "Phi-3.5-mini-instruct_Uncensored-Q8_0/*" --local-dir ./你可以指定一个新的本地目录(Phi-3.5-mini-instruct_Uncensored-Q8_0),也可以将它们全部下载到当前位置(./)。
Artefact2 在此处提供了一篇很棒的文章,其中包含图表展示了各种性能。
首先要确定的是你能运行多大的模型。要做到这一点,你需要弄清楚你有多少 RAM 和/或 VRAM。
如果你希望模型运行得尽可能快,你需要将整个模型放入 GPU 的 VRAM 中。目标是选择文件大小比你的 GPU 总 VRAM 小 1-2GB 的量化版本。
如果你想要绝对的最高质量,可以将系统 RAM 和 GPU 的 VRAM 加起来,然后同样选择文件大小比这个总和小 1-2GB 的量化版本。
接下来,你需要决定是使用“I-quant”还是“K-quant”。
如果你不想考虑太多,选择 K-quants 中的一个即可。这些文件格式为“QX_K_X”,例如 Q5_K_M。
如果你想深入了解,可以查看这个非常有用的特性图表:
但基本上,如果你目标是 Q4 以下,并且运行 cuBLAS(Nvidia)或 rocBLAS(AMD),你应该考虑 I-quants。这些文件格式为 IQX_X,例如 IQ3_M。它们是较新的版本,在相同大小下提供更好的性能。
这些 I-quants 也可以在 CPU 和 Apple Metal 上使用,但会比对应的 K-quant 慢,因此你需要在速度和性能之间做出权衡。
I-quants 不 与 Vulkan(同样适用于 AMD)兼容,因此如果你有 AMD 显卡,请仔细检查你使用的是 rocBLAS 构建版本还是 Vulkan 构建版本。在撰写本文时,LM Studio 有一个支持 ROCm 的预览版,其他推理引擎也有针对 ROCm 的特定构建版本。
想要支持我的工作?请访问我的 ko-fi 页面:https://ko-fi.com/bartowski