[本科项目实训] 行动模拟实现 与 FastAPI 对应交互-V0

to 2024 / 06 / 16

行动模拟

该项目拟通过大语言模型分析拆解人类描述的任务,自动的调用行动库进行执行并完成内容的汇报。因而需要针对任务对大模型进行微调(比如本项目使用的p-tuning v2),行动模拟即针对微调结果将大模型与行动库进行对接,模拟实际场景下的函数输入输出。

第一步,即加载微调后的大模型,可参考之前博客中给出的cli_demo.py:

# load raw model
tokenizer = AutoTokenizer.from_pretrained(model_path % model_name, trust_remote_code=True)
config = AutoConfig.from_pretrained(model_path % model_name, trust_remote_code=True)
config.pre_seq_len = pre_seq_len
model = AutoModel.from_pretrained(model_path % model_name, config=config, trust_remote_code=True)

# feed ptuning model
prefix_state_dict = torch.load(os.path.join(model_path % ptuning_checkpoint, "pytorch_model.bin"))
new_prefix_state_dict = {}
for k, v in prefix_state_dict.items():
    if k.startswith("transformer.prefix_encoder."):
        new_prefix_state_dict[k[len("transformer.prefix_encoder."):]] = v
model.transformer.prefix_encoder.load_state_dict(new_prefix_state_dict)

# model config
model = model.quantize(quantization_bit)
model = model.half().cuda()
model.transformer.prefix_encoder.float().cuda()
model.eval()

第二步,即设计大模型与行动库的交互步骤,这里根据场景要求给出五步:

  • 语言模型基于人类输入文本进行任务类型判定和拆解
  • 行动库接受参数并模拟对应任务反馈给语言模型结果
  • 语言模型基于结果进行简单分析并给出任务结果报告
  • 整合输出结果以 PDF 的格式展示为报告方便下载打印
  • 记录所有内容并反馈给后端,供前后端交互
def simulate(uid, prompt, options, params, history_formatted, chat_tmp_path):
    # init
    data_lines = []; act_img_path = None
    prefix = ["【系统】","【核心】"]; suffix = "\n\n"; key = "KEY"
    act_map = {"零":__act0, "壹":__act1, "贰":__act2}
    template = ["步骤#理解并基于输入拆分函数参数\*语音#%s",
                "步骤#基于函数调用结果进行总结\*结果#%s"]

    # step1: LLM response -> understand & split
    data_lines.append("%s正在与LLM语言核心交互%s" %  (prefix[0], suffix))
    response0, _ = model.chat(tokenizer, template[0] % prompt, history_formatted, 
        max_length=params['max_length'], top_p=params['top_p'], temperature=params['temperature'])
    
    # WARN:TEST
    response0 = response0 + "KEY壹;济南"
    
    data_lines.append("%s%s%s" %  (prefix[1], response0, suffix))

    # step2: text split & action select( N=3 )
    kidx_st = response0.find(key)
    uf_flag = kidx_st==-1
    if not uf_flag:
        kidx_ed = response0.find(";", kidx_st)
        uf_flag = kidx_ed==-1
    if uf_flag:
        data_lines.append("%sLLM语言核心解析函数失败%s" %  (prefix[0], suffix))
    else:
        act_info, act_response, act_text, act_img_path = act_map[response0[kidx_st+3:kidx_ed]](response0[kidx_ed:])
        data_lines.append("%s%s%s" %  (prefix[0], act_info, suffix))
        data_lines.append("%s%s%s" %  (prefix[0], "默认查询日期:" + str(datetime.date.today()), suffix))
        data_lines.append("%s%s%s" %  (prefix[0], act_response, suffix))

    # step4: LLM response -> analysis
        response1, _ = model.chat(tokenizer, template[1] % act_response, history_formatted, 
            max_length=params['max_length'], top_p=params['top_p'], temperature=params['temperature'])
        data_lines.append("%s%s%s" %  (prefix[1], response1, suffix))

    # step4: pdf generate
        if __gen_pdf(uid, act_text):
            data_lines.append("%s任务报告输出完成%s" %  (prefix[1], suffix))
        else:
            data_lines.append("%s任务报告生成失败%s" %  (prefix[1], suffix))

    # step5: write to the tmp_file
    with open(chat_tmp_path, mode="w", encoding='utf-8') as f:
        f.writelines(data_lines)

    # step6: send back sim_img_path
    return act_img_path

这里需要设计好大语言模型微调时的prompt,确保模型交互没有问题。实际上这里模型参与了多种问题的处理,我尝试了基于不同的prompt模板训练不同的微调模型,使其对于当前的多任务情况更加适配,这在之后的博客中会有所提及。但这里的行动库并不完善,其中模拟操作可能需要返回图片等佐证。

FastAPI 交互

在行动模拟程序与后端的交互中,我写了一个样例:

img_path = simulate(uid, prompt, options, params, history_formatted, chat_tmp_path)
    
# gen stream_obj
def __itf():
    cline=""
    with open(chat_tmp_path, mode="r", encoding='utf-8') as f:
        for line in f:
            cline = cline + line; time.sleep(tdelay)
            yield ("data: " + json.dumps( 
                        dict(
                            role="AI", id=uid, 
                            parentMessageId=None, 
                            text=cline + footer
                        ) 
                    ))
    
# return stream response
return StreamingResponse(content=__itf(), headers=stream_response_headers,
                         media_type="text/event-stream")

行动模拟程序最后一步将所有交互过程写回到临时文件,FastAPI 后端生成一个文件的字节流以相应的格式传给前端进行展示,这里使用了StreamingResponse,其实际上还可以传递图片,文件可以通过FileResponse进行传输。目前为测试版,仅供参考。

参考资料

[1] ChatGLM-6B/ptuning at main · THUDM/ChatGLM-6B · GitHub

[2] 自定义响应 - HTML,流,文件和其他 - FastAPI (tiangolo.com)

posted @ 2024-06-22 15:39  yicheng_liu0219  阅读(41)  评论(0)    收藏  举报