LlamaIndex 如何透過 OpenDMA 連接 Alfresco:Reader、Retriever 與智能體工具
Connect LlamaIndex to Alfresco with OpenDMA: Reader, Retriever, and Agent Tools
文章介紹如何透過 OpenDMA 將 LlamaIndex 接入 Alfresco,並提供 AlfrescoReader、AlfrescoRetriever 和 AlfrescoToolSpec 三種整合方式。
Connecting LlamaIndex to Alfresco looks simple at first: read documents, extract text, build an index. In practice, the repository context becomes important very quickly.
At that point there are usually three different tasks that all look similar from a distance:
- ingest Alfresco content into a LlamaIndex
Index, for example aVectorStoreIndex - retrieve content live from Alfresco without building a separate vector store
- give an agent tools to browse Alfresco, inspect metadata, search, and read selected documents
The OpenDMA LlamaIndex integration provides all three surfaces. You can use AlfrescoReader, AlfrescoRetriever, or AlfrescoToolSpec, depending on where the repository should stay in the application flow.
The interesting part is not getting bytes out of Alfresco once. The interesting part is keeping the repository context: site, path, type, aspects, properties, permissions, and the query language the repository already has.
The examples in this article are available as a runnable Python project in the OpenDMA Alfresco–LlamaIndex sample repository. You can clone the repository and follow along with the examples below.
OpenDMA between LlamaIndex and Alfresco
OpenDMA is a vendor-neutral API for Document Management and ECM systems. An OpenDMA adaptor plays a similar role to a database driver: it maps a concrete system like Alfresco to the OpenDMA model.
For a Python LlamaIndex application, the important part is the OpenDMA REST endpoint. The application talks to OpenDMA over HTTP. Behind that endpoint, an Alfresco adaptor maps Alfresco objects, folders, documents, content streams, metadata, classes, aspects, and search into the OpenDMA API.
This keeps the LlamaIndex code at the ECM level. The application does not need to scatter Alfresco Content Services REST API calls for nodes, content download, sites, search, aspects, and properties through its own code.
The same application shape can later be used with other ECM systems through other OpenDMA adaptors, for example Documentum, FileNet P8, OnBase, CMOD, OpenText, or SharePoint. In an enterprise deployment, the OpenDMA or ECI layer is also the place where concerns like auditing, identity translation, RBAC, SIEM integration, or identity forwarding belong.
Use AlfrescoReader when you want to build an index
AlfrescoReader is the LlamaIndex Alfresco reader for ingestion. Use it when you want to load Alfresco content into a LlamaIndex Index, for example a VectorStoreIndex.
It is a convenience reader for Alfresco repositories exposed through OpenDMA. It uses Alfresco defaults and understands Alfresco site short names. The following example reads from the swsdp site of the standard Alfresco sample setup and uses Docling for legacy Word documents:
from llama_index.core import VectorStoreIndex
from llama_index.readers.docling import DoclingReader
from llama_index.readers.opendma import AlfrescoReader
reader = AlfrescoReader(
endpoint="http://localhost:7070/opendma/alf",
username="admin",
password="admin",
sites=["swsdp"],
file_extractor_per_mimetype={
"application/msword": DoclingReader(),
},
)
documents = reader.load_data()
index = VectorStoreIndex.from_documents(documents)
Each returned LlamaIndex Document contains the extracted text in text and OpenDMA metadata in metadata.
The sites parameter is useful for Alfresco, but it is not the only loading strategy. The reader also supports document IDs, folder IDs, recursive folder traversal, and OpenDMA queries. When reading a site, do not assume this only means the Document Library. Alfresco sites can also contain wiki pages, links, and other objects below the site folders.
In a production application, this ingestion step usually should not run over the whole repository every time. The normal shape is to run it for new and changed documents and use a persistent vector store.
Keep the Alfresco metadata
With ECM content, metadata is not decoration. It is often the difference between a demo and a usable application.
Documents loaded through OpenDMA do not only carry text chunks. They also carry OpenDMA metadata, Alfresco metadata, and integration metadata. That includes values such as:
opendma:Titleopendma:CheckedOutalfresco:Sitealfresco:Pathalfresco:cm:namealfresco:cm:creatoralfresco:cm:accessedcontent_state
You can inspect the metadata before inserting documents into an index:
for doc in documents[:3]:
print(doc.id_)
print(doc.metadata.get("opendma:Title"))
print(doc.metadata.get("alfresco:Site"))
print(doc.metadata.get("alfresco:Path"))
This matters because a real Alfresco repository is not a small set of clean tutorial files. It may contain hundreds of thousands or millions of documents, many teams, meeting notes, contracts, agreements, product specifications, working drafts, and project folders with similar vocabulary.
A plain similarity search across all indexed repository content can return irrelevant chunks. If the question is about a particular project or team site, alfresco:Site and alfresco:Path are useful signals. If checked-out content should be excluded, opendma:CheckedOut can be part of the retrieval logic.
The metadata-aware retrieval tutorial shows this more explicitly. It first indexes the Alfresco sample site, then adds similar content from a second site and demonstrates how retrieval quality degrades when all chunks are treated as one flat pool.
Why not just write a small Alfresco REST reader?
For a prototype, a small custom reader is tempting. Download content from Alfresco, turn it into text, and hand it to LlamaIndex.
That works until the reader needs to know more about the repository.
The code quickly grows from "download this node's content" into site discovery, folder traversal, metadata extraction, content type handling, aspects and properties, path reconstruction, checked-out state, full-text search, MIME-specific parsing, and access-control-aware deployment choices.
OpenDMA puts these concerns behind an ECM abstraction. The LlamaIndex application can still be plain Python, but it does not become the place where the Alfresco integration is rebuilt piece by piece.
This also affects content conversion. The OpenDMA reader decodes plain text directly and delegates richer formats to LlamaIndex file readers through MIME-type mappings. In the example above, legacy Word files are explicitly mapped to Docling. Where repository renditions are part of the OpenDMA/adaptor deployment, they belong in the repository integration layer rather than being reimplemented separately in every application.
Use AlfrescoRetriever when you do not want a vector store
Sometimes a vector store is the right choice. If you need semantic retrieval over a curated corpus, AlfrescoReader plus a LlamaIndex index is a good fit.
But building a vector store has a cost. You need to ingest content, extract text, chunk it, calculate embeddings, store the result, and keep it synchronized with Alfresco. In an enterprise repository, access rights and compliance boundaries are often the harder part.
AlfrescoRetriever is the other option. It implements the LlamaIndex retriever API and performs live full-text search against Alfresco through OpenDMA.
from llama_index.core.node_parser import SentenceSplitter
from llama_index.readers.docling import DoclingReader
from llama_index.retrievers.opendma import AlfrescoRetriever
retriever = AlfrescoRetriever(
endpoint="http://localhost:7070/opendma/alf",
username="admin",
password="admin",
sites=["swsdp"],
file_extractor_per_mimetype={
"application/msword": DoclingReader(),
},
transformations=[
SentenceSplitter(chunk_size=1024, chunk_overlap=100),
],
similarity_top_k=8,
)
nodes = retriever.retrieve("meeting notes")
The retriever turns the input string into an Alfresco AFTS TEXT query. If sites is set, it adds site restrictions. The result is converted into LlamaIndex nodes and returned as NodeWithScore.
This is important: AlfrescoRetriever is full-text retrieval, not semantic vector search. The similarity_top_k parameter limits the number of LlamaIndex nodes returned after document loading and node parsing. It is not a vector similarity score.
The advantage is that every retrieval call goes through Alfresco via OpenDMA. There is no up-front ingestion of the whole repository, no embeddings for all content, and no separate copy of repository text that needs to be synchronized.
With effective-user authentication or identity forwarding, Alfresco remains the system deciding what the query can return, including repository permissions and governance/security markings enforced in the Alfresco/OpenDMA path. If the OpenDMA endpoint is called with a shared technical or admin account, the application still has to handle user-level authorization. That part does not disappear.
Agentic retrieval without a vector store
A live full-text retriever works especially well when an agent is allowed to make more than one search attempt.
The first query might be too specific:
localisation of new website design
The next query might use fewer terms:
website design
Or it might focus on the domain word that actually appears in the documents:
localisation
This does not turn Alfresco full-text search into semantic search. A vector store will often retrieve better when the user's words do not match the document text. But an agentic workflow can compensate in many practical cases by changing the query terms and restricting the search to the relevant site.
The Agentic RAG with OpenDMA Retriever tutorial shows this pattern with an agent that uses AlfrescoRetriever inside a search_content tool.
Use AlfrescoToolSpec when the agent needs to browse
AlfrescoRetriever is for retrieval. AlfrescoToolSpec is for agents that need to inspect the repository.
That is a different task. Sometimes the answer is not found by retrieving the best text chunks. The agent may first need to list sites, browse a folder, inspect metadata, find a candidate document, and only then read text from it.
AlfrescoToolSpec exposes tools such as:
alfresco_list_sitesopendma_list_childrenopendma_get_metadataopendma_describe_classopendma_searchopendma_read_text
The tools are configured for a fixed OpenDMA endpoint, account, and repository. This is a better surface for an agent than a generic HTTP client and arbitrary credentials.
from llama_index.core.agent import FunctionAgent
from llama_index.llms.openai import OpenAI
from llama_index.tools.opendma import AlfrescoToolSpec
tool_spec = AlfrescoToolSpec(
endpoint="http://localhost:7070/opendma/alf",
username="admin",
password="admin",
)
agent = FunctionAgent(
name="AlfrescoAgent",
tools=tool_spec.to_tool_list(),
llm=OpenAI(model="gpt-4o-mini"),
system_prompt=(
"Use repository metadata and listings before reading document text. "
"Read document text only when metadata is not enough."
),
)
The prompt matters. Reading document text is more expensive than listing children or getting metadata. A useful agent should browse first, inspect metadata, and read text only when it has a candidate document.
The text-reading tool returns chunks with continuation tokens. That is important for long documents and large repositories. The agent should not request a full document when the metadata already answers the question.
The tool-calling agent tutorial shows this with an agent that first locates a document, inspects metadata, and only reads text when needed.
Choosing the surface
Start with AlfrescoReader if you need semantic search over a controlled indexed corpus.
Start with AlfrescoRetriever if keeping search live in Alfresco is more important than vector similarity.
Use AlfrescoToolSpec when the agent needs repository navigation, metadata inspection, and selective reading.
Try the examples yourself
The complete runnable examples for AlfrescoReader, AlfrescoRetriever, and AlfrescoToolSpec are available in the GitHub sample project.
Clone the repository to experiment with the different integration approaches in your own environment.
For complete runnable flows, see the existing tutorials:
- OpenDMA: https://opendma.org/
- LlamaIndex OpenDMA integration: https://github.com/OpenDMA/llama-index-opendma
- Basic RAG
- Metadata-Aware Retrieval
- Agentic RAG with OpenDMA Retriever
- Tool-Calling Agent with ToolSpec
- Adaptors and ECI Server
In all three cases, the LlamaIndex code works against OpenDMA instead of becoming a custom Alfresco REST integration.
來源:DEV Community · dev.to