Views
No views yet
1import os
2from transformers import AutoTokenizer, AutoModelForCausalLM
3import torch
4
5# 设置环境变量,解决OpenMP错误
6# 这个环境变量设置允许程序在检测到多个OpenMP库时继续运行,避免出现冲突错误
7os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
8
9
10# 设置模型和数据路径
11MODEL_PATH = "Fintech-Dreamer/FinSynth_model_chatbot"
12
13
14def generate_response(model, tokenizer, instruction, input_text, max_length=512):
15 """
16 使用模型生成客服回答
17
18 参数:
19 model: 加载的语言模型实例
20 tokenizer: 模型对应的分词器
21 instruction: 指令部分文本,一般是客户的问题
22 input_text: 输入文本,作为参考上下文或背景信息
23 max_length: 生成文本的最大长度,默认为512个token
24
25 返回:
26 prompt: 完整的输入提示词
27 response: 模型生成的回答内容(仅包含模型生成部分,不包含输入提示词)
28 """
29 # 构造提示词格式 - 使用特殊标记组织对话形式
30 # <|begin of sentence|>标记句子开始,和/分别标记用户和助手角色
31 # 这种特殊标记格式是某些模型预训练时使用的对话格式,需要严格遵循
32 prompt = f"<|begin of sentence|> {instruction}\n{input_text} <|Assistant|>"
33
34 # 编码输入,将文本转换为模型可以理解的token序列
35 # add_special_tokens=True确保添加特殊标记如开始和结束标记
36 # truncation=True确保输入不超过模型的最大处理长度
37 # padding=True确保所有输入长度一致
38 inputs = tokenizer(prompt, return_tensors="pt", truncation=True, padding=True, add_special_tokens=True)
39
40 # 将输入移动到模型所在的设备(CPU/GPU)
41 # 这确保了模型和输入在同一设备上,避免跨设备操作导致的错误
42 inputs = inputs.to(model.device)
43
44 # 使用torch.no_grad()避免计算梯度,节省内存并加速推理过程
45 # 在推理阶段不需要计算梯度,这可以显著减少内存使用并提高速度
46 with torch.no_grad():
47 # 调用模型的generate方法生成回答
48 # 这里设置了多个生成参数来控制输出的质量和特性
49 outputs = model.generate(
50 **inputs,
51 max_length=max_length, # 设置生成文本的最大长度
52 num_return_sequences=1, # 只返回一个生成序列
53 do_sample=True, # 使用采样策略,增加多样性
54 temperature=0.6, # 温度参数,控制生成文本的随机性(与模型配置一致)
55 top_p=0.95, # 使用nucleus sampling,只考虑概率和超过0.95的token(与模型配置一致)
56 top_k=20, # 只考虑概率最高的20个token,增加生成文本的可控性
57 repetition_penalty=1.1, # 重复惩罚系数,降低模型重复同一内容的可能性
58 pad_token_id=151643, # 填充标记ID(与模型配置中的eos_token_id一致)
59 bos_token_id=151646, # 句子开始标记ID(与模型配置一致)
60 eos_token_id=151643, # 句子结束标记ID(与模型配置一致)
61 use_cache=True, # 使用缓存加速生成过程
62 )
63
64 # 将生成的token序列解码为文本
65 # skip_special_tokens=True会跳过特殊标记,只保留实际文本内容
66 # clean_up_tokenization_spaces=True会清理分词过程中产生的额外空格
67 full_response = tokenizer.decode(outputs[0], skip_special_tokens=True, clean_up_tokenization_spaces=True)
68
69 # 分离模型输入和输出
70 # 如果在完整响应中找到了助手标记后的内容,则提取出来
71 # 否则尝试找出与输入不同的部分作为输出
72 if "<|Assistant|>" in full_response:
73 response = full_response.split("<|Assistant|>")[1].strip()
74 else:
75 input_without_assistant = prompt.split("<|Assistant|>")[0]
76 if full_response.startswith(input_without_assistant):
77 response = full_response[len(input_without_assistant) :].strip()
78 else:
79 response = "[无法分离模型生成内容] " + full_response
80
81 # 返回两个独立的结果:输入提示词和模型生成的回答
82 return prompt, response
83
84
85def process_test_data():
86 """
87 处理测试数据集并生成客服回答
88
89 功能:
90 - 加载客服问答测试数据集
91 - 初始化模型和分词器
92 - 对每个测试样本生成客服回答
93 - 清晰区分并打印模型的输入提示词和输出结果
94
95 返回:
96 None,结果直接打印
97 """
98 # 加载测试数据
99
100 # 加载模型和分词器
101 print(f"加载模型: {MODEL_PATH}")
102
103 print("正在加载分词器...")
104 # 加载预训练的分词器,使用local_files_only=True确保只从本地加载
105 # 分词器负责将文本转换为数字token序列,这是模型处理文本的第一步
106 tokenizer = AutoTokenizer.from_pretrained(
107 MODEL_PATH,
108 trust_remote_code=True, # 允许使用模型自定义的代码
109 padding_side="left", # 在左侧进行填充,适合生成任务
110 truncation_side="left", # 在左侧进行截断,保留最新的内容
111 )
112
113 print("正在加载模型...")
114 # 加载预训练的语言模型,同样使用local_files_only=True
115 # 模型是实际执行推理的部分,加载到合适的设备(CPU/GPU)上
116 model = AutoModelForCausalLM.from_pretrained(
117 MODEL_PATH,
118 trust_remote_code=True, # 允许使用模型自定义的代码
119 device_map="auto", # 自动选择可用的设备(CPU/GPU)
120 torch_dtype=torch.bfloat16, # 使用bfloat16精度,在保持准确性的同时减少内存占用
121 use_cache=True, # 启用缓存以提高生成速度
122 )
123
124 # 设置模型为评估模式,关闭dropout等训练特性,提高推理性能
125 # 评估模式下模型行为更加确定,适合推理任务
126 model.eval()
127
128 # 处理每个测试样本
129 print("开始生成客服回答...")
130
131 try:
132 # 提取指令和输入文本
133 instruction = "What types of grants are included in the full grant date fair value calculation?" # 指令部分,通常是客户问题
134 input_text = "(1) Amounts shown in this column do not reflect dollar amounts actually received by the NEO. Instead, these amounts reflect the aggregate full grant date fair value calculated in accordance with ASC 718 for the respective fiscal year for grants of RSUs, SY PSUs, and MY PSUs, as applicable. The assumptions used in the calculation of values of the awards are set forth under Note 4 to our consolidated financial statements titled Stock-Based Compensation in our Form 10-K. With regard to the stock awards with performance-based vesting conditions, the reported grant date fair value assumes the probable outcome of the conditions at Base Compensation Plan for SY PSUs and MY PSUs, determined in accordance with applicable accounting standards."
135
136 # 生成回答
137 print("\n===== 模型预测 =====")
138
139 print("\n正在生成客服回答...")
140
141 # 构造完整提示并生成回答
142 prompt, response = generate_response(model, tokenizer, instruction, input_text)
143
144 # 清晰区分模型输入和输出(只打印一次)
145 print("\n\n==================== 模型输入 ====================")
146 print(prompt)
147
148 print("\n\n==================== 模型输出(仅包含生成部分)====================")
149 print(response)
150
151 except Exception as e:
152 # 异常处理,确保一个样本的错误不会导致整个程序崩溃
153 # 这对于批量处理多个样本时非常重要
154 print(f"\n处理样本时出错: {str(e)}")
155 import traceback
156
157 traceback.print_exc() # 打印详细错误信息,便于调试
158
159 print("\n客服回答生成完成!")
160 return None
161
162
163def main():
164 """
165 主函数,程序入口点
166
167 功能:
168 - 启动客服聊天机器人测试流程
169 - 处理测试数据并生成回答
170 - 控制整个程序的执行流程
171 """
172 print("===== 客服聊天机器人模型调用 =====")
173 process_test_data()
174
175
176if __name__ == "__main__":
177 main()