Outlines:用于指令生成和格式化输出的大模型 LLM Python 库

文章目录

  • 1. Outlines简介
  • 2. 使用正则表达式控制模式生成格式
  • 2.1 demo
  • 2.2 正则匹配代码解释
  • 2.3 建议使用txt文件存储正则表达式
  • 1. Outlines简介

    Outlines 是一个帮助用户以简单和稳定方式使用 LLM 的 Python 库,能够基于regex(正则化表达式)、json、grammar 实现 structured generation。

    官方文档:https://outlines-dev.github.io/outlines/welcome/

    Outlines 库的特性:

  • 让 LLM 生成有效的 JSON
  • 用于 vLLM 部署 LLM 服务
  • 使 LLM 遵循正则表达式约束的生成格式
  • 提供强大的 Prompt Templating:通过 Prompt 模板更好地管理复杂的 Prompt
  • 2. 使用正则表达式控制模式生成格式

    2.1 demo

    使用 Outlines 使 LLM 遵循正则表达式约束的生成格式,demo:

    from outlines import models, generate
    from vllm import LLM, SamplingParams
    import re
    
    # 在知乎随便找的一段 text
    text="特别想问,为什么国乒断代这么严重?答:女队还好,30以上陈梦一个,也才30,不结婚生孩子,也能再打两年,后面有孙颖莎,王曼昱,王艺迪,陈幸同,培养培养,后面还有钱天一,蒯蔓,06年的也有男队属于断了,现在就马龙,樊振东,王楚钦,梁靖崑,林高远。巴黎之后,还能指望龙队了吗?36了,就国乒这种不把人练死的强度,他再继续,我都怕他折寿,国外快乐乒乓,没这么高强度训练,马龙可以比肩波尔,老瓦,甚至倪老太太的岁数上赛场,但就国乒这强度,拉倒吧!林高远,巴黎之后30了,也不会再使劲培养了,下面没有打上来,他还是主力之一,梁靖崑,实力有,不稳啊,就问你敢把他带奥运单打吗?开局丢两局,丢三局,再追,谁敢啊?男队巴黎之后,稳的也就只有樊振东和王楚钦,论实力撑死再加一个梁靖崑,林高远。但是稳拿出手的也只有两个人,樊振东和王楚钦,第三个人没了!再看看后面小将,林诗栋?今年19,还不如18.19的王楚钦,王楚钦虽然中间没成绩,但是两头成绩好啊!向鹏?21了,要打出来,现在也该打出来了,结果还不如林诗栋综上所述,女队可以,男队堪忧,不能总指着马龙不知道怎么奥运会了,我这半年前的帖子还火了,各位看客也别在这冷嘲热讽的,实在不行,您站在赛场上,腿不软,您都是厉害的,能站在奥运会赛场上的在我看来都是好选手,您与其在这冷嘲热讽,不如过好你的生活,向一年赚几千万努力呢,都是中国人,对一个站在奥运赛场的人冷嘲热讽大可不必。"
    
    # prompt template
    system_prompt="给你一段对话文本,你需要根据文本分内容进行结构化总结。"
    user_prompt_template=f"文本:{text}请总结文本内容。输出格式为:总结:xxx;支撑观点1:xxx;支撑观点2:xxx;要求支撑观点的数量不超过3个,每个支撑观点的字数不超过50字,输出总字数不超过200字。"
    user_prompt = user_prompt_template.format(text)
    
    # model
    ckpt_path="models/qwen/Qwen2-7B-Instruct"
    llm = LLM(model=ckpt_path, 
        tokenizer=ckpt_path,
        trust_remote_code=False,
        dtype="half",
        max_model_len=8192,
        tensor_parallel_size=4
    )
    tokenizer = llm.get_tokenizer()
    sampling_params = SamplingParams(
            temperature=0.0, 
            max_tokens=1024, 
            repetition_penalty=1.00
    )
    
    # 使用 outlines.models 包装模型
    llm = models.VLLM(llm)
    
    # 使用 regex 控制模型的输出格式,与 user_prompt_template 对应
    regex_str = r"(总结:(.*?)'\n'支撑观点1:(.*?)'\n'支撑观点2:(.*?)'\n'支撑观点\d+:(.*?))"
    generator = generate.regex(llm, regex_str)
    
    # prompt
    messages = [
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": user_prompt}
    ]
    prompt = tokenizer.apply_chat_template(
        messages,
        tokenize=False,
        add_generation_prompt=True
    )
    
    # output
    output = generator(prompt, sampling_params=sampling_params)
    print(output)
    

    输出:

    总结:分析了中国乒乓球国家队男女队的现状及问题;
    支撑观点1:女队相对稳定,有陈梦、孙颖莎等年轻选手;
    支撑观点2:男队面临断代危机,主力选手年龄偏大,年轻选手表现不稳定;
    支撑观点3:强调了对运动员的尊重和理解,建议关注他们的努力和成就。
    文本讨论了中国乒乓球国家队的现状,特别是男队的断代问题,指出女队相对稳定,而男队面临主力老化和年轻选手表现不稳定的问题。
    作者强调了对运动员的尊重和理解,建议关注他们的努力和成就,而非冷嘲热讽。通过对比女队和男队的表现,文本突出了男队面临的挑战和问题。
    作者在讨论中表达了对运动员的关心和支持,呼吁大家关注他们的努力和成就,而非进行负面评价。
    ...
    

    2.2 正则匹配代码解释

    上述 demo 中使用的正则表达式为:

    regex_str = r"(总结:(.?)'\n’支撑观点1:(.?)'\n’支撑观点2:(.?)'\n’支撑观点\d+:(.?))"

    其中 (.*?) 表示匹配整个字符串,并且希望尽可能少地匹配字符,直到字符串的末尾。用法示例如下:

    import re
    
    text = "这是一个正则表达式的使用示例,符号(.*?)用于匹配整个字符串。"
    pattern = r'(.*?)'
    matches = re.findall(pattern, text)
    print(''.join(matches))
    
    # 输出:
    # 这是一个正则表达式的使用示例,符号(.*?)用于匹配整个字符串。
    

    2.3 建议使用txt文件存储正则表达式

    在 2.1 的 demo 中,尽管我们在 regex_str 中加了 \n 换行符,但模型回答并没有按要求换行;并且除了三个支撑观点,模型还输出了其他额外回答。因此使用字符串形式的正则表达式难以严格控制模型的输出格式,建议使用txt文本形式。

    使用 txt 文本形式存储正则表达式:

    output_re.txt:

    总结:(.*?)
    支撑观点1:(.*?)
    支撑观点2:(.*?)
    支撑观点\d+:(.*?)
    

    读取正则表达式:

    with open('output_re.txt', 'r',encoding='utf-8') as f:
        regex_str = f.read()
    generator = generate.regex(llm, regex_str)
    

    输出:

    总结:分析了中国乒乓球国家队男女队的现状及问题;  
    支撑观点1:女队相对稳定,有陈梦、孙颖莎等年轻选手作为后备力量;  
    支撑观点2:男队面临断代危机,主力选手年龄偏大,年轻选手如林高远、梁靖崑等表现不稳定,难以接班;  
    支撑观点3:强调了对运动员的尊重和理解,建议关注他们的努力和成就,而非冷嘲热讽。
    

    可以明显看出,使用txt文本格式读取的正则表达式比字符串格式的正则表达式具有更强的约束力。

    作者:ctrl A_ctrl C_ctrl V

    物联沃分享整理
    物联沃-IOTWORD物联网 » Outlines:用于指令生成和格式化输出的大模型 LLM Python 库

    发表回复