You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中使用Langchain与OpenSearch多索引查询的问题求助

解决Langchain跨OpenSearch多索引查询问题

问题原因

你当前代码里虽然指定了index_name="index-*"通配符,但默认检索器只会返回Top K个最相关文档(默认k=4),而你需要的是所有文档标题,自然会出现结果不全的情况;另外部分场景下通配符索引的检索逻辑存在限制,可能只返回单个索引的结果。

解决方案

方案1:调整检索器参数,获取足够多的相关文档

通过修改检索器的search_kwargs,设置足够大的k值(覆盖所有文档数量),确保能获取到所有索引中的文档,再让LLM提取标题:

from langchain.vectorstores import OpenSearchVectorSearch
from langchain.chains import ConversationalRetrievalChain
from langchain.embeddings import OpenAIEmbeddings
from langchain.chat_models import ChatOpenAI

embeddings = OpenAIEmbeddings()

def get_llm(model):
    llm = ChatOpenAI(model_name=model.lower(), verbose=False, temperature=0)
    return llm

# 初始化OpenSearch向量存储,使用通配符索引名
docsearch = OpenSearchVectorSearch(
    opensearch_url="http://localhost:9200",
    index_name="index-*",
    embedding_function=embeddings
)

# 创建检索器,设置足够大的k值(根据总文档数调整,比如设为1000)
retriever = docsearch.as_retriever(
    search_kwargs={"k": 1000}
)

chain = ConversationalRetrievalChain.from_llm(
    llm=get_llm("gpt-3.5-turbo"),
    retriever=retriever,
    # 开启原始文档返回,方便调试结果是否完整
    return_source_documents=True
)

result = chain({'question': '列出所有文档的标题,每个标题单独一行', "chat_history": []})
print(result['answer'])
# 调试用:查看返回的原始文档
# print(result['source_documents'])

方案2:手动遍历所有目标索引,合并检索结果

如果通配符索引的检索不稳定,可以手动列出所有index-开头的索引,分别创建向量存储实例,合并所有文档后再提取标题:

from langchain.vectorstores import OpenSearchVectorSearch
from langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings

embeddings = OpenAIEmbeddings()

def get_llm(model):
    llm = ChatOpenAI(model_name=model.lower(), verbose=False, temperature=0)
    return llm

# 手动指定所有目标索引
target_indices = ["index-pdf", "index-html"]  # 根据实际索引名补充
all_documents = []

for idx in target_indices:
    vs = OpenSearchVectorSearch(
        opensearch_url="http://localhost:9200",
        index_name=idx,
        embedding_function=embeddings
    )
    # 获取当前索引的所有文档
    docs = vs.get()["documents"]
    all_documents.extend(docs)

# 让LLM提取并整理所有文档标题
llm = get_llm("gpt-3.5-turbo")
prompt = f"请从以下文档中提取所有文档的标题,每个标题单独一行:\n{[doc.page_content for doc in all_documents]}"
response = llm.predict(prompt)
print(response)

方案3:直接调用OpenSearch API查询元数据

如果文档标题存储在元数据(比如metadata['title'])中,直接通过OpenSearch客户端查询元数据字段,效率更高:

from opensearchpy import OpenSearch
from langchain.chat_models import ChatOpenAI

# 初始化OpenSearch客户端
client = OpenSearch(
    hosts=[{'host': 'localhost', 'port': 9200}],
    http_compress=True,
    use_ssl=False,
    verify_certs=False,
    ssl_show_warn=False
)

# 查询所有index-*索引的文档,提取title元数据
query = {
    "query": {"match_all": {}},
    "_source": ["metadata.title"]  # 假设标题存在于metadata.title字段
}

response = client.search(
    index="index-*",
    body=query,
    size=1000  # 根据总文档数调整
)

# 提取所有标题
titles = [hit['_source']['metadata']['title'] for hit in response['hits']['hits'] if 'title' in hit['_source']['metadata']]

# 让LLM整理输出
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
formatted_response = llm.predict(f"请将以下标题整理成清晰的列表,每个标题单独一行:\n{titles}")
print(formatted_response)

注意事项

  • 如果文档数量极大,方案1和2中的全量获取文档方式可能导致内存占用过高,此时推荐方案3直接查询元数据。
  • 确保OpenSearch集群允许跨索引查询,且所有索引的结构一致(比如元数据字段名相同)。

内容的提问来源于stack exchange,提问作者user2966197

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 19:05:54