LlamaIndex 系列【15】对话引擎(Chat Engine)
1. 概述
对话引擎是面向基于自有数据进行多轮对话的高层接口(支持来回多轮交互,而非单次问答)。你可以理解为接入了自有知识库的 ChatGPT。
从概念上来说,它是有状态的查询引擎(Query Engine)。对话引擎会维护对话历史,能够结合前文上下文回答用户问题。
💡提示
如果你只需要基于数据进行独立单次提问(不需要保存对话历史),请直接使用[查询引擎])。
2. 入门案例
2.1 构建索引
这块我们在之前已经学习过了,直接贴代码:
import os
from dotenv import load_dotenv
from llama_index.core import SimpleDirectoryReader, VectorStoreIndex, StorageContext
from llama_index.core.vector_stores import SimpleVectorStore
from llama_index.embeddings.openai_like import OpenAILikeEmbedding
load_dotenv()
embed_model = OpenAILikeEmbedding(
model_name="text-embedding-v3",
api_key=os.environ["DASHSCOPE_API_KEY"],
api_base="https://ws-jfb8j8mx0n7e2k6a.cn-beijing.maas.aliyuncs.com/compatible-mode/v1",
)
# 读取 ./data 目录下的全部文件,自动按扩展名选择解析器
reader = SimpleDirectoryReader(
input_dir="./data",
raise_on_error=True,
)
documents = reader.load_data(show_progress=True)
store = SimpleVectorStore()
storage_context = StorageContext.from_defaults(vector_store=store)
# 快速构建:解析、分块、向量化、建索引一步完成
index = VectorStoreIndex.from_documents(
documents,
storage_context=storage_context,
embed_model=embed_model, # 局部指定向量模型;不传则回退到 Settings.embed_model
show_progress=True,
)
# 检查索引状态
print(f"文档数: {len(documents)}")
print(f"节点数(分块后): {len(index.docstore.docs)}")
for ref_doc_id, info in index.ref_doc_info.items():
print(f" {info.metadata.get('file_name')}: {len(info.node_ids)} 个节点")
2.2 构建对话引擎
新建 chat_test.py 配置大模型、嵌入模型,通过本地文件加载索引,构建对话引擎:
import os
from dotenv import load_dotenv
from llama_index.core import Settings, StorageContext, load_index_from_storage
from llama_index.embeddings.openai_like import OpenAILikeEmbedding
from llama_index.llms.openai_like import OpenAILike
load_dotenv()
api_key = os.environ["DASHSCOPE_API_KEY"]
API_BASE = "https://ws-jfb8j8mx0n7e2k6a.cn-beijing.maas.aliyuncs.com/compatible-mode/v1"
# 对话引擎需要 LLM
Settings.llm = OpenAILike(
model="qwen-plus", # 百炼对话模型,可按需换 qwen-max / qwen-turbo / qwen-long
api_key=api_key,
api_base=API_BASE,
is_chat_model=True,
)
# 检索阶段需要 embedding,同样显式配置
Settings.embed_model = OpenAILikeEmbedding(
model_name="text-embedding-v3",
api_key=api_key,
api_base=API_BASE,
)
# 从持久目录加载索引(VectorStoreIndex(storage_context=...) 不会载入索引结构)
storage_context = StorageContext.from_defaults(persist_dir="./storage")
index = load_index_from_storage(storage_context)
# 构建对话引擎
chat_engine = index.as_chat_engine()
2.3 对话测试
文档内容:

发起对话:
response = chat_engine.chat("星云科技哪一年成立")
print(response)
正确输出:

3. 进阶使用
3.1 快速上手
从索引构建对话引擎:
chat_engine = index.as_chat_engine()
基于自有数据开启对话:
response = chat_engine.chat("Tell me a joke.")
清空对话历史,开启新一轮对话:
chat_engine.reset()
启动交互式对话终端(REPL):
chat_engine.chat_repl()
3.2 高层 API
一行代码直接基于索引构建并配置对话引擎:
chat_engine = index.as_chat_engine(chat_mode="condense_question", verbose=True)
📌 通过入参 chat_mode 可以切换不同类型的对话引擎:
condense_question对应CondenseQuestionChatEngine;react对应ReActChatEngine;context对应ContextChatEngine。
📌 说明:高层
API主打易用性,但不会暴露全部可配置项。
可选对话模式:
best:将查询引擎封装为工具,根据大模型能力自动选用ReAct数据智能体 或OpenAI数据智能体。OpenAI智能体需要gpt-3.5-turbo/gpt-4,依赖OpenAI的函数调用接口。condense_question:读取对话历史,把用户后续提问重写为适配索引检索的独立查询;再调用查询引擎获取结果并回复。context:每一轮用户消息都从索引中召回节点,将召回文本填入系统提示词,让大模型结合检索上下文自然回答。condense_plus_context:结合condense_question和context两种能力。读取对话历史,把用户问题重写为检索query,召回文本后填入系统提示词,大模型结合上下文回答。simple:直接和大模型对话,不使用查询引擎、不检索知识库。react:和best逻辑一致,但强制使用ReAct数据智能体。openai:和best逻辑一致,但强制使用OpenAI数据智能体。
3.3 底层组合API
如果你需要更精细化的自定义能力,可以使用底层组合 API。直白来说:不再调用 index.as_chat_engine(...),而是手动显式实例化 ChatEngine 对象。
📌 提示:该用法建议配合
API文档或示例Notebook学习。
下面示例实现这些自定义能力:
- 自定义问题精简提示词
- 预置初始对话历史
- 开启调试日志输出
from llama_index.core import PromptTemplate
from llama_index.core.llms import ChatMessage, MessageRole
from llama_index.core.chat_engine import CondenseQuestionChatEngine
custom_prompt = PromptTemplate(
"""\
给定一段人机对话历史,以及用户的后续问题,请将该问题重写为独立完整的问题,
需要包含对话里所有相关上下文信息。
<对话历史>
{chat_history}
<用户后续问题>
{question}
<独立完整问题>
"""
)
# ChatMessage 对象列表,预置历史对话
custom_chat_history = [
ChatMessage(
role=MessageRole.USER,
content="助手你好,我们今天正在深入讨论Paul Graham相关内容。",
),
ChatMessage(role=MessageRole.ASSISTANT, content="好的,我们开始。"),
]
query_engine = index.as_query_engine()
chat_engine = CondenseQuestionChatEngine.from_defaults(
query_engine=query_engine,
condense_question_prompt=custom_prompt,
chat_history=custom_chat_history,
verbose=True,
)
3.4 流式输出
想要开启流式返回,直接调用 stream_chat 方法,替代普通的 chat 方法。
⚠️ 注意:该设计和查询引擎不完全统一(查询引擎是通过
streaming=True参数开启),官方正在优化行为一致性!
同步流式(stream_chat):
chat_engine = index.as_chat_engine()
streaming_response = chat_engine.stream_chat("Tell me a joke.")
for token in streaming_response.response_gen:
print(token, end="")
异步流式(astream_chat):
chat_engine = index.as_chat_engine()
streaming_response = await chat_engine.astream_chat("Tell me a joke.")
async for token in streaming_response.async_response_gen():
print(token, end="")
如果使用
FastAPI等异步框架,请使用astream_chat。注意需要使用await调用,并遍历异步流式接口(如async_response_gen())。
完整端到端教程:流式响应示例
4. 官方示例
我们先提供几个简易实现,后续会推出更复杂高级的模式!
简单说明:
SimpleChatEngine不会使用知识库;其余所有对话引擎都会依托查询引擎来使用知识库。
更多推荐


所有评论(0)