Sign In
Free Sign Up
  • English
  • Español
  • 简体中文
  • Deutsch
  • 日本語
Sign In
Free Sign Up
  • English
  • Español
  • 简体中文
  • Deutsch
  • 日本語

教你的LLM始终以事实而非虚构回答问题

大型语言模型(LLM)是先进的人工智能系统,可以回答各种问题。尽管它们在已知的主题上提供了有用的回答,但在陌生的主题上并不总是准确。这种现象被称为幻觉

# 什么是幻觉?

在我们看一个LLM幻觉的例子之前,让我们先考虑一下维基百科对“幻觉”的定义:

“幻觉是在没有外部刺激的情况下产生的具有真实感的感知。”

此外:

“幻觉是生动的、实质性的,并被认为位于外部客观空间中。”

换句话说,幻觉是对某个真实或具体事物的错误(或虚假)感知。例如,ChatGPT(OpenAI的一种著名大型语言模型)被问到LLM幻觉是什么,它的回答是:

LLM幻觉。来源:aruna-x

因此,问题是,我们如何改进(或修复)这个结果?简明的答案是在问题中添加事实,例如在提问之前或之后提供LLM的定义。

例如:

LLM是大型语言模型(Large Language Model),一种模拟人类口语和书写方式的人工神经网络。请告诉我,LLM幻觉是什么?

ChatGPT对这个问题的公共领域回答是:

ChatGPT LLM幻觉回答

注意:

第一句话“对我之前回答中的混淆表示抱歉”的原因是我们在给ChatGPT提问“LLM幻觉是什么”之前,给它了第二个提示:“LLM是…”。

这些补充提高了答案的质量。至少它不再认为LLM幻觉是“晚期生活偏头痛的伴随症状”!😆

# 外部知识减少幻觉

在这个关键时刻,非常重要的一点是,LLM并不是无所不能、无所不知的终极权威。LLM是在大量数据上进行训练的,它学习语言中的模式,但它可能并不总是能够获得最新的信息或对复杂主题有全面的理解。

那么现在怎么办?如何增加减少LLM幻觉的机会?

解决这个问题的方法是在查询(或提示)中包含支持文档,以引导LLM获得更准确和明智的回答。就像人类一样,它需要从这些文档中学习,以准确正确地回答您的问题。

有许多来源可以提供有用的文档,包括Google或Bing等搜索引擎以及Arxiv等数字图书馆,它们提供了一个搜索相关段落的接口。使用数据库也是一个不错的选择,提供了更灵活和私密的查询接口。

从来源中检索到的知识必须与问题/提示相关。有几种检索相关文档的方法,包括:

  • **基于关键词:**在纯文本中搜索关键词,适用于对术语进行精确匹配。
  • **基于向量搜索:**搜索更接近嵌入的记录,有助于搜索适当的释义或常规文档。

如今,向量搜索非常流行,因为它可以解决释义问题并计算段落的含义。向量搜索不是一种一刀切的解决方案;它应该与特定的过滤器配对使用,以保持其性能,特别是在搜索大量记录时。例如,如果您只想检索与物理学(作为一个学科)相关的知识,您必须过滤掉所有关于其他学科的信息。这样,LLM就不会被来自其他学科的知识所困惑。

# 使用SQL自动化整个过程...和向量搜索

在回答问题之前,LLM还应该学会从数据源中查询数据,自动化整个过程。实际上,LLM已经能够编写SQL查询并遵循指令。

向量流水线

SQL功能强大,可以用于构建复杂的搜索查询。它支持许多不同的数据类型和函数。它允许我们使用ORDER BYLIMIT编写向量搜索的SQL查询,将嵌入之间的相似度分数视为列distance。非常简单明了,不是吗?

有关如何构建向量SQL查询的更多信息,请参见下一节向量SQL的样子

使用向量SQL构建复杂的搜索查询有很多好处,包括:

  • 增加了对数据类型和函数的灵活性支持
  • 提高了效率,因为SQL在数据库内部高度优化和执行
  • 人类可读且易于学习,因为它是标准SQL的扩展
  • 对LLM友好

注意:

互联网上有很多SQL示例和教程。LLM熟悉标准SQL以及一些方言。

除了MyScale之外,许多SQL数据库解决方案(如Clickhouse和PostgreSQL)正在将向量搜索添加到其现有功能中,允许用户使用向量SQL和LLM回答关于复杂主题的问题。同样,越来越多的应用程序开发人员开始将向量搜索与SQL集成到他们的应用程序中。

Boost Your AI App Efficiency now
Sign up for free to benefit from 150+ QPS with 5,000,000 vectors
Free Trial
Explore our product

# 向量SQL的样子

向量结构化查询语言(Vector SQL)旨在教会LLM如何查询向量SQL数据库,并包含以下额外函数:

  • DISTANCE(column, query_vector): 此函数比较列向量和查询向量之间的距离,可以是精确匹配或近似匹配。
  • NeuralArray(entity): 此函数将实体(例如图像或文本片段)转换为嵌入。

使用这两个函数,我们可以扩展标准SQL以进行向量搜索。例如,如果您想搜索与词flower相关的10个相关记录,可以使用以下SQL语句:

SELECT * FROM table
ORDER BY DISTANCE(vector, NeuralArray(flower))
LIMIT 10

DISTANCE函数由以下内容组成:

  • 内部函数NeuralArray(flower)将词flower转换为嵌入。
  • 然后将此嵌入序列化并注入DISTANCE函数中。

向量SQL是SQL的扩展版本,需要根据所使用的向量数据库进行进一步的转换。例如,许多实现对DISTANCE函数有不同的名称。在MyScale中称为distance,在Clickhouse中称为L2DistanceCosineDistance。此外,根据数据库的不同,此函数名称将有不同的翻译。

# 如何教LLM编写向量SQL

现在我们了解了向量SQL的基本原理和其独特的函数,让我们使用LLM来帮助我们编写向量SQL查询。

# 1. 教LLM标准的向量SQL是什么

首先,我们需要教LLM标准的向量SQL是什么。我们的目标是确保LLM在编写向量SQL查询时能够自动执行以下三个操作:

  • 从我们的问题/提示中提取关键词。它可以是一个对象、一个概念或一个主题。
  • 决定使用哪个列执行相似性搜索。它应该始终选择一个用于相似性的向量列。
  • 将我们问题的其余约束条件转换为有效的SQL。

# 2. 设计LLM提示

确定LLM构建向量SQL查询所需的确切信息后,我们可以设计提示,如下所示:

# 这是一个向量SQL提示的示例
_prompt = f"""您是一个MyScale专家。给定一个输入问题,首先创建一个语法正确的MyScale查询来运行,然后查看查询的结果并返回输入问题的答案。
MyScale查询具有一个名为`DISTANCE(column, array)`的向量距离函数,用于计算与用户问题的相关性,并通过该相关性对特征数组列进行排序。
当查询要求获取{top_k}个最接近的行时,您必须使用此距离函数计算到实体的数组在向量列上的距离,并按照距离排序以检索相关行。

*注意*:`DISTANCE(column, array)`只接受数组列作为其第一个参数,并接受一个`NeuralArray(entity)`作为其第二个参数。您还需要一个名为`NeuralArray(entity)`的用户定义函数来检索实体的数组。

除非用户在问题中指定了要获取的示例数量,否则使用LIMIT子句查询最多{top_k}个结果,正如MyScale所要求的那样。您只能按照距离函数的顺序排序。
永远不要查询表中的所有列。您必须只查询需要回答问题的列。将每个列名用双引号(")括起来,以将其标识为定界符。
注意只使用您在下面的表中看到的列名。注意不要查询不存在的列。还要注意哪个列在哪个表中。
如果问题涉及“今天”,请注意使用today()函数获取当前日期。`ORDER BY`子句应始终位于`WHERE`子句之后。不要在SQL的末尾添加分号。注意表模式中的注释。

使用以下格式:

======== 表信息 ========
<一些表信息>

问题:“问题在这里”
SQL查询:“要运行的SQL查询”


让我们开始:

======== 表信息 ========
{table_info}

问题:{input}
SQL查询:

这个提示应该能够完成其工作。但是,您添加的示例越多,构建正确的向量SQL查询的LLM过程就会越好,就像使用以下向量SQL到文本对作为提示:

SQL表创建语句:

------ 表模式 ------
CREATE TABLE "ChatPaper" (
    abstract String,
    id String,
    vector Array(Float32),
    categories Array(String),
    pubdate DateTime,
    title String,
    authors Array(String),
    primary_category String
) ENGINE = ReplicatedReplacingMergeTree()
ORDER BY id
PRIMARY KEY id

问题和答案:

问题:什么是PaperRank?这些作品的贡献是什么?使用具有超过2个类别的论文。
SQL查询:SELECT ChatPaper.title, ChatPaper.id, ChatPaper.authors FROM ChatPaper WHERE length(categories) > 2 ORDER BY DISTANCE(vector, NeuralArray(PaperRank contribution)) LIMIT {top_k}

您添加的相关示例越多,LLM构建正确的向量SQL查询的能力就越好。

最后,以下是一些设计提示时的额外提示:

  • 覆盖可能出现在任何问题中的所有可能函数。
  • 避免单调的问题。
  • 修改表模式,例如添加/删除/修改名称和数据类型。
  • 对齐提示的格式。
Join Our Newsletter

# 一个真实世界的例子:使用MyScale

让我们现在构建一个真实世界的例子 (opens new window),按照以下步骤进行:

一个真实世界的例子:使用MyScale

# 准备数据库

我们已经为您准备了一个游乐场,其中有超过200万篇论文可以查询。您可以通过将以下Python代码添加到您的应用程序中来访问这些数据。

from sqlalchemy import create_engine
MYSCALE_HOST = "msc-950b9f1f.us-east-1.aws.myscale.com"
MYSCALE_PORT = 443
MYSCALE_USER = "chatdata"
MYSCALE_PASSWORD = "myscale_rocks"

engine = create_engine(f'clickhouse://{MYSCALE_USER}:{MYSCALE_PASSWORD}@{MYSCALE_HOST}:{MYSCALE_PORT}/default?protocol=https')

如果您愿意,您可以跳过接下来的步骤,其中我们使用MyScale控制台创建表并插入数据,并跳到我们使用向量SQL和创建SQLDatabaseChain来查询数据库的部分。

创建数据库表:

CREATE TABLE default.ChatArXiv (
    `abstract` String,
    `id` String,
    `vector` Array(Float32),
    `metadata` Object('JSON'),
    `pubdate` DateTime,
    `title` String,
    `categories` Array(String),
    `authors` Array(String),
    `comment` String,
    `primary_category` String,
    CONSTRAINT vec_len CHECK length(vector) = 768)
ENGINE = ReplacingMergeTree ORDER BY id SETTINGS index_granularity = 8192

插入数据:

INSERT INTO ChatArXiv
SELECT
  abstract, id, vector, metadata,
  parseDateTimeBestEffort(JSONExtractString(toJSONString(metadata), 'pubdate')) AS pubdate,
  JSONExtractString(toJSONString(metadata), 'title') AS title,
  arrayMap(x->trim(BOTH '"' FROM x), JSONExtractArrayRaw(toJSONString(metadata), 'categories')) AS categories,
  arrayMap(x->trim(BOTH '"' FROM x), JSONExtractArrayRaw(toJSONString(metadata), 'authors')) AS authors,
  JSONExtractString(toJSONString(metadata), 'comment') AS comment,
  JSONExtractString(toJSONString(metadata), 'primary_category') AS primary_category
FROM
  s3(
    'https://myscale-demo.s3.ap-southeast-1.amazonaws.com/chat_arxiv/data.part*.zst',
    'JSONEachRow',
    'abstract String, id String, vector Array(Float32), metadata Object(''JSON'')',
    'zstd'
  );
ALTER TABLE ChatArXiv ADD VECTOR INDEX vec_idx vector TYPE MSTG('metric_type=Cosine');

# 创建VectorSQLDatabaseChain

您将需要LangChain实验性包来使用VectorSQLDatabaseChain。您可以通过执行以下安装脚本来安装它:

python3 -m venv .venv
source .venv/bin/activate
pip3 install langchain langchain-experimental --upgrade

安装了此功能后,下一步是使用它来查询数据库,如下所示的Python代码:

from sqlalchemy import create_engine
MYSCALE_HOST = "msc-950b9f1f.us-east-1.aws.myscale.com"
MYSCALE_PORT = 443
MYSCALE_USER = "chatdata"
MYSCALE_PASSWORD = "myscale_rocks"

# 创建与数据库的连接
engine = create_engine(f'clickhouse://{MYSCALE_USER}:{MYSCALE_PASSWORD}@{MYSCALE_HOST}:{MYSCALE_PORT}/default?protocol=https')

from langchain.embeddings import HuggingFaceInstructEmbeddings
from langchain.callbacks import StdOutCallbackHandler
from langchain.llms import OpenAI
from langchain.utilities.sql_database import SQLDatabase

from langchain_experimental.sql.prompt import MYSCALE_PROMPT
from langchain_experimental.sql.vector_sql import VectorSQLDatabaseChain
from langchain_experimental.sql.vector_sql import VectorSQLRetrieveAllOutputParser

# 此解析器将`NeuralArray()`转换为嵌入
output_parser = VectorSQLRetrieveAllOutputParser(
    model=HuggingFaceInstructEmbeddings(model_name='hkunlp/instructor-xl')
)

# 使用上述提示
PROMPT = PromptTemplate(
    input_variables=["input", "table_info", "top_k"],
    template=_prompt,
)

# 将元数据绑定到SqlAlchemy引擎
metadata = MetaData(bind=engine)

# 创建SQLDatabaseChain
query_chain = VectorSQLDatabaseChain.from_llm(
    # GPT-3.5生成更好的有效SQL
    llm=OpenAI(openai_api_key=OPENAI_API_KEY, temperature=0),
    # 使用预定义的提示,根据需要更改
    prompt=PROMPT,
    # 返回前10个相关文档
    top_k=10,
    # 直接使用数据库中的结果
    return_direct=True,
    # 使用我们的数据库进行检索
    db=SQLDatabase(engine, None, metadata),
    # 将`NeuralArray()`转换为嵌入
    sql_cmd_parser=output_parser)

# 启动链!并将所有链调用跟踪到标准输出
query_chain.run("介绍一些在2019年左右发表的使用生成对抗网络的论文。",
                callbacks=[StdOutCallbackHandler()])

# 使用 RetrievalQAwithSourcesChain 进行提问

您还可以将这个VectorSQLDatabaseChain作为检索器使用。您可以将其插入到一些检索QA链中,就像LangChain中的其他检索器一样。

from langchain_experimental.retrievers.vector_sql_database \
    import VectorSQLDatabaseChainRetriever
from langchain.chains.qa_with_sources.map_reduce_prompt import combine_prompt_template

OPENAI_API_KEY = "sk-***"

# 定义如何序列化来自数据库的结构化数据
document_with_metadata_prompt = PromptTemplate(
    input_variables=["page_content", "id", "title", "authors", "pubdate", "categories"],
    template="内容:\n\t标题:{title}\n\t摘要:{page_content}\n\t" +
             "作者:{authors}\n\t出版日期:{pubdate}\n\t类别:{categories}\n来源:{id}"
)
# 定义您用于询问LLM的提示
COMBINE_PROMPT = PromptTemplate(
    template=combine_prompt_template, input_variables=["summaries", "question"])

# 使用SQLDatabaseChain创建一个检索器
retriever = VectorSQLDatabaseChainRetriever(
            sql_db_chain=query_chain, page_content_key="abstract")

# 最后,使用检索器创建一个问答链
ask_chain = RetrievalQAWithSourcesChain.from_chain_type(
    ChatOpenAI(model_name='gpt-3.5-turbo-16k',
                openai_api_key=OPENAI_API_KEY, temperature=0.6),
    retriever=retriever,
    chain_type='stuff',
    chain_type_kwargs={
        'prompt': COMBINE_PROMPT,
        'document_prompt': document_with_metadata_prompt,
    }, return_source_documents=True)

# 运行链!并从LLM获取结果
ask_chain("介绍一些在2019年左右发表的使用生成对抗网络的论文。",
    callbacks=[StdOutCallbackHandler()])

我们还在huggingface (opens new window)上提供了一个实时演示,代码在GitHub (opens new window)上可用!我们使用了自定义的检索QA链 (opens new window)来最大化我们的搜索和提问管道在LangChain中的性能!

# 总结

在现实中,大多数LLM都会产生幻觉。减少其出现的最实际的方法是在问题中添加额外的事实(外部知识)。外部知识对于提高LLM系统的性能至关重要,可以实现高效准确地检索答案。每个词都很重要,您不希望浪费金钱来检索通过不准确的查询获得的未使用的信息。

如何做到?

这就是向量SQL的用武之地,它允许您执行精细粒度的向量搜索,以定位和检索所需的信息。

向量SQL功能强大且易于人和机器学习。您可以使用许多数据类型和函数创建复杂的查询。LLM也喜欢向量SQL,因为它的训练数据集包含许多参考资料。

最后,可以根据不同的嵌入模型将向量SQL转换为许多向量数据库。我们相信这是向量数据库的未来。

对我们正在做的事情感兴趣吗?立即加入我们的discord (opens new window)

Keep Reading
images
使用SQL和MyScale简化文本嵌入

MyScale最近推出了EmbedText函数,这是一个强大的功能,将SQL查询与文本向量化能力集成在一起,将文本转化为数值向量。这些向量有效地将人类感知的语义相似性映射到向量空间中的相似性。使用SQL熟悉的语法,EmbedText简化了向量 ...

images
超越静态管道:使用 LlamaIndex 增强 AI 代理

基本的检索增强生成 (RAG) 数据管道通常依赖于硬编码的步骤,每次运行时都遵循预定义的路径。在这些系统中,没有实时决策,也不会根据输入数据动态调整操作。这种限制可能会降低在复杂或变化环境中的灵活性和响应能力,突显了传统 RAG 系 ...

Start building your Al projects with MyScale today

Free Trial
Contact Us