初始化项目,由ModelHub XC社区提供模型
Model: ystemsrx/Qwen2-Boundless Source: Original Platform
This commit is contained in:
224
README.zh.md
Normal file
224
README.zh.md
Normal file
@@ -0,0 +1,224 @@
|
||||
[English](README.md)
|
||||
|
||||
# Qwen2-Boundless
|
||||
|
||||
## 简介
|
||||
|
||||
Qwen2-Boundless 是一个基于 Qwen2-1.5B-Instruct 微调的模型,专为回答各种类型的问题而设计,无论是道德的、违法的、色情的、暴力的内容,均可自由询问。该模型经过特殊的数据集训练,能够应对复杂和多样的场景。需要注意的是,微调数据集全部为中文,因此模型在处理中文时表现更佳。
|
||||
|
||||
> **警告**:本模型仅用于研究和测试目的,用户应遵循当地法律法规,并对自己的行为负责。
|
||||
|
||||
## 模型使用
|
||||
|
||||
你可以通过以下代码加载并使用该模型:
|
||||
|
||||
```python
|
||||
from transformers import AutoModelForCausalLM, AutoTokenizer
|
||||
import os
|
||||
|
||||
device = "cuda" # the device to load the model onto
|
||||
current_directory = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
model = AutoModelForCausalLM.from_pretrained(
|
||||
current_directory,
|
||||
torch_dtype="auto",
|
||||
device_map="auto"
|
||||
)
|
||||
tokenizer = AutoTokenizer.from_pretrained(current_directory)
|
||||
|
||||
prompt = "Hello?"
|
||||
messages = [
|
||||
{"role": "system", "content": ""},
|
||||
{"role": "user", "content": prompt}
|
||||
]
|
||||
text = tokenizer.apply_chat_template(
|
||||
messages,
|
||||
tokenize=False,
|
||||
add_generation_prompt=True
|
||||
)
|
||||
model_inputs = tokenizer([text], return_tensors="pt").to(device)
|
||||
|
||||
generated_ids = model.generate(
|
||||
model_inputs.input_ids,
|
||||
max_new_tokens=512
|
||||
)
|
||||
generated_ids = [
|
||||
output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
|
||||
]
|
||||
|
||||
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
|
||||
print(response)
|
||||
```
|
||||
|
||||
### 连续对话
|
||||
|
||||
要实现连续对话,可以使用以下代码:
|
||||
|
||||
```python
|
||||
from transformers import AutoModelForCausalLM, AutoTokenizer
|
||||
import torch
|
||||
import os
|
||||
|
||||
device = "cuda" # the device to load the model onto
|
||||
|
||||
# 获取当前脚本所在的目录
|
||||
current_directory = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
model = AutoModelForCausalLM.from_pretrained(
|
||||
current_directory,
|
||||
torch_dtype="auto",
|
||||
device_map="auto"
|
||||
)
|
||||
tokenizer = AutoTokenizer.from_pretrained(current_directory)
|
||||
|
||||
messages = [
|
||||
{"role": "system", "content": ""}
|
||||
]
|
||||
|
||||
while True:
|
||||
# 获取用户输入
|
||||
user_input = input("User: ")
|
||||
|
||||
# 将用户输入添加到对话中
|
||||
messages.append({"role": "user", "content": user_input})
|
||||
|
||||
# 准备输入文本
|
||||
text = tokenizer.apply_chat_template(
|
||||
messages,
|
||||
tokenize=False,
|
||||
add_generation_prompt=True
|
||||
)
|
||||
model_inputs = tokenizer([text], return_tensors="pt").to(device)
|
||||
|
||||
# 生成响应
|
||||
generated_ids = model.generate(
|
||||
model_inputs.input_ids,
|
||||
max_new_tokens=512
|
||||
)
|
||||
generated_ids = [
|
||||
output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
|
||||
]
|
||||
|
||||
# 解码并打印响应
|
||||
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
|
||||
print(f"Assistant: {response}")
|
||||
|
||||
# 将生成的响应添加到对话中
|
||||
messages.append({"role": "assistant", "content": response})
|
||||
```
|
||||
|
||||
### 流式响应
|
||||
|
||||
对于需要流式响应的应用,使用以下代码:
|
||||
|
||||
```python
|
||||
import torch
|
||||
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
|
||||
from transformers.trainer_utils import set_seed
|
||||
from threading import Thread
|
||||
import random
|
||||
import os
|
||||
|
||||
DEFAULT_CKPT_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
def _load_model_tokenizer(checkpoint_path, cpu_only):
|
||||
tokenizer = AutoTokenizer.from_pretrained(checkpoint_path, resume_download=True)
|
||||
|
||||
device_map = "cpu" if cpu_only else "auto"
|
||||
|
||||
model = AutoModelForCausalLM.from_pretrained(
|
||||
checkpoint_path,
|
||||
torch_dtype="auto",
|
||||
device_map=device_map,
|
||||
resume_download=True,
|
||||
).eval()
|
||||
model.generation_config.max_new_tokens = 512 # For chat.
|
||||
|
||||
return model, tokenizer
|
||||
|
||||
def _get_input() -> str:
|
||||
while True:
|
||||
try:
|
||||
message = input('User: ').strip()
|
||||
except UnicodeDecodeError:
|
||||
print('[ERROR] Encoding error in input')
|
||||
continue
|
||||
except KeyboardInterrupt:
|
||||
exit(1)
|
||||
if message:
|
||||
return message
|
||||
print('[ERROR] Query is empty')
|
||||
|
||||
def _chat_stream(model, tokenizer, query, history):
|
||||
conversation = [
|
||||
{'role': 'system', 'content': ''},
|
||||
]
|
||||
for query_h, response_h in history:
|
||||
conversation.append({'role': 'user', 'content': query_h})
|
||||
conversation.append({'role': 'assistant', 'content': response_h})
|
||||
conversation.append({'role': 'user', 'content': query})
|
||||
inputs = tokenizer.apply_chat_template(
|
||||
conversation,
|
||||
add_generation_prompt=True,
|
||||
return_tensors='pt',
|
||||
)
|
||||
inputs = inputs.to(model.device)
|
||||
streamer = TextIteratorStreamer(tokenizer=tokenizer, skip_prompt=True, timeout=60.0, skip_special_tokens=True)
|
||||
generation_kwargs = dict(
|
||||
input_ids=inputs,
|
||||
streamer=streamer,
|
||||
)
|
||||
thread = Thread(target=model.generate, kwargs=generation_kwargs)
|
||||
thread.start()
|
||||
|
||||
for new_text in streamer:
|
||||
yield new_text
|
||||
|
||||
def main():
|
||||
checkpoint_path = DEFAULT_CKPT_PATH
|
||||
seed = random.randint(0, 2**32 - 1) # 随机生成一个种子
|
||||
set_seed(seed) # 设置随机种子
|
||||
cpu_only = False
|
||||
|
||||
history = []
|
||||
|
||||
model, tokenizer = _load_model_tokenizer(checkpoint_path, cpu_only)
|
||||
|
||||
while True:
|
||||
query = _get_input()
|
||||
|
||||
print(f"\nUser: {query}")
|
||||
print(f"\nAssistant: ", end="")
|
||||
try:
|
||||
partial_text = ''
|
||||
for new_text in _chat_stream(model, tokenizer, query, history):
|
||||
print(new_text, end='', flush=True)
|
||||
partial_text += new_text
|
||||
print()
|
||||
history.append((query, partial_text))
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print('Generation interrupted')
|
||||
continue
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
## 数据集
|
||||
|
||||
Qwen2-Boundless 模型使用了特殊的 `bad_data.json` 数据集进行微调,该数据集包含了广泛的文本内容,涵盖道德、法律、色情及暴力等主题。由于微调数据集全部为中文,因此模型在处理中文时表现更佳。如果你有兴趣了解或使用该数据集,可以通过以下链接获取:
|
||||
|
||||
- [bad_data.json 数据集](https://huggingface.co/datasets/ystemsrx/bad_data.json)
|
||||
|
||||
同时我们也从 [这个文件](https://github.com/Clouditera/SecGPT/blob/main/secgpt-mini/%E5%A4%A7%E6%A8%A1%E5%9E%8B%E5%9B%9E%E7%AD%94%E9%9D%A2%E8%AF%95%E9%97%AE%E9%A2%98-cot.txt) 中整理、清洗出一部分与网络安全相关的数据进行训练。
|
||||
|
||||
## GitHub 仓库
|
||||
|
||||
更多关于该模型的细节以及持续更新,请访问我们的 GitHub 仓库:
|
||||
|
||||
- [GitHub: ystemsrx/Qwen2-Boundless](https://github.com/ystemsrx/Qwen2-Boundless)
|
||||
|
||||
## 声明
|
||||
|
||||
本模型提供的所有内容仅用于研究和测试目的,模型开发者不对任何可能的滥用行为负责。使用者应遵循相关法律法规,并承担因使用本模型而产生的所有责任。
|
||||
Reference in New Issue
Block a user