modelscope可控细节的长文档摘要

modelscope可控细节的长文档摘要尝试
本文的想法来自今年OpenAI cookbook的一篇实践:summarizing_long_documents,目标是演示如何以可控的细节程度总结大型文档。

如果我们想让大语言模型总结一份长文档(例如 10k 或更多tokens),但是直接输入大语言模型往往会得到一个相对较短的摘要,该摘要与文档的长度并不成比例。例如,20k tokens的文档的摘要不会是 10k tokens的文档摘要的两倍长。本文通过将文档分为几部分来解决这个问题,然后分段生成摘要。在对大语言模型进行多次查询后,可以重建完整的摘要。通过控制文本块的数量及其大小,我们最终可以控制输出中的细节级别。

本文使用的工具和模型如下:

大语言模型:Qwen2的GGUF格式模型

工具1:Ollama,将大语言模型GGUF部署成OpenAI格式的API

工具2:transformers,使用transformers的新功能,直接加载GGUF格式模型的tokenizer,用于文档长度查询和分段。

最佳实践

运行Qwen2模型(详见《魔搭社区GGUF模型怎么玩!看这篇就够了》)

复制模型路径,创建名为“ModelFile”的meta文件,内容如下:

FROM /mnt/workspace/qwen2-7b-instruct-q5_k_m.gguf# set the temperature to 0.7 [higher is more creative, lower is more coherent]
PARAMETER temperature 0.7
PARAMETER top_p 0.8
PARAMETER repeat_penalty 1.05
TEMPLATE """{{ if and .First .System }}<|im_start|>system
{{ .System }}<|im_end|>
{{ end }}<|im_start|>user
{{ .Prompt }}<|im_end|>
<|im_start|>assistant
{{ .Response }}"""
# set the system message
SYSTEM """
You are a helpful assistant.
"""

使用ollama create命令创建自定义模型并运行

ollama create myqwen2 --file ./ModelFile
ollama run myqwen2```

安装依赖&读取需要总结的文档

import os
from typing import List, Tuple, Optional
from openai import OpenAI
from transformers import AutoTokenizer
from tqdm import tqdm
# load doc
with open("data/artificial_intelligence_wikipedia.txt", "r") as file:artificial_intelligence_wikipedia_text = file.read()

加载encoding并检查文档长度

HuggingFace的transformers 支持加载GGUF单文件格式,以便为 gguf 模型提供进一步的训练/微调功能,然后再将这些模型转换回生态系统gguf中使用ggml,GGUF文件通常包含配置属性,tokenizer,以及其他的属性,以及要加载到模型的所有tensor,参考文档:https://huggingface.co/docs/transformers/gguf

目前支持的模型架构为:llama,mistral,qwen2

# load encoding and check the length of dataset
encoding = AutoTokenizer.from_pretrained("/mnt/workspace/cherry/",gguf_file="qwen2-7b-instruct-q5_k_m.gguf")
len(encoding.encode(artificial_intelligence_wikipedia_text))

调用LLM的OpenAI格式的API

client = OpenAI(base_url = 'http://127.0.0.1:11434/v1',api_key='ollama', # required, but unused
)def get_chat_completion(messages, model='myqwen2'):response = client.chat.completions.create(model=model,messages=messages,temperature=0,)return response.choices[0].message.content

文档拆解

我们定义了一些函数,将大文档分成较小的部分。

def tokenize(text: str) -> List[str]:    return encoding.encode(text)
# This function chunks a text into smaller pieces based on a maximum token count and a delimiter.
def chunk_on_delimiter(input_string: str,max_tokens: int, delimiter: str) -> List[str]:chunks = input_string.split(delimiter)combined_chunks, _, dropped_chunk_count = combine_chunks_with_no_minimum(chunks, max_tokens, chunk_delimiter=delimiter, add_ellipsis_for_overflow=True)if dropped_chunk_count > 0:print(f"warning: {dropped_chunk_count} chunks were dropped due to overflow")combined_chunks = [f"{chunk}{delimiter}" for chunk in combined_chunks]return combined_chunks# This function combines text chunks into larger blocks without exceeding a specified token count. It returns the combined text blocks, their original indices, and the count of chunks dropped due to overflow.
def combine_chunks_with_no_minimum(chunks: List[str],max_tokens: int,chunk_delimiter="\n\n",header: Optional[str] = None,add_ellipsis_for_overflow=False,
) -> Tuple[List[str], List[int]]:dropped_chunk_count = 0output = []  # list to hold the final combined chunksoutput_indices = []  # list to hold the indices of the final combined chunkscandidate = ([] if header is None else [header])  # list to hold the current combined chunk candidatecandidate_indices = []for chunk_i, chunk in enumerate(chunks):chunk_with_header = [chunk] if header is None else [header, chunk]if len(tokenize(chunk_delimiter.join(chunk_with_header))) > max_tokens:print(f"warning: chunk overflow")if (add_ellipsis_for_overflowand len(tokenize(chunk_delimiter.join(candidate + ["..."]))) <= max_tokens):candidate.append("...")dropped_chunk_count += 1continue  # this case would break downstream assumptions# estimate token count with the current chunk addedextended_candidate_token_count = len(tokenize(chunk_delimiter.join(candidate + [chunk])))# If the token count exceeds max_tokens, add the current candidate to output and start a new candidateif extended_candidate_token_count > max_tokens:output.append(chunk_delimiter.join(candidate))output_indices.append(candidate_indices)candidate = chunk_with_header  # re-initialize candidatecandidate_indices = [chunk_i]# otherwise keep extending the candidateelse:candidate.append(chunk)candidate_indices.append(chunk_i)# add the remaining candidate to output if it's not emptyif (header is not None and len(candidate) > 1) or (header is None and len(candidate) > 0):output.append(chunk_delimiter.join(candidate))output_indices.append(candidate_indices)return output, output_indices, dropped_chunk_count

摘要函数

现在我们可以定义一个实用程序来以可控的细节级别总结文本(注意参数detail)。

该函数首先根据可控参数在最小和最大块数之间进行插值来确定块数detail。然后,它将文本拆分成块并对每个块进行总结。

<span>def summarize(text: str,</span>

现在,我们可以使用此实用程序生成具有不同详细程度的摘要。通过detail从 0 增加到 1,我们可以逐渐获得更长的底层文档摘要。参数值越高,detail摘要越详细,因为实用程序首先将文档拆分为更多块。然后对每个块进行汇总,最终摘要是所有块摘要的串联。

def summarize(text: str,detail: float = 0,model: str = 'myqwen2',additional_instructions: Optional[str] = None,minimum_chunk_size: Optional[int] = 500,chunk_delimiter: str = "\n",summarize_recursively=False,verbose=False):"""Summarizes a given text by splitting it into chunks, each of which is summarized individually. The level of detail in the summary can be adjusted, and the process can optionally be made recursive.Parameters:- text (str): The text to be summarized.- detail (float, optional): A value between 0 and 1 indicating the desired level of detail in the summary.0 leads to a higher level summary, and 1 results in a more detailed summary. Defaults to 0.- model (str, optional): The model to use for generating summaries. Defaults to 'gpt-3.5-turbo'.- additional_instructions (Optional[str], optional): Additional instructions to provide to the model for customizing summaries.- minimum_chunk_size (Optional[int], optional): The minimum size for text chunks. Defaults to 500.- chunk_delimiter (str, optional): The delimiter used to split the text into chunks. Defaults to ".".- summarize_recursively (bool, optional): If True, summaries are generated recursively, using previous summaries for context.- verbose (bool, optional): If True, prints detailed information about the chunking process.Returns:- str: The final compiled summary of the text.The function first determines the number of chunks by interpolating between a minimum and a maximum chunk count based on the `detail` parameter. It then splits the text into chunks and summarizes each chunk. If `summarize_recursively` is True, each summary is based on the previous summaries, adding more context to the summarization process. The function returns a compiled summary of all chunks."""# check detail is set correctlyassert 0 <= detail <= 1# interpolate the number of chunks based to get specified level of detailmax_chunks = len(chunk_on_delimiter(text, minimum_chunk_size, chunk_delimiter))min_chunks = 1num_chunks = int(min_chunks + detail * (max_chunks - min_chunks))# adjust chunk_size based on interpolated number of chunksdocument_length = len(tokenize(text))chunk_size = max(minimum_chunk_size, document_length // num_chunks)text_chunks = chunk_on_delimiter(text, chunk_size, chunk_delimiter)if verbose:print(f"Splitting the text into {len(text_chunks)} chunks to be summarized.")print(f"Chunk lengths are {[len(tokenize(x)) for x in text_chunks]}")# set system messagesystem_message_content = "Rewrite this text in summarized form."if additional_instructions is not None:system_message_content += f"\n\n{additional_instructions}"accumulated_summaries = []for chunk in tqdm(text_chunks):if summarize_recursively and accumulated_summaries:# Creating a structured prompt for recursive summarizationaccumulated_summaries_string = '\n\n'.join(accumulated_summaries)user_message_content = f"Previous summaries:\n\n{accumulated_summaries_string}\n\nText to summarize next:\n\n{chunk}"else:# Directly passing the chunk for summarization without recursive contextuser_message_content = chunk# Constructing messages based on whether recursive summarization is appliedmessages = [{"role": "system", "content": system_message_content},{"role": "user", "content": user_message_content}]# Assuming this function gets the completion and works as expectedresponse = get_chat_completion(messages, model=model)accumulated_summaries.append(response)# Compile final summary from partial summariesfinal_summary = '\n\n'.join(accumulated_summaries)return final_summary
summary_with_detail_0 = summarize(artificial_intelligence_wikipedia_text, detail=0, verbose=True)

summary_with_detail_pt25 = summarize(artificial_intelligence_wikipedia_text, detail=0.25, verbose=True)

在这里插入图片描述

此实用程序还允许传递附加指令。

summary_with_additional_instructions = summarize(artificial_intelligence_wikipedia_text, detail=0.1,additional_instructions="Write in point form and focus on numerical data.")
print(summary_with_additional_instructions)

最后,请注意,该实用程序允许递归汇总,其中每个摘要都基于先前的摘要,从而为汇总过程添加更多上下文。可以通过将参数设置summarize_recursively为 True 来启用此功能。这在计算上更昂贵,但可以提高组合摘要的一致性和连贯性。

recursive_summary = summarize(artificial_intelligence_wikipedia_text, detail=0.1, summarize_recursively=True)
print(recursive_summary)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/40824.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

6个步骤实现Postman接口压力测试(建议收藏)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 这里讲是postman做接口并发测试&#xff0c;基础用法不做赘述 1、第一步接口可以通的情况下点击…

Proteus-51单片机-DS18B20多点测温

DS18B20多点测温 一、Proteus仿真演示 每个DS18B20都有一个唯一的64位序列号,这使得在同一总线上可以挂载多个传感器,无需额外的地址分配。主机(通常为单片机)通过特定的时序控制,可以依次读取各个DS18B20的温度数据,实现分布式测温。 二、代码特点 三、开发环境介绍 本…

基于Arduino平台开源小车的初步使用体验

创作原因&#xff1a;偶然有机会接触到基于Arduino平台的开源智能小车&#xff0c;初步使用后与大家分享。因使用时间不常&#xff0c;可以纯当个乐子看看&#xff0c;感谢大家的阅读&#xff01; 图&#xff1a;一款基于Arduino平台的开源小车 一、开发环境 Misly&#xff1…

el表达式笔记及ognl

文章目录 spel底层spel核心代码TokenKind源码 spel本地调试 spel示例spel list例子spel 对象例子spel list例子SimpleEvaluationContext 类找不到##### spel 如何表示包含(也就是like)? spel官网文档 ognl表达式ognl和表达式语言的区别 这里重点说下SPEL(Spring Expression La…

shark云原生-日志体系-filebeat高级配置(适用于生产)

文章目录 1. filebeat.inputs 静态日志收集器2. filebeat.autodiscover 自动发现2.1. autodiscover 和 inputs2.2. 如何配置1.2.1. Providers 提供者1.2.2. Providers kubernetes templates1.2.3. 基于提示&#xff08;hints&#xff09;的自动发现支持的 **hints**的完整列表&…

windows搭建mqtt服务器,并配置DTU收集传感器数据

1.下载并安装emqx服务器 参考&#xff1a;Windows系统下本地MQTT服务器搭建&#xff08;保姆级教程&#xff09;_mqtt windows-CSDN博客 这里我下载的是emqx-5.3.0-windows-amd64.zip版本 下载好之后&#xff0c;放到服务器的路径&#xff0c;我这里放的地方是&#xff1a;C…

脑启发设计:人工智能的进化之路

编者按&#xff1a;你可以用左手&#xff08;不常用的那只手&#xff09;的小指与食指拿起一件物品么&#xff1f; 试完你是不是发现自己竟然可以毫不费力地用自己不常用的手中&#xff0c;两根使用频率相对较低的手指&#xff0c;做一个不常做的动作。这就是人类大脑不可思议…

如何声明一个类?类如何继承?

要声明一个类&#xff0c;需要使用关键字class&#xff0c;后面跟着类名。类名通常以大写字母开头。类的声明通常包括类的成员变量和成员函数。 类可以通过继承来扩展现有的类。要让一个类继承另一个类&#xff0c;需要使用冒号&#xff08;:&#xff09;并在后面跟着父类的名…

等保2.0中,云计算平台如何做到数据的分类和加密?

数据分类 在等保2.0中&#xff0c;数据分类是确保数据安全的首要步骤。云计算平台需要根据数据的敏感性和重要性进行分类&#xff0c;以便采取相应的保护措施。数据分类通常包括以下几个步骤&#xff1a; 数据识别&#xff1a;识别出哪些数据是需要保护的&#xff0c;这可能包…

py黑帽子学习笔记_burp

配置burp kali虚机默认装好了社区版burp和java&#xff0c;其他os需要手动装 burp是用java&#xff0c;还得下载一个jython包&#xff0c;供burp用 配apt国内源&#xff0c;然后apt install jython --download-only&#xff0c;会只下载包而不安装&#xff0c;下载的目录搜一…

电子数据取证如何规范高效

文章关键词&#xff1a;电子数据取证、现场勘验、手机取证 随着信息技术的迅猛发展和广泛应用&#xff0c;电子数据作为一种独立的法定证据形式&#xff0c;在执纪执法实践中的作用愈加凸显。规范、科学、高效的电子数据取证工作&#xff0c;不仅是保证电子数据符合法定要求、…

FreeRTOS LVGL页面切换为LCD纯手动绘制遇到的问题

有时候我们需要将FreeRTOS和LVGL页面切换为LCD纯手动绘制,提供更高的灵活性和可定制性。 自定义界面设计:使用LCD纯手动绘制界面,可以完全自定义界面的外观和行为。可以根据特定的需求和设计概念创建独特的用户界面,而不受LVGL框架的限制。 资源优化:LVGL是一个功能强大的…

9.x86游戏实战-汇编指令mov

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

java实现多级菜单展示(递归)

实体类如下&#xff1a; package com.ssdl.baize.po;import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.annotations.ApiModel; import io.swagge…

cefsharp在splitContainer.Panel2中显示调试工具DevTools(非弹出式)含源代码

一、弹出式调试工具 (ShowDevTools) ChromiumWebBrowser webbrowser; public void showDevTools(){//定位到某元素webbrowser.ShowDevTools(null, parameters.XCoord, parameters.YCoord);

STM32智能农业监控系统教程

目录 引言环境准备智能农业监控系统基础代码实现&#xff1a;实现智能农业监控系统 4.1 数据采集模块 4.2 数据处理与分析 4.3 控制系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;农业监控与优化问题解决方案与优化收尾与总结 1. 引言 智能农业监控系统利用STM32嵌…

代码随想录day37 动态规划(3)

416. 分割等和子集 - 力扣&#xff08;LeetCode&#xff09; 解1&#xff1a;二维dp数组&#xff0c;时间O(m*n)&#xff0c;空间O(m*n)&#xff0c;m、n为dp数组的行和列数。 判断原数组总和能否整除2&#xff1b; 将target设为total // 2&#xff08;若是total / 2&#…

遇到的异步问题

事例1&#xff1a; app.post("/predictfunc") async def predictfunc(item: Item):# 使用asyncio.to_thread()在单独的线程中运行predict_in_threadresult await asyncio.to_thread(predictfunc_main, item)return result 事例2&#xff1a; app.post("/remo…

PCL从理解到应用【02】PCL环境安装 | PCL测试| Linux系统

前言 本文介绍在Ubuntu18.04系统中&#xff0c;如何安装PCL。 源码安装方式&#xff1a;pcl版本1.91&#xff0c;vtk版本8.2.0&#xff0c;Ubuntu版本18.04。 安装好后&#xff0c;可以看到pcl的库&#xff0c;在/usr/lib/中&#xff1b; 通过编写C代码&#xff0c;直接调用…

华为路由器静态路由配置(eNSP模拟实验)

实验目标 如图下所示&#xff0c;让PC1ping通PC2 具体操作 配置PC设备ip 先配置PC1的ip、掩码、网关。PC2也做这样的配置 配置路由器ip 配置G0/0/0的ip信息 #进入系统 <Huawei>system-view #进入GigabitEthernet0/0/0接口 [Huawei]int G0/0/0 #设置接口的ip和掩码 […