在 Elasticsearch 中使用 Mistral Chat completions 进行上下文工程

作者:来自 Elastic Ugo Sangiorgi

学习如何在 Elasticsearch 中使用 Mistral Chat completions 进行上下文工程,将 LLM 响应基于特定领域知识,从而获得准确的输出。

测试 Elastic 领先的开箱即用功能。深入了解我们的示例笔记本,开始免费的云试用,或立即在本地机器上体验 Elastic。


使用 Elasticsearch 进行上下文工程非常简单,我们将通过 Mistral Chat completions 来演示这一点。

从滑板上投掷石斧

我清楚地记得自己玩过《Super Adventure Island》------一款超级任天堂游戏,主角是一个骑着滑板、向敌人投掷石斧的原始人。然而,到我写这篇文章时,我问过的所有 LLMs 都没能告诉我这款游戏是什么。在这篇博客中,我将向你展示如何通过一些上下文工程来影响 LLMs。

为什么这很重要?企业常常需要处理复杂的特定领域知识 ------ 产品目录、内部文档、法规或客户支持数据。开箱即用的 LLMs 可能会给出泛泛的回答。通过应用上下文工程(Context Engineering ),你可以确保模型的响应基于公司自身的数据,从而提高可靠性和信任度。当然,这对视频游戏标题也同样有效。

情境化上下文工程

我们可以将上下文概括为一组属性,用于倾斜或影响传递给 LLM 的数据,以使其响应更有依据。因此,上下文工 程被认为是精心设计、构建和选择这些上下文属性的实践,以便让 LLM 生成更准确、更相关或与特定目标更一致的输出。

正如 Dexter Horthy 在他的 "12-Factor Agents" 原则中的第三条中指出的那样,掌握自己的上下文对于确保 LLM 生成最佳输出至关重要。

它实际上是提示设计、数据整理和系统指令微调的结合 ,旨在在不修改模型底层参数的情况下控制其行为

在 Elasticsearch 中使用 Mistral Chat completions

你可以在 mistral-chat-completions.ipynb 笔记本中运行以下所有代码。我们将向 Mistral 询问 90 年代的超级任天堂游戏,然后尝试让它的回答偏向提及一款非常受欢迎的游戏 ------ Super Adventure Island。

安装 Elasticsearch

可以通过创建云部署(说明见此处)或在 Docker 中运行(说明见此处)来启动并运行 Elasticsearch。你也可以参照文章 "如何在 Linux,MacOS 及 Windows 上进行安装 Elasticsearch" 来进行安装。

假设你使用的是云部署,请按照说明获取该部署的 API Key 和 Elasticsearch 主机。我们稍后会用到它们。

获取 Mistral API 密钥

要从 Elasticsearch 调用 Mistral 模型,你需要:

  • 一个 Mistral 账号(La Plateforme / 控制台)。

  • 控制台中创建的 API 密钥(密钥只显示一次------请复制并安全保存)。

Mistral 还宣布了免费的 API 等级和价格调整,因此通常有免费或低成本的方式开始使用。

测试

我们可以使用 Dev Tools 来测试 _inference 端点创建和 _stream API。可以像下面这样创建推理端点:

bash 复制代码
`

1.  PUT _inference/chat_completion/mistral-embeddings-chat-completion
2.  {
3.    "service": "mistral",
4.    "task_type": "chat_completion",
5.    "service_settings": {
6.      "api_key": "--yourmistralapikey--",
7.      "model": "mistral-large-latest" 
8.    }
9.  }

`AI写代码

现在我们来向 Mistral 询问 90 年代的超级任天堂游戏,但选择一款并不流行的游戏。有一款名为 Super Adventure Island 的游戏,主角骑着滑板并投掷石斧。我们将使用 _inference/chat_completion API 来流式获取响应。

bash 复制代码
`

1.  POST _inference/chat_completion/mistral-embeddings-chat-completion/_stream
2.  {
3.    "messages": [
4.      {
5.        "role": "system",
6.        "content": "You are a helpful gaming expert that provides concise answers about video games."
7.      },
8.      {
9.        "role": "user",
10.        "content": "What SNES games had a character on a skateboard throwing stone axes?"
11.      }
12.    ]
13.  }

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

不出所料,回答中不会提到 Super Adventure Island,因为它并不是一款流行的游戏;相反,Mistral 会回答像 Joe & Mac 这样的游戏(有石斧但没有滑板),并告诉你没有一款同时具备这两个元素的游戏。注意:这不一定是 Mistral 的问题,因为我们测试的其他 LLM 也没有给出正确的答案。

响应结构如下:

  • event:发送的事件类型(此处始终为 "message")。

  • data:包含实际响应片段的 JSON 负载。

markdown 复制代码
`

1.  event: message
2.  data: {
3.    "id" : "8135d95c85b4475e8099b8e9aab42315",
4.    "choices" : [
5.      {
6.        "delta" : {
7.          "content" : "There's one",
8.          "role" : "assistant"
9.        },
10.        "index" : 0
11.      }
12.    ],
13.    "model" : "mistral-large-latest",
14.    "object" : "chat.completion.chunk"
15.  }

18.  event: message
19.  data: {
20.    "id" : "8135d95c85b4475e8099b8e9aab42315",
21.    "choices" : [
22.      {
23.        "delta" : {
24.          "content" : "notable SNES game"
25.        },
26.        "index" : 0
27.      }
28.    ],
29.    "model" : "mistral-large-latest",
30.    "object" : "chat.completion.chunk"
31.  }

34.  event: message
35.  data: {
36.    "id" : "8135d95c85b4475e8099b8e9aab42315",
37.    "choices" : [
38.      {
39.        "delta" : {
40.          "content" : "but without"
41.        },
42.        "index" : 0
43.      }
44.    ],
45.    "model" : "mistral-large-latest",
46.    "object" : "chat.completion.chunk"
47.  }
48.  ...

50.  event: message
51.  data: {
52.    "id" : "8135d95c85b4475e8099b8e9aab42315",
53.    "choices" : [
54.      {
55.        "delta" : {
56.          "content" : " match."
57.        },
58.        "finish_reason" : "stop",
59.        "index" : 0
60.      }
61.    ],
62.    "model" : "mistral-large-latest",
63.    "object" : "chat.completion.chunk",
64.    "usage" : {
65.      "completion_tokens" : 100,
66.      "prompt_tokens" : 34,
67.      "total_tokens" : 134
68.    }
69.  }

72.  event: message
73.  data: [DONE]

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)收起代码块![](https://csdnimg.cn/release/blogv2/dist/pc/img/arrowup-line-top-White.png)

请注意,最终的对象还包含诸如 finish_reason 和 usage 之类的元数据。我们的笔记本会负责解析这个结构,并将其显示为聊天文本的形式。

运行示例

首先,你需要在 mistral-chat-completions.ipynb 笔记本中设置 ELASTICSEARCH_HOST、ELASTICSEARCH_API_KEY 和 MISTRAL_API_KEY 这几个凭证。

ini 复制代码
`

1.  # Credentials - Enter your API keys securely
2.  ELASTICSEARCH_URL = getpass.getpass("Enter your Elasticsearch URL: ").strip()
3.  ELASTICSEARCH_API_KEY = getpass.getpass("Enter your Elasticsearch API key: ")
4.  MISTRAL_API_KEY = getpass.getpass("Enter your Mistral API key: ")

`AI写代码

我们使用的模型是 mistral-large-latest,在 MISTRAL_MODEL 中设置 ------ 可用模型列表可在 Mistral 的 Models Overview 中找到。

ini 复制代码
`

1.  # Configurations, no need to change these values
2.  MISTRAL_MODEL = "mistral-large-latest"  
3.  INFERENCE_ENDPOINT_NAME = (
4.      "mistral-embeddings-chat-completion"
5.  )

`AI写代码

笔记本中有用于向 Elasticsearch 发送请求、解析响应并在控制台流式显示的代码。现在让我们使用 Python 再次提出问题。

bash 复制代码
`

1.  user_question = "What SNES games had a character on a skateboard and stone axes?"

3.  messages = [
4.      {"role": "system", "content": "You are a helpful gaming expert that provides concise answers about video games."},
5.      {"role": "user", "content": user_question}
6.      ]

8.  print(f"User: {user_question}")
9.  print("Assistant: \n")

11.  for chunk in stream_chat_completion(ELASTICSEARCH_URL, INFERENCE_ENDPOINT_NAME, messages):
12.      print(chunk, end="", flush=True)

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

在 Elasticsearch 中为 Mistral 进行上下文工程

在笔记本中,我们有一个名为 snes_games.csv 的数据集,包含所有 1700 多款超级任天堂游戏的信息,包括标题、发行商、类别、在美国和日本的发行年份以及简短描述 ------ 这将作为我们的内部数据库,我们将像下面这样将其索引到 Elasticsearch:

bash 复制代码
`

1.  INDEX_NAME = "snes-games"
2.  snes_mapping = {
3.      "mappings": {
4.          "properties": {
5.              "id": {"type": "keyword"},
6.              "title": {"type": "text", "copy_to": "description_semantic"},
7.              "publishers": {"type": "keyword"},
8.              "year_US": {"type": "keyword"},
9.              "year_JP": {"type": "keyword"},
10.              "category": {"type": "keyword", "copy_to": "description_semantic"},
11.              "description": {"type": "text", "copy_to": "description_semantic"},
12.              "description_semantic": {"type": "semantic_text"}
13.          }
14.      }
15.  }

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

注意,我们将 title、category 和 description 字段复制到 description_semantic(类型为 semantic_text);这就是生成字段稀疏向量嵌入所需的全部内容,无需单独的嵌入模型或复杂的向量操作 ------ 它使用 ELSER。

语义搜索

一旦我们索引了数据集(详细信息请参见笔记本),就可以在索引上进行搜索。有很多方法可以将词汇搜索与语义搜索(semantic search)结合起来,但在此示例中,我们将仅使用 description_semantic 字段来发起语义搜索查询:

json 复制代码
`

1.  search_body = {
2.          "size": max_results,
3.          "query": {
4.              "semantic": {
5.              "field": "description_semantic",
6.              "query": query
7.              }
8.          }
9.      }

`AI写代码

初步结果令人鼓舞;同样的查询 "What SNES games had a character on a skateboard throwing axes?" 成功识别了我们要找的游戏,包括之前我不知道的 Super Adventure Island II(在日本名为 高橋名人の大冒険島II)!

vbnet 复制代码
`

1.  Searching for: 'What SNES games had a character on a skateboard throwing axes?'

3.  1. Super Adventure Island II•Takahashi Meijin no Daibouken Jima II - In Adventure Island II, Master Higgins keeps his stone axe and skateboard but also gains the help of four dinosaur companions, each with unique abilities on land, sea, or air. Players collect fruit to stay alive, find eggs for power-ups, and ride dinos to tackle tougher stages with new variety. (Score: 19.44)

5.  2. Super Adventure Island•Takahashi Meijin no Daibouken Jima - In this Adventure Island entry, Master Higgins wields either his classic stone axe or a boomerang, with fireballs as power-ups. He can super-jump, but no longer runs faster like in the NES. Higgins must collect fruit to survive, and can ride a skateboard to speed through stages. (Score: 19.14)

7.  3. Frogger - Frogger is a classic arcade game brought to the SNES by Morning Star Multimedia and Majesco Entertainment. Players guide a frog across busy roads and rivers, avoiding obstacles to reach safety. (Score: 10.63)

9.  4. Kikuni Masahiko no Jantoushi Dora Ou 2 - Board game (Score: 9.58)

11.  5. Kindai Mahjong Special - Board game (Score: 9.58)

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

现在我们拥有更多的领域知识,可以将这些数据提供给 Mistral,帮助它生成更好的响应,但又不会完全取代 Mistral 的推理能力。

RAG 聊天作为上下文工程的一部分

这里有一个简单的 RAG 增强函数,用于在上下文中包含我们的搜索结果(完整文档的 _source):

ini 复制代码
`

1.  def rag_chat(user_question: str, max_context_docs: int = 10) -> str:
2.      context_docs = search_documents(user_question, max_context_docs)

4.      context_text = ""
5.      if context_docs:
6.          context_text = "\n\nRelevant context information:\n"
7.          for i, doc in enumerate(context_docs, 1):
8.              context_text += f"\n{i}. {doc['_source']}\n"

10.      system_prompt = """
11.          You are a helpful assistant that answers about Super Nintendo games. 
12.          Use the provided context information to answer the user's question accurately. 
13.          If the context doesn't contain relevant information, you can use your general knowledge mixed with the context, 
14.          Treat the context as your general knowledge in the answer"""

16.      user_prompt = user_question
17.      if context_text:
18.          user_prompt = f"{context_text}\n\nQuestion: {user_question}"

20.      messages = [
21.          {"role": "system", "content": system_prompt},
22.          {"role": "user", "content": user_prompt}
23.      ]

25.      full_response = ""
26.      for chunk in stream_chat_completion(ELASTICSEARCH_URL, INFERENCE_ENDPOINT_NAME, messages):
27.          print(chunk, end="", flush=True)
28.          full_response += chunk

30.      return full_response

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

再次提问时,我们得到的响应更加简明且有依据:

markdown 复制代码
`

1.  Based on the provided context, the **Super Adventure Island** series on the SNES features a character (Master Higgins) who uses a **skateboard** and **axes**:

3.  1. **Super Adventure Island (1992)** – Master Higgins wields a **stone axe** (or boomerang) and can ride a **skateboard** to speed through stages.
4.  2. **Super Adventure Island II (1995)** – Master Higgins keeps his **stone axe** and **skateboard**, while also gaining dinosaur companions for additional abilities.

6.  These are the only SNES games in the given context that match your description.

`AI写代码

结论

我们已经涵盖了大部分上下文工程,包括用户提示、指令/系统提示和 RAG,但这个示例也可以扩展以包含短期和长期记忆,因为它们可以轻松地表示为 Elasticsearch 中单独索引的文档。

了解更多本博客中介绍的内容:

原文:www.elastic.co/search-labs...

相关推荐
Elasticsearch6 小时前
实时日志与繁荣:修复可观测性中的一个根本性缺陷
elasticsearch
Elastic 中国社区官方博客17 小时前
Elasticsearch 开放推理 API 增加了对 Google 的 Gemini 模型的支持
大数据·人工智能·elasticsearch·搜索引擎·ai·全文检索·googlecloud
rit843249918 小时前
Git常用命令的详细指南
大数据·git·elasticsearch
亚林瓜子18 小时前
AWS OpenSearch(ES)启用慢速日志
elasticsearch·性能调优·aws·log·opensearch·日志组
我要升天!19 小时前
Git的原理与使用 -- 分支管理
大数据·git·elasticsearch
阿里云大数据AI技术1 天前
云栖实录 | 阿里云发布Elasticsearch Serverless 2.0,重塑AI搜索时代基础设施
elasticsearch·搜索引擎
梁萌1 天前
在linux上使用docker搭建ELK日志框架
elk·elasticsearch·docker·kibana·logstash·日志框架
yangmf20401 天前
如何使用 INFINI Gateway 增量迁移 ES 数据
大数据·数据库·elasticsearch·搜索引擎·gateway