[Python] some challenge while try to add document to Azure search

Discussão em 'Python' iniciado por Stack, Março 8, 2025.

  1. Stack

    Stack Membro Participativo

    I'm looking for way to query Azure AI with vector indexing from Confluence DataCenter Server I'm using the following python code

    I'm getting an error

    ERROR - Failed to upload documents to Azure Search: 'dict' object has no attribute 'name'

    the code failed on vector_store.add_documents(split_docs) I review https://python.langchain.com/docs/concepts/vectorstores/ https://python.langchain.com/docs/concepts/text_splitters/

    I understand I need to convert split_docs structure to list, is it the right approach ?

    the structure data is as following

    First document type: <class 'langchain_core.documents.base.Document'>

    First document content: page_content='Be aware: Described steps require manual actions. Already automated actions are removed from below guide. It is also possible that some version skips "Y" part, so then any Y-1 version is X-1.Preparing new Release Candidate (RC,' metadata={'title': 'Managing EBF and RC branches during release - rules and steps for 10.5 line', 'id': '294514485', 'source': 'https://confluencewiki.XXX.com/display/ABC/Managing+EBF+and+RC+branches+during+release+-+rules+and+steps+for+10.5+line', 'when': '2024-08-12T05:06:02.270-07:00'}

    import os
    import logging
    from langchain_community.document_loaders import ConfluenceLoader
    from langchain_openai import AzureOpenAIEmbeddings
    from langchain_community.vectorstores import AzureSearch
    from langchain.text_splitter import RecursiveCharacterTextSplitter
    from langchain.chains import RetrievalQA
    from langchain_openai import AzureChatOpenAI
    from azure.search.documents.indexes import SearchIndexClient
    from azure.core.credentials import AzureKeyCredential
    from langchain_core.documents import Document

    # Set up logging
    logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
    logging.FileHandler("confluence_rag.log"), # Log to a file
    logging.StreamHandler() # Also log to console
    ]
    )
    logger = logging.getLogger(__name__)

    # Configuration
    CONFLUENCE_URL = "https://confluencewiki.XXX.com/" # Base URL of your Confluence Data Center
    CONFLUENCE_USERNAME = "XXZ"
    CONFLUENCE_TOKEN = "X+X" # Use password or personal access token
    CONFLUENCE_SPACE_KEY = "SCAN" # Optional: Specify a space key to limit the scope

    AZURE_SEARCH_ENDPOINT = "https://XXX.search.windows.net"
    AZURE_SEARCH_INDEX_NAME = "confluence-index"
    AZURE_SEARCH_API_KEY = "XXX"

    AZURE_OPENAI_ENDPOINT = "https://XXX.openai.azure.com/"
    AZURE_OPENAI_API_KEY = "XXX"
    AZURE_OPENAI_DEPLOYMENT_NAME = "embeddingmodel"
    AZURE_OPENAI_EMBEDDING_DEPLOYMENT = "embeddingmodel" # Embedding deployment name

    # Initialize Azure OpenAI Embeddings
    logger.info(f"Initializing Azure OpenAI Embeddings with deployment: {AZURE_OPENAI_EMBEDDING_DEPLOYMENT}")
    try:
    embeddings = AzureOpenAIEmbeddings(
    azure_endpoint=AZURE_OPENAI_ENDPOINT,
    api_key=AZURE_OPENAI_API_KEY,
    deployment=AZURE_OPENAI_EMBEDDING_DEPLOYMENT,
    api_version="2023-05-15",
    )
    test_embedding = embeddings.embed_query("Test sentence")
    logger.info(f"Embedding test successful: {len(test_embedding)} dimensions")
    except Exception as e:
    logger.error(f"Failed to initialize Azure OpenAI Embeddings: {e}")
    raise

    # Initialize Azure OpenAI Chat Model
    logger.info(f"Initializing Azure OpenAI Chat Model with deployment: {AZURE_OPENAI_DEPLOYMENT_NAME}")
    try:
    llm = AzureChatOpenAI(
    azure_endpoint=AZURE_OPENAI_ENDPOINT,
    api_key=AZURE_OPENAI_API_KEY,
    deployment_name=AZURE_OPENAI_DEPLOYMENT_NAME,
    api_version="2023-05-15",
    temperature=0.7,
    )
    except Exception as e:
    logger.error(f"Failed to initialize Azure OpenAI Chat Model: {e}")
    raise

    # Step 1: Load Confluence Data
    logger.info(f"Loading Confluence data from space: {CONFLUENCE_SPACE_KEY}")
    loader = ConfluenceLoader(
    url=CONFLUENCE_URL,
    token=CONFLUENCE_TOKEN,
    cloud=False,
    space_key=CONFLUENCE_SPACE_KEY,
    limit=100,
    )
    try:
    documents = loader.load()
    logger.info(f"Loaded {len(documents)} documents from Confluence")
    except Exception as e:
    logger.error(f"Failed to load Confluence data: {e}")
    raise


    # Step 2: Split Documents
    logger.info("Splitting documents into chunks")
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
    split_docs = text_splitter.split_documents(documents)
    logger.info(f"Split into {len(split_docs)} chunks")
    logger.info(f"First split_doc: {split_docs[0].page_content}, Metadata: {split_docs[0].metadata}")

    # Test Azure Search Connection
    logger.info("Testing Azure Search connection")
    try:
    credential = AzureKeyCredential(AZURE_SEARCH_API_KEY)
    index_client = SearchIndexClient(endpoint=AZURE_SEARCH_ENDPOINT, credential=credential)
    index_client.get_service_statistics()
    logger.info("Azure Search connection successful")
    except Exception as e:
    logger.error(f"Azure Search connection failed: {e}")
    raise

    # Step 3: Initialize Azure Search Vector Store
    logger.info(f"Initializing Azure Search Vector Store with index: {AZURE_SEARCH_INDEX_NAME}")
    try:
    vector_store = AzureSearch(
    azure_search_endpoint=AZURE_SEARCH_ENDPOINT,
    azure_search_key=AZURE_SEARCH_API_KEY,
    index_name=AZURE_SEARCH_INDEX_NAME,
    embedding_function=embeddings.embed_query,
    fields=[
    {"name": "id", "type": "Edm.String", "key": True},
    {"name": "title", "type": "Edm.String", "searchable": True, "filterable": True},
    {"name": "content", "type": "Edm.String", "searchable": True},
    {
    "name": "embedding",
    "type": "Collection(Edm.Single)",
    "searchable": True,
    "vectorSearchDimensions": 1536,
    "vectorSearchConfiguration": "my-vector-profile",
    },
    ],
    vector_search_configuration={
    "vectorSearches": [
    {
    "profiles": [
    {"name": "my-vector-profile", "algorithmConfigurationName": "my-hnsw-config"}
    ],
    "algorithms": [
    {"name": "my-hnsw-config", "kind": "hnsw"}
    ],
    }
    ]
    }
    )
    except Exception as e:
    logger.error(f"Failed to initialize Azure Search Vector Store: {e}")
    logger.debug(f"Endpoint: {AZURE_SEARCH_ENDPOINT}, Index: {AZURE_SEARCH_INDEX_NAME}")
    raise

    # Step 4: Add Documents to Azure Search
    logger.info("Uploading documents to Azure Search")
    logger.info(f"First document type: {type(split_docs[0])}")
    logger.info(f"First document content: {split_docs[0]}")
    logger.info(f"First loaded document type: {type(documents[0])}")
    logger.info(f"First loaded document content: {documents[0]}")


    try:
    vector_store.add_documents(split_docs)
    logger.info(f"Uploaded {len(split_docs)} documents to Azure Search")
    except Exception as e:
    logger.error(f"Failed to upload documents to Azure Search: {e}")
    raise

    # Step 5: Set up RetrievalQA Chain
    logger.info("Setting up RetrievalQA chain")
    retriever = vector_store.as_retriever(search_kwargs={"k": 5})
    qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=retriever,
    return_source_documents=True,
    )

    # Step 6: Query the System
    def query_confluence(user_query):
    logger.info(f"Querying Confluence with: {user_query}")
    try:
    result = qa_chain({"query": user_query})
    logger.info("Query completed successfully")
    return result["result"], result["source_documents"]
    except Exception as e:
    logger.error(f"Query failed: {e}")
    raise

    # Example Usage
    if __name__ == "__main__":
    user_query = "Please point out the most important data from IT space?"
    logger.debug(f"Starting main execution with query: {user_query}")
    answer, sources = query_confluence(user_query)
    logger.info("Answer generated:")
    print("Answer:", answer)
    print("\nSources:")
    for doc in sources:
    logger.info(f"Source: {doc.metadata['title']} (ID: {doc.metadata['id']})")
    print(f"- {doc.metadata['title']} (ID: {doc.metadata['id']})")

    Continue reading...

Compartilhe esta Página