模型概述: Granite-3.0-3B-A800M-Base 是一个仅解码器的语言模型,支持多种文本到文本生成任务。它采用两阶段训练策略从头开始训练。第一阶段,模型在源自不同领域的 8 万亿 tokens 上进行训练。第二阶段,使用精心挑选的高质量数据混合进一步训练 2 万亿 tokens,旨在提升其在特定任务上的性能。
支持语言: 英语、德语、西班牙语、法语、日语、葡萄牙语、阿拉伯语、捷克语、意大利语、韩语、荷兰语和中文。用户可以对 Granite 3.0 模型进行微调,以支持这 12 种语言之外的其他语言。
在 openmind 中的使用:
import importlib
import os
import time
import argparse
import torch
import numpy as np
import logging
from packaging import version
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="pipeline",
)
parser.add_argument(
"--debug",
action="store_true",
help="Debug mode",
)
parser.add_argument(
"--gguf_file",
"-g",
type=str,
help="Path to GGUF file",
default=None,
)
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, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(model_path, device_map=device_map, trust_remote_code=True)
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,
trust_remote_code=True,
)
if not args.debug:
# 判断openmind版本是否大于0.9.0
if version.parse(importlib.metadata.version("openmind")) >= version.parse("0.9.0"):
pipeline_pt = pipeline_pt.pipeline
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 = "npu" if is_torch_npu_available() else "cpu"
logging.info(f"NPU {'available' if device_map == 'npu' 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()预期用途:
大型语言模型(LLMs)在文本到文本生成中的主要应用场景包括文本摘要、文本分类、信息提取、问答等。所有Granite Base模型均能够处理这些任务,因为它们是在来自多个领域的大量数据上训练而成的。此外,它们还可以作为基准,用于创建针对特定应用场景的专用模型。
生成:
以下是使用Granite-3.0-3B-A800M-Base模型的简单示例。
安装以下库:
pip install torch torchvision torchaudio
pip install accelerate
pip install transformers然后,复制下面的代码片段来运行示例。
from transformers import AutoModelForCausalLM, AutoTokenizer
device = "auto"
model_path = "ibm-granite/granite-3.0-3b-a800m-base"
tokenizer = AutoTokenizer.from_pretrained(model_path)
# drop device_map if running on CPU
model = AutoModelForCausalLM.from_pretrained(model_path, device_map=device)
model.eval()
# change input text as desired
input_text = "Where is the Thomas J. Watson Research Center located?"
# tokenize the text
input_tokens = tokenizer(input_text, return_tensors="pt").to(device)
# generate output tokens
output = model.generate(**input_tokens,
max_length=4000)
# decode output tokens into text
output = tokenizer.batch_decode(output)
# print output
print(output)模型架构: Granite-3.0-3B-A800M-Base 基于仅解码器的稀疏混合专家(MoE)Transformer架构。该架构的核心组件包括:细粒度专家、无丢弃令牌路由和负载均衡损失。
| 模型 | 2B 密集型 | 8B 密集型 | 1B MoE | 3B MoE |
|---|---|---|---|---|
| 嵌入维度(Embedding size) | 2048 | 4096 | 1024 | 1536 |
| 层数(Number of layers) | 40 | 40 | 24 | 32 |
| 注意力头维度(Attention head size) | 64 | 128 | 64 | 64 |
| 注意力头数量(Number of attention heads) | 32 | 32 | 16 | 24 |
| KV头数量(Number of KV heads) | 8 | 8 | 8 | 8 |
| MLP隐藏层维度(MLP hidden size) | 8192 | 12800 | 512 | 512 |
| MLP激活函数(MLP activation) | SwiGLU | SwiGLU | SwiGLU | SwiGLU |
| 专家数量(Number of Experts) | — | — | 32 | 40 |
| MoE TopK | — | — | 8 | 8 |
| 初始化标准差(Initialization std) | 0.1 | 0.1 | 0.1 | 0.1 |
| 序列长度(Sequence Length) | 4096 | 4096 | 4096 | 4096 |
| 位置嵌入(Position Embedding) | RoPE | RoPE | RoPE | RoPE |
| 参数数量(# Parameters) | 2.5B | 8.1B | 1.3B | 3.3B |
| 激活参数数量(# Active Parameters) | 2.5B | 8.1B | 400M | 800M |
| 训练令牌数(# Training tokens) | 12T | 12T | 10T | 10T |
训练数据: 本模型采用两阶段训练策略,在开源数据和专有数据的混合数据集上进行训练。
数据集的详细说明可参见《Granite技术报告》(https://github.com/ibm-granite/granite-3.0-language-models/blob/main/paper.pdf) 和《作者致谢名单》(https://github.com/ibm-granite/granite-3.0-language-models/blob/main/author-ack.pdf)。
基础设施: 我们使用IBM的超级计算集群Blue Vela训练Granite 3.0语言模型,该集群配备了NVIDIA H100 GPU。该集群提供了可扩展且高效的基础设施,支持在数千个GPU上训练模型,同时通过使用100%可再生能源最大限度地减少环境影响。
伦理考量与局限性: 大型语言模型的使用涉及人们必须意识到的风险和伦理考量,包括但不限于:偏见与公平性、错误信息以及自主决策。Granite-3.0-3B-A800M-Base模型在这方面也不例外。尽管该模型适用于多种生成式AI任务,但它尚未经过任何安全对齐,因此可能会产生有问题的输出。此外,由于较小模型的尺寸和记忆能力有限,它们在生成场景中是否更容易通过逐字复制训练数据中的文本来产生幻觉,这一点仍不确定。这方面目前是一个活跃的研究领域,我们期待在该领域进行更严格的探索、理解和缓解。在伦理方面,所有大型语言模型都存在被恶意利用的潜在风险。我们敦促社区以符合伦理的意图并负责任地使用Granite-3.0-3B-A800M-Base模型。
资源