RAG检索引擎Elasticsearch安装配置(mac)及pdf灌库案例

基本流程:

  • 文档加载,按条件切割成片段
  • 将切割的文本片段灌入检索引擎
  • 封装检索接口
  • 构造调用流程:Query -> 检索 ->Prompt->LLM->回复

检索引擎:Elasticsearch

        Elasticsearch 是一个分布式搜索和分析引擎,专门用于处理大规模的数据搜索、日志分析和数据存储。它基于 Apache Lucene 库构建,提供了实时的全文搜索功能,可以在大规模数据集上进行高效的搜索、索引和分析。

下载链接:Download Elasticsearch | Elastic

下载完成后 bin内运行elasticsearch

mac系统提醒打不开,在系统设置里,找到隐私与安全性,点仍要打开

我下载的是8.15.1版本的,默认用了自带的jdk,但是jdk打不开,只能用我本地自己的jdk

解决方法:进入终端,cd到bin目录

vim elasticsearch-env

找到以下代码块并修改为:

if [ ! -z "$JAVA_HOME" ]; then
  JAVA="$JAVA_HOME/bin/java"
  JAVA_TYPE="JAVA_HOME"

  if [ ! -x "$JAVA" ]; then
    echo "could not find java in $JAVA_TYPE at $JAVA" >&2
    exit 1
  fi

  # 检查用户指定的 JDK 版本
  "$JAVA" -cp "$ES_HOME/lib/java-version-checker/*" org.elasticsearch.tools.java_version_checker.JavaVersionChecker
else
  # 默认使用捆绑的 JDK
  if [ "$(uname -s)" = "Darwin" ]; then
    # macOS 有不同的结构
    JAVA="$ES_HOME/jdk.app/Contents/Home/bin/java"
  else
    JAVA="$ES_HOME/jdk/bin/java"
  fi
  JAVA_TYPE="bundled JDK"
fi

配置好后重启elasticsearch

终端显示了 用户名和密码,访问https://localhost:9200,如果出现了这个错误,就改为 https 不是 http(未加密)

[WARN ][o.e.h.n.Netty4HttpServerTransport] [MacBook-Pro.local] received plaintext http traffic on an https channel, closing connection Netty4HttpChannel{localAddress=/[0:0:0:0:0:0:0:1]:9200, remoteAddress=/[0:0:0:0:0:0:0:1]:51677}

显示以下内容则说明ok了

接下来我们在项目中新建一个.env文件

ELASTICSEARCH_BASE_URL='https://localhost:9200'
ELASTICSEARCH_PASSWORD='xxx' # 替换成自己的
ELASTICSEARCH_NAME='xxx' # 替换

使用load_dotenv引入配置环境

from dotenv import load_dotenv
load_dotenv()

# 引入配置文件
ELASTICSEARCH_BASE_URL = os.getenv('ELASTICSEARCH_BASE_URL')
ELASTICSEARCH_PASSWORD = os.getenv('ELASTICSEARCH_PASSWORD')
ELASTICSEARCH_NAME= os.getenv('ELASTICSEARCH_NAME')

ok 接下来我们就可以进行rag的项目流程了

pdf预处理函数

# pdf预处理
def extract_text_from_pdf(filename, page_numbers=None, min_line_length=1):
    '''从pdf文件中 按指定页码提取文字'''
    paragraphs = []
    buffer = ""
    full_text = ""
    # 提取全部文本
    for i, page_layput in enumerate(extract_pages(filename)):
        # 如果指定了页码范围,跳过范围外的页
        if page_numbers is not None and i not in page_numbers:
            continue
        for element in page_layput:
            # 检查当前元素是否是LTTextContainer对象,LTTextContainer对象是pdfminer中的的一个类,用于表示PDF中的文本容器
            if isinstance(element, LTTextContainer): 
                full_text += element.get_text() + "\n"
    # 按空行分隔, 将文本重新组织成段落
    lines = full_text.split("\n")
    for text in lines:
        if len(text) >= min_line_length:
            buffer += (' '+ text) if not text.endswith('-') else text.strip('-')  # 针对英文单词换行
        elif buffer:
            paragraphs.append(buffer)
            buffer = ""
    if buffer:
        paragraphs.append(buffer)
    return paragraphs

字符预处理函数

# 预处理函数
def to_keywords(input_string):
    # 使用正则表达式替换所有非字母数字的字符为空格
    no_symbols = re.sub(r'[^a-zA-Z0-9\s]', ' ', input_string)
    tokenize = word_tokenize(no_symbols) # 分词
    # 加载停用词表
    stop_words = set(stopwords.words('english')) 
    ps = PorterStemmer() # 创建porterStemmer对象
    # 去停用词,取词根
    filter_sentence = [ps.stem(w) for w in tokenize if not w.lower() in stop_words]
    return ' '.join(filter_sentence)  # 用空格分隔

关键字检索函数

# 关键字检索
def search(query_string, top_n=3):
    # ES 的查询语言
    search_query = {
        "match":{
            "keywords": to_keywords(query_string)
        }
    }
    res = es.search(index=index_name, query=search_query, size=top_n)
    return [hit["_source"]["text"] for hit in res["hits"]["hits"]]

灌库流程

# 1 创建 Elasticsearch 连接
es = Elasticsearch(
    hosts=[ELASTICSEARCH_BASE_URL], # 服务器地址与端口
    http_auth=('ELASTICSEARCH_NAME', 'ELASTICSEARCH_PASSWORD'), # 账号密码
    verify_certs=False,  # 忽略自签名证书验证
    ssl_show_warn=False  # 禁用 SSL 警告
)

# 2 定义索引名称
index_name = 'demo01'

# 3. 如果索引已存在,删除它(仅供演示,实际应用时不需要这步)
if es.indices.exists(index=index_name):
    es.indices.delete(index=index_name)

# 3 创建索引
es.indices.create(index=index_name)

# 4 灌库指令
actions = [
    {
        "_index": index_name,
        "_source":{
            "keywords":to_keywords(para),
            "text":para
        }
    }
    for para in paragraphs
]

# 文本灌库
helpers.bulk(es, actions) # 批量导入

# 异步灌库
time.sleep(2)

注意:第一次运行在代码中添加以下内容

nltk.download('punkt')
nltk.download('stopwords')

查询结果

results = search("how many parameters does llama 2 have", top_n=3)
for res in results:
    print(res+"\n")

成功查询

### 构建 RAG(Retrieval-Augmented Generation)检索的方法 构建 RAG 检索的核心目标是从大量文档或数据集中高效提取与查询相关的信息片段。以下是关于如何构建 RAG 检索的关键要素和技术细节: #### 1. 数据准备 为了构建有效的检索,需要高质量的数据集作为输入源。这些数据可以来自结构化数据、网页抓取内容或其他形式的知识资源[^3]。 - **数据清洗**:去除噪声数据,如广告、重复项和其他无关信息。 - **分词处理**:将文本分割成单词或短语以便后续分析。 - **标注分类**(可选):如果适用,可以通过人工或自动方式对数据进行标记以提升检索精度。 #### 2. 向量化表示 为了让机器理解自然语言并能快速匹配相似条目,需采用合适的向量嵌入技术转换原始文本至数值空间[^2]。 - 使用预训练的语言模型(例如 BERT, RoBERTa 等),获取句子级别的密集向量表达。 - 或者应用传统方法比如 TF-IDF 来计算稀疏特征矩阵。 #### 3. 创建索引结构 建立高效的索引来加速最近邻查找过程至关重要。常见的几种策略包括但不限于以下选项: - Annoy (Approximate Nearest Neighbors Oh Yeah): 提供近似最邻近搜索功能,在高维环境下表现良好。 - FAISS(Facebook AI Similarity Search): Facebook 开发的一个用于大规模相似度搜索的,特别适合于处理海量矢量集合中的精确/近似的KNN问题。 ```python import faiss from sentence_transformers import SentenceTransformer model = SentenceTransformer('all-MiniLM-L6-v2') texts = ["example text", ... ] # Your corpus here embeddings = model.encode(texts) index = faiss.IndexFlatL2(embeddings.shape[1]) # Build the index index.add(np.array(embeddings)) # Add vectors to it ``` #### 4. 集成搜索引擎 最后一步是把前面所做的一切整合到一起形成完整的解决方案。这通常意味着开发一个API端点或者命令行工具让用户提交他们的请求,并返回最佳候选列表连同相应分数一同给出[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值