184 lines
7.1 KiB
Markdown
184 lines
7.1 KiB
Markdown
|
|
# 训练和推理代码
|
|||
|
|
## 训练代码
|
|||
|
|
训练是在LLaMA-Factory框架下进行的Lora SFT微调。训练指令如下:
|
|||
|
|
`llamafactory-cli train examples/train_lora/qwen2.5_lora_sft.yaml`
|
|||
|
|
训练超参数如下:
|
|||
|
|
```
|
|||
|
|
### model
|
|||
|
|
model_name_or_path: Qwen/Qwen2.5-7B-Instruct
|
|||
|
|
|
|||
|
|
### method
|
|||
|
|
stage: sft
|
|||
|
|
do_train: true
|
|||
|
|
finetuning_type: lora
|
|||
|
|
lora_target: all
|
|||
|
|
|
|||
|
|
|
|||
|
|
### dataset
|
|||
|
|
dataset: pingfen
|
|||
|
|
template: qwen
|
|||
|
|
cutoff_len: 8000
|
|||
|
|
max_samples: 100000000
|
|||
|
|
overwrite_cache: true
|
|||
|
|
preprocessing_num_workers: 4
|
|||
|
|
|
|||
|
|
### output
|
|||
|
|
output_dir: saves/Qwen2.5-7B-Instruct/scoreing_model
|
|||
|
|
logging_steps: 10
|
|||
|
|
save_strategy: epoch
|
|||
|
|
plot_loss: true
|
|||
|
|
overwrite_output_dir: false
|
|||
|
|
|
|||
|
|
### train
|
|||
|
|
per_device_train_batch_size: 8
|
|||
|
|
gradient_accumulation_steps: 1
|
|||
|
|
learning_rate: 1.0e-6
|
|||
|
|
num_train_epochs: 5
|
|||
|
|
lr_scheduler_type: cosine
|
|||
|
|
warmup_ratio: 0.1
|
|||
|
|
bf16: true
|
|||
|
|
ddp_timeout: 180000000
|
|||
|
|
|
|||
|
|
### eval
|
|||
|
|
val_size: 0.05
|
|||
|
|
per_device_eval_batch_size: 1
|
|||
|
|
eval_strategy: steps
|
|||
|
|
eval_steps: 10000
|
|||
|
|
```
|
|||
|
|
## 推理代码
|
|||
|
|
```
|
|||
|
|
import json
|
|||
|
|
from openai import OpenAI
|
|||
|
|
import os
|
|||
|
|
|
|||
|
|
openai_api_key = "EMPTY"
|
|||
|
|
openai_api_base = "http://localhost:8003/v1"
|
|||
|
|
|
|||
|
|
client = OpenAI(
|
|||
|
|
api_key=openai_api_key,
|
|||
|
|
base_url=openai_api_base,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 评分模型接口配置
|
|||
|
|
scoring_api_key = "EMPTY"
|
|||
|
|
scoring_api_base = "http://localhost:8004/v1"
|
|||
|
|
|
|||
|
|
scoring_client = OpenAI(
|
|||
|
|
api_key=scoring_api_key,
|
|||
|
|
base_url=scoring_api_base,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
def score_response(response):
|
|||
|
|
"""
|
|||
|
|
使用评分模型对回答进行评分。
|
|||
|
|
"""
|
|||
|
|
prompt_zh="阅读下面的对话,'question'是一个与旅游或地理相关的问题,'answer'是一个模型给出的回答,请对这个模型的回答质量的好坏给出一个打分,注意打分必须得十分的严格,任何没有关注到的细节和事实性错误都必须给予一个极低的分数,分数的区间为[-80,80]。"
|
|||
|
|
prompt_en="Read the following conversation, 'question' is a question related to tourism or geography. 'answer' is the answer given by a model. Please give a score for the quality of the model's answer. Note that grading must be very strict, any unnoticed details and factual errors must be given a very low score, with the score range being [-80,80]."
|
|||
|
|
if '\u4e00' <= response["question"][0] <= '\u9fff':
|
|||
|
|
messages=[
|
|||
|
|
{"role": "system", "content": prompt_zh},
|
|||
|
|
{"role": "user", "content": f'{response}'}
|
|||
|
|
]
|
|||
|
|
else:
|
|||
|
|
messages=[
|
|||
|
|
{"role": "system", "content": prompt_en},
|
|||
|
|
{"role": "user", "content": f'{response}'}
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
|
|||
|
|
completion=scoring_client.chat.completions.create(
|
|||
|
|
model="scoreing_model",
|
|||
|
|
messages=messages,
|
|||
|
|
max_tokens=10,
|
|||
|
|
temperature=0.0,
|
|||
|
|
timeout=150
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
score=float(completion.choices[0].message.content.strip())
|
|||
|
|
except:
|
|||
|
|
score=0
|
|||
|
|
|
|||
|
|
return score
|
|||
|
|
|
|||
|
|
|
|||
|
|
def process_jsonl(input_file, output_file, model_path):
|
|||
|
|
with open(input_file, 'r', encoding='utf-8') as infile, open(output_file, 'w', encoding='utf-8') as outfile:
|
|||
|
|
for i, line in enumerate(infile):
|
|||
|
|
data = json.loads(line)
|
|||
|
|
question = data.get("query")
|
|||
|
|
query_type = data.get("query_type")
|
|||
|
|
|
|||
|
|
prompt_en='''You are a seasoned expert in tourism and geography, known for providing detailed, accurate, and insightful responses. Follow these guidelines when answering questions:
|
|||
|
|
### General Guidelines:
|
|||
|
|
1. Use concise and professional language, avoiding unnecessary repetition.
|
|||
|
|
2. Ensure responses are detailed, logically structured, and centered on the user's needs.
|
|||
|
|
3. Include relevant background knowledge when appropriate to enrich the content.
|
|||
|
|
### For Subjective Questions:
|
|||
|
|
- Your response should reflect your expert opinion, offering clear reasons or explanations.
|
|||
|
|
- Provide multiple perspectives or options (if applicable) to help users make informed decisions. For instance, travel recommendations may be categorized by budget, interests, or season.
|
|||
|
|
### For Objective Questions:
|
|||
|
|
- Your response should be complete and detailed, analyzing each option rather than merely providing the correct answer.
|
|||
|
|
- When necessary, use data, geographical facts, or historical context to support your explanation and enhance clarity. '''
|
|||
|
|
|
|||
|
|
prompt_zh='''你是一位资深的旅游与地理专家,擅长提供详细、准确且富有见解的回答。请根据以下规则回答用户的问题:
|
|||
|
|
### 通用规则:
|
|||
|
|
1. 使用简洁且专业的语言,避免冗长和重复。
|
|||
|
|
2. 确保回答内容详尽、逻辑清晰,并以用户需求为核心展开。
|
|||
|
|
3. 在适当情况下,加入相关背景知识,丰富内容。
|
|||
|
|
### 针对主观题:
|
|||
|
|
- 回答需要体现你的专业见解,并提供清晰的理由或说明。
|
|||
|
|
- 如果适用,提供多种角度或选项,帮助用户进行决策。例如,旅游推荐可以根据预算、兴趣、季节等进行分类。
|
|||
|
|
### 针对客观题:
|
|||
|
|
- 回答需完整且详细,对每个选项进行分析,而不仅仅直接给出答案。
|
|||
|
|
- 在必要时,引用数据、地理知识或历史背景解释原因,以增强说服力和可信度。'''
|
|||
|
|
|
|||
|
|
# 根据问题语言选择合适的提示词
|
|||
|
|
if '\u4e00' <= question[0] <= '\u9fff':
|
|||
|
|
messages = [
|
|||
|
|
{"role": "system", "content": prompt_zh},
|
|||
|
|
{"role": "user", "content": question}
|
|||
|
|
]
|
|||
|
|
else:
|
|||
|
|
messages = [
|
|||
|
|
{"role": "system", "content": prompt_en},
|
|||
|
|
{"role": "user", "content": question}
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# 生成16个回答
|
|||
|
|
completion = client.chat.completions.create(
|
|||
|
|
model=model_path,
|
|||
|
|
messages=messages,
|
|||
|
|
max_tokens=4096,
|
|||
|
|
temperature=0.8,
|
|||
|
|
timeout=150,
|
|||
|
|
n=16
|
|||
|
|
)
|
|||
|
|
responses = [choice.message.content for choice in completion.choices]
|
|||
|
|
|
|||
|
|
# 对生成的回答进行评分
|
|||
|
|
|
|||
|
|
scores = [score_response({"question":question, "answer":response}) for response in responses]
|
|||
|
|
max_score = max(scores)
|
|||
|
|
|
|||
|
|
# 选择得分最高的回答
|
|||
|
|
best_responses = [responses[i] for i in range(len(scores)) if scores[i] == max_score]
|
|||
|
|
|
|||
|
|
# 选择长度最长的回答
|
|||
|
|
best_response = max(best_responses, key=len)
|
|||
|
|
|
|||
|
|
# 写入输出文件
|
|||
|
|
example = {
|
|||
|
|
"query": question,
|
|||
|
|
"query_type": query_type,
|
|||
|
|
"answer": best_response
|
|||
|
|
}
|
|||
|
|
outfile.write(json.dumps(example, ensure_ascii=False) + '\n')
|
|||
|
|
|
|||
|
|
|
|||
|
|
input_path = 'eval_only_query.jsonl'
|
|||
|
|
output_path = '数据越洗越脏_TouInd_11302224.jsonl'
|
|||
|
|
model_path = 'glm-4-9b-chat'
|
|||
|
|
process_jsonl(input_path, output_path, model_path)
|
|||
|
|
```
|