在我的上一篇文章系列中,我讨论了使用诸如LlamaIndex
、LangChain
、GPT4All
、Ollama
等工具构建RAG应用程序,以利用LLM来解决特定应用场景的问题。本文将探讨如何通过三种不同的技术优化RAG系统的准确性和性能:句子窗口检索法
、混合搜索
、重排序
。本文相关的所有源代码已发布在GitLab。请先克隆仓库,以继续本文内容。
基于检索的增强生成(RAG)通过将外部权威知识库整合到生成响应的过程中,提升了大型语言模型(LLM)的性能。RAG应用包括Naive RAG
、Advanced RAG
和Modular RAG
。更多关于这些RAG类型的内容可以从这里阅读。最早的和最基本的RAG方法叫做Naive RAG
。Naive RAG在各个阶段都会面临各种挑战。在检索阶段,可能会出现‘无法找到所有相关片段或找到不相关的片段’。在增强阶段,可能会遇到‘整合检索到的片段时的挑战,这些片段可能不连贯或包含重复信息’。在生成阶段,LLM可能会生成‘未基于提供的上下文(检索到的片段)或基于不相关上下文生成的回答’。
高级RAG
作为一种新的范式已经发展起来,通过有针对性的改进来解决初级RAG
范式的一些局限性。高级RAG的优化技术可以分为预检索
、检索
和后检索
优化。预检索优化主要集中在数据索引优化以及查询优化上。数据索引优化技术旨在以一种帮助提高检索效率的方式来存储数据。预检索优化技术包括滑动窗口
、增强数据粒度
、添加元数据
、优化索引结构
等。检索阶段旨在识别最相关的上下文。通常,检索基于向量搜索,计算查询与索引数据之间的语义相似度。因此,大多数检索优化技术都围绕嵌入模型进行。微调嵌入模型技术
和动态嵌入技术
是检索优化技术的一些示例。对检索到的上下文进行额外处理可以解决诸如上下文窗口限制超限或引入噪声等问题,从而阻碍对关键信息的关注。提示压缩
和重新排名
是后检索优化技术的一些示例。如果您想了解更多关于这些高级RAG优化技术的信息,请参阅这篇文章here。在这篇文章中,我使用了句子窗口检索(预检索)
、混合搜索(检索)
和重新排名(后检索)
来构建高级RAG应用。以下图示说明了初级RAG和高级RAG之间的差异以及相应的技术。
在 Sentence Window Retrieval
技术中,检索时会抓取单个句子,并返回该句子周围的文本窗口。Sentence Window Retrieval 的核心思想是将嵌入和合成过程分开,从而实现更细粒度和目标明确的信息检索。该方法专注于嵌入和检索 单个句子或较小的文本单元
,而不是整个文本块。通过将这些较小的单元嵌入并存储在向量数据库中,这样我们就可以执行更精确的相似性搜索,找到与给定查询最相关的句子。除了检索相关句子外,Sentence Window Retrieval 还包括目标句子前后相关的句子作为上下文,然后将其输入语言模型进行合成,确保生成的答案具有必要的上下文,使其连贯且完整。更多关于 Sentence Window Retrieval 的信息,请参阅 此链接。
混合搜索是一种结合两种或多种搜索算法,旨在提高搜索结果的相关性的技术。虽然没有定义具体结合哪些算法,但混合搜索通常指的是将传统的基于关键字的搜索与现代的向量搜索相结合。传统上,基于关键字的搜索一直是搜索引擎的主要选择。然而,随着机器学习算法的出现,向量嵌入使得一种新的搜索技术——称为语义搜索——得以实现,这种搜索方式可以让数据搜索更加语义化。然而,这两种搜索技术都有其不可忽视的权衡。
关键词搜索
虽然它的确切关键词匹配功能对于特定术语(如产品名称或行业术语)是有益的,但它对拼写错误和同义词很敏感,可能会忽略重要的上下文信息。语义搜索
虽然其语义搜索功能允许基于数据语义的跨语言和多模态搜索,并且对拼写错误具有鲁棒性,但它可能会忽略关键词。此外,它依赖于生成的向量嵌入的质量,并且对领域外的词汇敏感。
结合关键字搜索和向量搜索形成混合搜索,可以让你更好地利用这两种搜索方法的优点,尤其是在文本搜索的用例中,。更多关于混合搜索的信息可以在这里找到。有许多向量数据库支持混合搜索。在这篇文章里,我使用了Qdrant
向量数据库。Qdrant通过结合稀疏和密集向量的支持来实现混合搜索功能。
在RAG中,可能会检索到大量的上下文,但并非所有这些上下文都与问题相关。重新排序和过滤文档,将更相关的文档置于前面,从而提高RAG的有效性。
在 RAG 中,我们会在许多文本文档中执行语义搜索,然后使用语言模型生成响应。为了确保在大规模情况下搜索速度快,我们通常使用向量搜索。但是由于信息被压缩成一个向量,会有一些信息丢失。虽然语义搜索是基于其与搜索查询的语义相似性来检索上下文,但“最相似并不一定最相关”。由于这种信息损失,我们经常发现前几个搜索结果可能会错过相关信息。不幸的是,相关的文档可能被排在 top_k 截断值以下,导致检索不到。重新排序是最简单的方法之一,可以显著提高 RAG 或其他基于检索的流程的召回效果。虽然也可以选择使用更好的检索模型。
重新排序是通过重排序模型(重排序器)来实现的。简而言之,重排序器是跨编码模型(Cross-encoder),它们将一个 document-query
对作为输入,并为该输入对给出一个综合的相关性评分。使用重排序器,用户可以根据给定的查询,将文档按相关性从高到低进行排序。有各种重排序模型可供使用。在这篇文章里,我使用了两个重排序模型 BAAI/bge-reranker-base
和 SentenceTransformerRerank
。SentenceTransformerRerank
使用来自 sentence-transformer 包的跨编码器来重新排列节点。关于这些重排序类型的信息,请参阅这篇 文章。
以下是RAG应用程序的完整实现。该应用程序的完整源代码可以在GitLab上查看,包含了RAG应用程序的完整实现。
3.1. 设置在 config.py
文件中,我定义了 RAG 系统所需的各项配置。这些配置通过环境变量读取,遵循 12-factor 应用程序 的原则。
import os
# 初始化索引标志
INIT_INDEX = os.getenv('INIT_INDEX', 'false').lower() == 'true'
# HTTP 端口
HTTP_PORT = os.getenv('HTTP_PORT', 7654)
# Qdrant 向量存储设置
QDRANT_HOST = os.getenv('QDRANT_HOST', 'localhost')
QDRANT_PORT = os.getenv('QDRANT_PORT', 6333)
3.2 HTTP协议的API (HTTP接口)
RAG应用程序包含了HTTP API。HTTP API的实现是在api.py
文件中进行的。此API包括一个HTTP POST端点api/question
,该端点接收包含question
和user_id
的JSON对象。user_id
用于演示目的。实际上,可以使用HTTP请求中的Authorization header
(例如JWT Bearer token
)来管理user_id
。当用户提交问题请求时,该请求会被转发到model.py
中的chat
函数进行处理。
from flask import Flask
from flask import jsonify
from flask import request
from flask_cors import CORS
import logging
import sys
from model import *
from config import *
app = Flask(__name__) # 创建Flask应用
CORS(app)
logging.basicConfig(stream=sys.stdout, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
@app.route('/api/question', methods=['POST'])
def post_question():
json = request.get_json(silent=True)
question = json['question']
user_id = json['user_id']
logging.info("收到用户 `%s` 发送的问题 `%s`", question, user_id) # 收到用户 `%s` 的问题 `%s`,调整为 `%s` 发送的问题 `%s` 并调整顺序以匹配英文结构
resp = chat(question, user_id)
data = {'answer':resp}
return jsonify(data), 200
if __name__ == '__main__':
init_llm() # 初始化大语言模型
init_index() # 初始化索引
init_query_engine() # 初始化查询引擎
app.run(host='0.0.0.0', port=HTTP_PORT, debug=True) # 启动应用,监听所有网络接口
3.3 模型
以下是展示了模型的实现方式。它包括一个函数 init_index
,该函数从给定的目录路径中抓取数据,并在 Qdrant 向量存储中创建一个向量索引。它使用 SentenceWindowNodeParser
进行预检索优化。它将文档拆分成单独的句子,以便这些句子将被嵌入。对于每个句子,它创建一个上下文窗口,窗口从嵌入句子的前一句开始,到嵌入句子后的一句结束,共计三句。窗口存储为元数据。在检索过程中,返回与查询最匹配的句子。检索后,需要通过定义一个 MetadataReplacementPostProcessor
并将其添加到 node_postprocessors
列表中,从元数据中提取整个窗口替换句子。QdrantVectorStore
启用了混合搜索功能。init_query_engine
函数使用先前创建的向量存储索引初始化 LlamIndex 查询引擎,并处理使用 SentenceTransformerRerank
和 BAAI/bge-reranker-base
模型进行处理的后检索重新排名。chat
函数负责向 LLM 提出问题。
import chromadb
import logging
import sys
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core import (Settings, VectorStoreIndex, SimpleDirectoryReader, PromptTemplate, Document)
from llama_index.core import StorageContext, ServiceContext
from llama_index.core.node_parser import SentenceWindowNodeParser
from llama_index.core.indices.postprocessor import MetadataReplacementPostProcessor
from llama_index.core.indices.postprocessor import SentenceTransformerRerank
from qdrant_client import QdrantClient
from llama_index.vector_stores.qdrant import QdrantVectorStore
from llama_index.llms.openai import OpenAI
import logging
import sys
from config import *
logging.basicConfig(stream=sys.stdout, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
global query_engine
query_engine = None
global index
index = None
def init_llm():
llm = OpenAI(model="gpt-4")
embed_model = OpenAIEmbedding(model_name="text-embedding-3-large")
Settings.llm = llm
Settings.embed_model = embed_model
def init_index():
global index
# 读取 docs 目录中的文档
# 该目录包含与红队和蓝队网络安全策略相关的数据集
reader = SimpleDirectoryReader(input_dir="./docs", recursive=True)
documents = reader.load_data()
logging.info("正在使用 `%d` 个文档来创建索引", len(documents))
# 使用文档创建大文档以更好地平衡文本
document = Document(text="\n\n".join([doc.text for doc in documents]))
# 句子窗口解析器
# window_size = 3,生成的结果窗口将包含三个句子
node_parser = SentenceWindowNodeParser.from_defaults(
window_size=3,
window_metadata_key="window",
original_text_metadata_key="original_text",
)
# 创建 Qdrant 客户端
qdrant_client = QdrantClient(f"http://{QDRANT_HOST}:{QDRANT_PORT}")
# 如果存在则删除该集合,在实际应用中应妥善处理而避免删除
qdrant_client.delete_collection("rahasak")
# 启用混合检索的 Qdrant 向量存储
vector_store = QdrantVectorStore(
collection_name="rahasak",
client=qdrant_client,
enable_hybrid=True,
batch_size=20
)
# 存储上下文和服务上下文
storage_context = StorageContext.from_defaults(vector_store=vector_store)
service_context = ServiceContext.from_defaults(
llm=Settings.llm,
embed_model=Settings.embed_model,
node_parser=node_parser,
)
# 使用 Qdrant 初始化向量存储索引
index = VectorStoreIndex.from_documents(
[document],
service_context=service_context,
storage_context=storage_context,
embed_model=Settings.embed_model
)
def init_query_engine():
global query_engine
global index
# 在检索后,定义 MetadataReplacementPostProcessor 并将其添加到 node_postprocessors 列表中,用元数据中的整个窗口替换句子
postproc = MetadataReplacementPostProcessor(target_metadata_key="window")
# 使用 BAAI/bge-reranker-base 模型的重排序器
rerank = SentenceTransformerRerank(
top_n=2,
model="BAAI/bge-reranker-base"
)
# 配置检索器以返回最相似的文档,默认值为 2
# 使用元数据后处理器和重排序器作为后处理器
query_engine = index.as_query_engine(
similarity_top_k=3,
node_postprocessors=[postproc, rerank],
)
def chat(input_question, user):
global query_engine
response = query_engine.query(input_question)
logging.info("来自 llm 的响应 - %s", response)
# 查看检索到的句子窗口和原始文本
logging.info("响应中的窗口元数据 - %s", response.source_nodes[0].node.metadata["window"])
logging.info("响应中的原始文本元数据 - %s", response.source_nodes[0].node.metadata["original_text"])
return response.response
4. 运行应用程序.
以下是操作RAG应用程序的主要步骤及如何与其互动。可以通过HTTP API提交问题请求,并相应地收到回复。
4.1. 安装依赖项.在这个应用中,我使用了若干必须通过Python的pip包管理工具安装的Python包。在运行应用之前,需要通过pip包管理工具安装这些包。requirements.txt
文件列出了所有必需的包。
huggingface-hub
sentence-transformers
Flask==2.0.1
Werkzeug==2.2.2
flask-cors
tiktoken
unstructured
llama-index
llama-index-llms-openai
llama-index-embeddings-openai
llama-index-embeddings-huggingface
llama-index-vector-stores-qdrant
torch
qdrant-client
fastembed
我用Python虚拟环境来设置这些依赖。可以通过在命令行中输入 pip install -r requirements.txt
来轻松安装这些包。
# 在 `ollama` 源码目录中创建虚拟环境
❯❯ cd iollama
❯❯ python -m venv .venv
# 激活虚拟环境
❯❯ source .venv/bin/activate
# 安装依赖
❯❯ pip install -r requirements.txt
# 如果通过 `requirements.txt` 安装包时出现依赖冲突问题,可以通过 pip 手动安装这些依赖
❯❯ pip install huggingface-hub
❯❯ pip install sentence-transformers
❯❯ pip install Flask==2.0.1
❯❯ pip install Werkzeug==2.2.2
❯❯ pip install flask-cors
❯❯ pip install tiktoken
❯❯ pip install unstructured
❯❯ pip install llama-index
❯❯ pip install llama-index-llms-openai
❯❯ pip install llama-index-embeddings-openai
❯❯ pip install llama-index-embeddings-huggingface
❯❯ pip install llama-index-vector-stores-qdrant
❯❯ pip install torch
❯❯ pip install qdrant-client
❯❯ pip install fastembed
4.2. 运行 Qdrant 向量数据库。
在RAG应用程序中,我使用了Qdrant向量数据库作为向量存储。接下来,我用Docker运行Qdrant。
# 使用 Docker 运行 Qdrant
❯❯ docker run -d -p 6333:6333 qdrant/qdrant
❯❯ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8a80f7907273 docker.io/qdrant/qdrant:latest ./entrypoint.sh 26 小时前创建 已运行 26 小时 0.0.0.0:6333->6333/tcp priceless_ishizaka
4.3. 运行RAG应用
The RAG应用可以通过api.py
按照以下方式启动。在运行之前,需要通过环境变量设置一些必要的配置。运行api.py
后,将会启动HTTP API,允许用户提交问题。
# 设置 openai API 密钥:
❯❯ export OPENAI_API_KEY=<在这里添加 openai API 密钥>
# 运行 rag 应用程序
❯❯ python api.py
2024-07-18 13:55:23,265 - INFO - 使用 46 个文档创建索引
2024-07-18 13:55:23,274 - INFO - HTTP 请求:DELETE http://localhost:6333/collections/rahasak "HTTP/1.1 200 OK"
2024-07-18 13:55:23,275 - INFO - HTTP 请求:GET http://localhost:6333/collections/rahasak/exists "HTTP/1.1 200 OK"
2024-07-18 13:55:23,277 - INFO - HTTP 请求:GET http://localhost:6333/collections/rahasak/exists "HTTP/1.1 200 OK"
检索 5 个文件:100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 5/5 [00:00<00:00, 67216.41it/s]
检索 5 个文件:100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 5/5 [00:00<00:00, 51025.60it/s]
2024-07-18 13:55:24,253 - INFO - HTTP 请求:GET http://localhost:6333/collections/rahasak/exists "HTTP/1.1 200 OK"
检索 5 个文件:100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 5/5 [00:00<00:00, 54330.36it/s]
检索 5 个文件:100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 5/5 [00:00<00:00, 51025.60it/s]
2024-07-18 13:55:25,949 - INFO - HTTP 请求:POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
2024-07-18 13:55:27,382 - INFO - HTTP 请求:POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
2024-07-18 13:55:28,700 - INFO - HTTP 请求:POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
2024-07-18 13:55:30,145 - INFO - HTTP 请求:POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
2024-07-18 13:55:30,171 - INFO - 0.913349 秒后重新请求 /embeddings
2024-07-18 13:55:38,234 - INFO - HTTP 请求:POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
2024-07-18 13:55:39,565 - INFO - HTTP 请求:POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
2024-07-18 13:55:41,006 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak "HTTP/1.1 200 OK"
2024-07-18 13:55:41,017 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/index?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:55:41,019 - INFO - HTTP 请求:GET http://localhost:6333/collections/rahasak/exists "HTTP/1.1 200 OK"
2024-07-18 13:55:41,020 - INFO - HTTP 请求:GET http://localhost:6333/collections/rahasak "HTTP/1.1 200 OK"
2024-07-18 13:56:09,043 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,078 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,101 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,123 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,144 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,164 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,190 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,214 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,240 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,263 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,287 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,311 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,334 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,353 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,378 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,409 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,433 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,455 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,480 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,505 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,526 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,550 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
2024-07-18 13:56:09,559 - INFO - HTTP 请求:PUT http://localhost:6333/collections/rahasak/points?wait=true "HTTP/1.1 200 OK"
* 运行 Flask 应用 'api' (延迟加载) 提供服务
* 环境:生产
警告:这是开发服务器。不要在生产环境中使用这个。
使用生产 WSGI 服务器代替。
* 调试模式:开启
2024-07-18 13:56:10,576 - INFO - 警告:这是开发服务器。不要在生产环境中使用这个。使用生产 WSGI 服务器代替。
* 在所有 IP 地址 (0.0.0.0) 上运行
* 运行在 http://127.0.0.1:7654
* 运行在 http://10.13.40.61:7654
2024-07-18 13:56:10,576 - INFO - * 按下 CTRL+C 退出
2024-07-18 13:56:10,577 - INFO - * 使用 stat 重启
4.4 发帖求助
当RAG应用运行起来后,我可以通过HTTP API提交与红队案例相关的问题。在下面的场景中,我可以查看每个节点检索到的原始句子,以及发送给大模型的上下文句子。
# 提交问题
❯❯ curl -XPOST "http://localhost:7654/api/question" \
--header "Content-Type: application/json" \
--data '
{
"question": "什么是红队",
"user_id": "eranga"
}
'
# RAG 调试输出,检索到的原始句子
2024-07-18 13:57:21,582 - INFO - sentence window retrieval orginal_text - 红队由网络安全专家组成,他们扮演攻击者角色,探测组织安全系统和流程中的弱点和漏洞。
# RAG 调试输出,转发给 LLM 的周围句子窗口
2024-07-18 13:57:21,582 - INFO - sentence window retrieval window - 理解红队
红队是一种结构化和策略性方法,用于评估组织的安全措施。与传统的安全评估不同,红队不仅限于简单的漏洞扫描或渗透测试。它模拟真实的网络威胁,评估组织的整体准备情况。红队由网络安全专家组成,他们扮演攻击者角色,探测组织安全系统和流程中的弱点和漏洞。
红队服务的关键内容包括
红队服务提供多方面的网络安全方法,使其成为合规性和风险管理中不可或缺的一部分。
这些服务包括以下几种实践:
渗透测试(Penetration Testing):
渗透测试,通常称为 Penetration Testing,是红队服务的基础元素。它涉及模拟网络攻击,以识别组织网络、系统和应用程序中的漏洞。
# LLM 返回的答案
{
"answer": "红队是一群模拟真实网络威胁的网络安全专家,旨在评估组织的整体准备情况。他们扮演攻击者角色,探测组织安全系统和流程中的弱点和漏洞。他们的方法是目标导向的,试图通过利用相关弱点来获得预定目标的访问权限。这种过程超出了简单的漏洞扫描或渗透测试。红队通常作为独立的网络安全服务提供商运作。"
}
---
# 提交问题
❯❯ curl -XPOST "http://localhost:7654/api/question" \
--header "Content-Type: application/json" \
--data '
{
"question": "什么是蓝队",
"user_id": "eranga"
}
'
# RAG 调试输出,检索到的原始句子
2024-07-18 14:04:50,840 - INFO - sentence window retrieval orginal_text - 蓝队专注于分析这些攻击并制定缓解和预防策略。
2024-07-18 14:04:50,840 - INFO - 127.0.0.1 - - [18/Jul/2024 14:04:50] "POST /api/question HTTP/1.1" 200 -
# RAG 调试输出,转发给 LLM 的周围句子窗口
2024-07-18 14:04:50,839 - INFO - sentence window retrieval window - 查看 GDPR 合规声明
✓ 我同意
2024-07-18 14:04:50,839 - INFO - sentence window retrieval window - 3/23/24, 1:18 PM 红队与蓝队在网络安全中的角色
https://maddevs.io/blog/red-team-vs-blue-team-in-cybersecurity/ 2/24红队和蓝队是网络安全中的两个关键部分。在这篇文章中,我们将探讨他们运作的基本原则、互动方法及其对组织网络安全的价值。
红队专门模拟真实威胁和攻击,以识别防御系统中的漏洞。蓝队专注于分析这些攻击并制定缓解和预防策略。紫队旨在促进攻防元素之间的有效互动,分析结果并提出优化双方策略和战术的建议。
红队和蓝队的合作将网络安全方法从静态措施转变为一个动态、不断更新的系统。紫队协调这些努力,并确保红队和蓝队之间的有效沟通和知识共享,从而提高整体网络安全策略的有效性。
# LLM 返回的答案
{
"answer": "在网络安全中,蓝队专注于分析攻击并制定缓解和预防策略。他们负责安装、配置和监控连接到公司网络的设备上的防病毒软件、入侵检测系统和其他保护机制。"
}
参照
-
https://medium.com/@drjulija/什么是朴素RAG、高级RAG和模块化RAG范式-edff410c202e
-
https://www.linkedin.com/pulse/通过句子窗口优化LLM性能的检索-rutam-bhagat-v24of
-
https://medium.com/@samvardhan777/增强RAG使用Qdrant和LlamaIndex-e190f93e4864
-
https://medium.com/@abul.aala.fareh/LlamaIndex中不同的重排序技术-6a56ed1f30a3
-
https://medium.com/@bavalpreetsinghh/LlamaIndex通过元数据替换和句子窗口节点解析来增强上下文-94e5ed8cdd6a
-
https://medium.aiplanet.com/使用LlamaIndex构建高级RAG工作流的查询管道-666ddd7d0d41
- https://medium.aiplanet.com/使用LlamaIndex实现高级RAG功能-e06b00dc0ed8
共同学习,写下你的评论
评论加载中...
作者其他优质文章