引言
什么是RAG
LLM会产生误导性的 “幻觉”,依赖的信息可能过时,处理特定知识时效率不高,缺乏专业领域的深度洞察,同时在推理能力上也有所欠缺。
正是在这样的背景下,检索增强生成技术(Retrieval-Augmented Generation,RAG)应时而生,成为 AI 时代的一大趋势。
RAG 通过在语言模型生成答案之前,先从广泛的文档数据库中检索相关信息,然后利用这些信息来引导生成过程,极大地提升了内容的准确性和相关性。RAG 有效地缓解了幻觉问题,提高了知识更新的速度,并增强了内容生成的可追溯性,使得大型语言模型在实际应用中变得更加实用和可信。
一个典型的RAG的例子:
这里面主要包括包括三个基本步骤:
1. 索引 — 将文档库分割成较短的 Chunk,并通过编码器构建向量索引。
2. 检索 — 根据问题和 chunks 的相似度检索相关文档片段。
3. 生成 — 以检索到的上下文为条件,生成问题的回答。
通义千问1.5
Qwen1.5版本年前开源了包括0.5B、1.8B、4B、7B、14B和72B在内的六种大小的基础和聊天模型,同时,也开源了量化模型。不仅提供了Int4和Int8的GPTQ模型,还有AWQ模型,以及GGUF量化模型。为了提升开发者体验,Qwen1.5的代码合并到Hugging Face Transformers中,开发者现在可以直接使用transformers>=4.37.0 而无需 trust_remote_code。
与之前的版本相比,Qwen1.5显著提升了聊天模型与人类偏好的一致性,并且改善了它们的多语言能力。所有模型提供了统一的上下文长度支持,支持32K上下文。还有,基础语言模型的质量也有所小幅改进。
Qwen1.5全系列统一具备强大的链接外部系统能力(agent/RAG/Tool-use/Code-interpreter)。
正因为Qwen1.5作为中文LLM率先合入了Transformers,我们也可以使用LLaMaIndex的原生HuggingFaceLLM来加载模型。
LLaMaIndex
LlamaIndex 是一个基于 LLM 的应用程序的数据框架,受益于上下文增强。 这种LLM系统被称为RAG系统,代表“检索增强生成”。LlamaIndex 提供了必要的抽象,可以更轻松地摄取、构建和访问私有或特定领域的数据,以便将这些数据安全可靠地注入 LLM 中,以实现更准确的文本生成。
GTE文本向量
文本表示是自然语言处理(NLP)领域的核心问题, 其在很多NLP、信息检索的下游任务中发挥着非常重要的作用。近几年, 随着深度学习的发展,尤其是预训练语言模型的出现极大的推动了文本表示技术的效果, 基于预训练语言模型的文本表示模型在学术研究数据、工业实际应用中都明显优于传统的基于统计模型或者浅层神经网络的文本表示模型。这里, 我们主要关注基于预训练语言模型的文本表示。
GTE-zh模型使用retromae初始化训练模型,之后利用两阶段训练方法训练模型:第一阶段利用大规模弱弱监督文本对数据训练模型,第二阶段利用高质量精标文本对数据以及挖掘的难负样本数据训练模型。
魔搭社区最佳实践
环境配置与安装
- python 3.10及以上版本
- pytorch 1.12及以上版本,推荐2.0及以上版本
- 建议使用CUDA 11.4及以上
本文主要演示的模型推理代码可在魔搭社区免费实例PAI-DSW的配置下运行(显存24G) :
第一步:点击模型右侧Notebook快速开发按钮,选择GPU环境
第二步:新建Notebook
安装依赖库
!pip install llama-index llama-index-llms-huggingface ipywidgets !pip install transformers -U import logging import sys logging.basicConfig(stream=sys.stdout, level=logging.INFO) logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout)) from IPython.display import Markdown, display import torch from llama_index.llms.huggingface import HuggingFaceLLM from llama_index.core.prompts import PromptTemplate from modelscope import snapshot_download from llama_index.core.base.embeddings.base import BaseEmbedding, Embedding from abc import ABC from typing import Any, List, Optional, Dict, cast from llama_index.core import ( VectorStoreIndex, ServiceContext, set_global_service_context, SimpleDirectoryReader, )
加载大语言模型
因为Qwen本次支持了Transformers,使用HuggingFaceLLM加载模型,模型为(Qwen1.5-4B-Chat)
# Model names qwen2_4B_CHAT = "qwen/Qwen1.5-4B-Chat" selected_model = snapshot_download(qwen2_4B_CHAT) SYSTEM_PROMPT = """You are a helpful AI assistant. """ query_wrapper_prompt = PromptTemplate( "[INST]<<SYS>>\n" + SYSTEM_PROMPT + "<</SYS>>\n\n{query_str}[/INST] " ) llm = HuggingFaceLLM( context_window=4096, max_new_tokens=2048, generate_kwargs={"temperature": 0.0, "do_sample": False}, query_wrapper_prompt=query_wrapper_prompt, tokenizer_name=selected_model, model_name=selected_model, device_map="auto", # change these settings below depending on your GPU model_kwargs={"torch_dtype": torch.float16}, )
加载数据:导入测试数据
!mkdir -p 'data/xianjiaoda/' !wget 'https://modelscope.oss-cn-beijing.aliyuncs.com/resource/rag/xianjiaoda.md' -O 'data/xianjiaoda/xianjiaoda.md' documents = SimpleDirectoryReader("/mnt/workspace/data/xianjiaoda/").load_data() documents
构建Embedding类
加载GTE模型,使用GTE模型构造Embedding类
embedding_model = "iic/nlp_gte_sentence-embedding_chinese-base" class ModelScopeEmbeddings4LlamaIndex(BaseEmbedding, ABC): embed: Any = None model_id: str = "iic/nlp_gte_sentence-embedding_chinese-base" def __init__( self, model_id: str, **kwargs: Any, ) -> None: super().__init__(**kwargs) try: from modelscope.models import Model from modelscope.pipelines import pipeline from modelscope.utils.constant import Tasks # 使用modelscope的embedding模型(包含下载) self.embed = pipeline(Tasks.sentence_embedding, model=self.model_id) except ImportError as e: raise ValueError( "Could not import some python packages." "Please install it with `pip install modelscope`." ) from e def _get_query_embedding(self, query: str) -> List[float]: text = query.replace("\n", " ") inputs = {"source_sentence": [text]} return self.embed(input=inputs)['text_embedding'][0].tolist() def _get_text_embedding(self, text: str) -> List[float]: text = text.replace("\n", " ") inputs = {"source_sentence": [text]} return self.embed(input=inputs)['text_embedding'][0].tolist() def _get_text_embeddings(self, texts: List[str]) -> List[List[float]]: texts = list(map(lambda x: x.replace("\n", " "), texts)) inputs = {"source_sentence": texts} return self.embed(input=inputs)['text_embedding'].tolist() async def _aget_query_embedding(self, query: str) -> List[float]: return self._get_query_embedding(query)
建设索引
加载数据后,基于文档对象列表(或节点列表),建设他们的index,就可以方便的检索他们。
embeddings = ModelScopeEmbeddings4LlamaIndex(model_id=embedding_model) service_context = ServiceContext.from_defaults(embed_model=embeddings, llm=llm) set_global_service_context(service_context) index = VectorStoreIndex.from_documents(documents)
查询和问答
搭建基于本地知识库的问答引擎
query_engine = index.as_query_engine() response = query_engine.query("西安交大是由哪几个学校合并的?") print(response)
参考开源链接https://github.com/modelscope/modelscope/tree/master/examples/pytorch/application