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

向Azure Cognitive Search添加嵌入时出现'str'无page_content属性错误

问题原因

你遇到的AttributeError: 'str' object has no attribute 'page_content'是因为LangChain的AzureSearch.add_documents()方法要求传入LangChain Document对象的列表,但你传的是纯字符串列表。Document对象必须包含page_content(文本内容)和metadata(元数据,比如文件名)两个属性,字符串显然没有这些属性。

另外你的代码还有两个坑:

  • 每页循环时重复把page_content加到doc_content里,会导致文本重复(比如第一页内容加一次,第二页加第一页+第二页,以此类推)
  • 没给文本块绑定文件名元数据,不符合你“上传带filename的嵌入”的需求
解决步骤

1. 导入LangChain的Document类

先从langchain.schema里导入Document,用来包装文本和元数据。

2. 修复文本提取逻辑

每个文件单独初始化文本变量,遍历完所有页面后再提取完整文本,避免重复累加。

3. 把分割后的字符串转成Document对象

给每个文本块套上Document,同时把当前文件名作为元数据传进去。

4. 正确调用add_documents

传入Document对象列表,而不是纯字符串。

修改后的完整代码

关键修改处已标注:

!pip install cohere tiktoken
!pip install openai==0.28.1
!pip install pymupdf
!pip install azure-storage-blob azure-identity
!pip install azure-search-documents --pre --upgrade
!pip install langchain

import fitz
import time
import uuid
import os
import openai

from PIL import Image
from io import BytesIO
from IPython.display import display

from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient

from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter

from langchain.chat_models import AzureChatOpenAI
from langchain.vectorstores import AzureSearch
from langchain.document_loaders import DirectoryLoader
from langchain.document_loaders import TextLoader
from langchain.text_splitter import TokenTextSplitter
from langchain.chains import ConversationalRetrievalChain
from langchain.prompts import PromptTemplate
# 新增:导入Document类,用来封装文本和元数据
from langchain.schema import Document

from google.colab import drive

OPENAI_API_BASE = "https://xxx.openai.azure.com"
OPENAI_API_KEY = "xxx"
OPENAI_API_VERSION = "2023-05-15"

openai.api_type = "azure"
openai.api_key = OPENAI_API_KEY
openai.api_base = OPENAI_API_BASE
openai.api_version = OPENAI_API_VERSION

AZURE_COGNITIVE_SEARCH_SERVICE_NAME = "https://xxx.search.windows.net"
AZURE_COGNITIVE_SEARCH_API_KEY = "xxx"
AZURE_COGNITIVE_SEARCH_INDEX_NAME = "test"

llm = AzureChatOpenAI(deployment_name="gpt35", openai_api_key=OPENAI_API_KEY, openai_api_base=OPENAI_API_BASE, openai_api_version=OPENAI_API_VERSION)
embeddings = OpenAIEmbeddings(deployment_id="ada002", chunk_size=1, openai_api_key=OPENAI_API_KEY, openai_api_base=OPENAI_API_BASE, openai_api_version=OPENAI_API_VERSION)

acs = AzureSearch(azure_search_endpoint=AZURE_COGNITIVE_SEARCH_SERVICE_NAME,
                  azure_search_key = AZURE_COGNITIVE_SEARCH_API_KEY,
                  index_name = AZURE_COGNITIVE_SEARCH_INDEX_NAME,
                  embedding_function = embeddings.embed_query)
    
def generate_tokens(s):
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
  splits = text_splitter.split_text(s)

  return splits

drive.mount('/content/drive')
folder = "/content/drive/.../pdf/"

# 移除全局的page_content和doc_content,每个文件单独处理
for filename in os.listdir(folder):
    file_path = os.path.join(folder, filename)
    if os.path.isfile(file_path):
        print(f"Processing file: {file_path}")

        doc = fitz.open(file_path)
        doc_content = ''  # 每个文件初始化一次文本变量
        for page in doc: # 遍历所有页面,提取完整文本
          doc_content += page.get_text()

        # 分割文本为块
        text_chunks = generate_tokens(doc_content)
        
        # 将每个文本块转为Document对象,绑定文件名元数据
        documents = [
            Document(page_content=chunk, metadata={"filename": filename}) 
            for chunk in text_chunks
        ]

        # 上传到Azure Cognitive Search
        acs.add_documents(documents=documents)
    
        print(f"文件 {filename} 处理完成,共分割为 {len(documents)} 个文本块")
        word_count = len(doc_content.split())
        print(f"文本单词总数: {word_count}")
        print("----------")
关键修改说明
  1. 导入Document类:必须用这个类来封装文本和元数据,LangChain的向量存储方法只认这个格式。
  2. 修复文本累加:每个文件单独初始化doc_content,遍历完所有页面后一次性提取,避免文本重复。
  3. 添加元数据:把文件名作为metadata传入Document,这样后续查询时能知道结果来自哪个文件。
  4. 正确传入参数:add_documents现在接收的是Document对象列表,符合方法要求,不会再触发属性错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:44:50