附註:
- 此教學課程需要存取 Oracle Cloud。若要註冊免費帳戶,請參閱開始使用 Oracle Cloud Infrastructure Free Tier 。
- 其使用 Oracle Cloud Infrastructure 證明資料、租用戶以及區間的範例值。完成實驗室時,請將這些值替代為雲端環境特定的值。
使用多代理程式通訊協定伺服器建置 AI 代理程式以進行發票解析
簡介
處理大量產品 (例如經銷商、產業及零售連鎖店) 的公司通常會面臨根據不準確、不完整或各種文字描述來識別產品的挑戰。在手動輸入資料的環境中,打字、縮寫和不同的交易名稱可能會難以正確識別系統中的項目,例如企業資源規劃 (ERP)、客戶關係管理 (CRM) 和電子商務平台。
在此案例中,工具有常見的需求可以:
-
解譯使用者提供的非正式或不正確的描述。
-
根據語意相似度建議最相似的產品。
-
如果語意搜尋找不到相關結果,則保證使用傳統演算法 (例如模糊比對) 進行備用。
-
與智慧代理的 API 和自動化流程整合。
在本教學課程中,我們將瞭解如何建立一個 AI 代理,專門用於解決客戶退貨發票中的不一致問題。專員能夠與提供向量搜尋和發票擷取工具的 MCP 伺服器互動,讓專員能夠根據客戶提供的資訊自動尋找公司的原始應收帳款發票。
MCP 伺服器 (模型相關資訊環境協定) 是一種軟體元件,負責透過標準化的訊息和工具協定,調解智慧型代理程式與外部服務之間的通訊。它作為語言模型 (LLM) 與現有 API 之間的橋接器,可讓 AI 代理程式存取舊有系統的特定功能,而不需要重新寫入或直接調整這些功能。
如何運作?
MCP 伺服器:
- 顯示一組代表動作或服務專員可呼叫的具名工具。
- 每個工具都可以連線至資料庫功能、REST API、傳統系統或任何可程式化的作業。
- 接收代理程式命令 (JSON 格式)、執行對應的服務,以及傳回標準化回應。
使用舊版應用程式
傳統應用程式通常已透過資料庫、檔案或內部 API 提供功能。使用 MCP 伺服器,您可以:
-
封裝對 REST 服務、預存程序或 SQL 查詢的呼叫。
-
讓代理程式可透過統一通訊介面存取這些服務。
-
將舊系統與以對話式 AI 和 RAG 為基礎的現代化架構整合。
優點
-
重複使用現有的業務邏輯。
-
不需要重製傳統系統。
-
讓 LLM 代理程式以安全且受控制的方式與外部系統互動。
-
促進 AI 與後端服務之間的整合測試、啟動多版本功能及模組化。
此代理程式是以 Oracle Cloud Infrastructure (OCI) Generative AI 語言模型為基礎,並與 MCP 伺服器所管理的動態宣告工具整合。
透過這兩個元件整合,系統會啟用以 Oracle LLM 為基礎的代理程式:
- 使用 MCP 從遠端代管工具。
- 執行產品與 EAN 的智慧型搜尋。
- 尋找對應的應收帳款發票。
- 使用鳳凰城和 OpenTelemetry 記錄可觀察的所有內容。
這個模組化設計可讓您重複使用,並輕鬆將系統演進至發票以外的網域。
目標
-
使用 LangGraph 和 LangChain 設定 AI 代理程式,以使用結構化提示。
-
使用
stdio
通訊協定將此代理程式與 MCP 伺服器整合。 -
使用在伺服器上註冊的遠端工具:
- 從產品描述執行向量搜尋。
- 識別項目的最有可能 EAN 代碼。
- 根據客戶、州別及價格等條件搜尋原始商業發票。
-
使用鳳凰城和 OpenTelemetry 即時監控代理程式執行情況。
-
根據 JSON 輸入模擬真正的問題解決,例如:
{ "customer": "Customer 43", "description": "Harry Potter", "price": 139.55, "location": "RJ" }
必備條件
-
存取 OCI 租用戶以管理您的雲端資源。您可以透過
oracle.com/cloud/free
免費註冊。 -
安裝 Python
version 3.12
或更新版本。 -
已啟用 OCI Generative AI 服務的 OCI 帳戶存取。
-
安裝並設定 Python
Langchain
程式庫。 -
使用 OCI Generative AI 存取
cohere.command-r-08-2024
模型。 -
安裝輔助程式庫:
oracledb
sentence_transformers
numpy
mcp-server-fastmcp
asyncio
langchain_core
langchain_community
mcp
langgraph
langchain_mcp_adapters
phoenix
(適用於 OpenTelemetry 的可觀察性)opentelemetry-sdk
,opentelemetry-exporter-otlp
-
具備下列工具的功能性 MCP 伺服器:
resolve_ean
search_vectorized_product
search_invoices_by_criteria
-
將
server_invoice_items.py
檔案設定為模擬 ERP 的 MCP 伺服器執行。 -
使用
pip install -r requirements.txt
指令下載和安裝requirements.txt
檔案。
工作 1:建立 Oracle Database 23ai (永遠免費)
在這項任務中,我們將瞭解如何以永遠免費模式佈建 Oracle Database 23ai。此版本提供完全受管理的環境,適用於開發、測試和學習,無須額外付費。
-
登入 OCI 主控台,導覽至 Oracle Database Autonomous Database ,然後按一下建立 Autonomous Database 執行處理。
-
請輸入下列資訊。
- 資料庫名稱:輸入執行處理的識別名稱。
- 工作負載類型:根據您的需求選取資料倉儲或交易處理。
- 區間: 選取適當的區間以組織您的資源。
-
選取永遠免費,確定已免費佈建此執行處理。
-
為
ADMIN
使用者建立安全密碼,此密碼將用於存取資料庫。 -
複查設定值,然後按一下建立 Autonomous Database 。等待幾分鐘的時間,讓執行處理可佈建並可供使用。
工作 2:執行 Autonomous Database 表格建立命令檔
準備資料庫以使用案例。從此處下載並執行 SQL 指令碼:script.sql
,為與 AI 代理程式調節發票的情況建立三個基本表格 (PRODUCTS
、INVOICE
及 ITEM_INVOICE
)。
-
前往 OCI 主控台,瀏覽至 Oracle Database Autonomous Database ,然後按一下新建立執行處理的名稱。
-
按一下資料庫動作和 SQL ,即可在瀏覽器中開啟 SQL 主控台。
-
在本機下載並開啟
script.sql
檔案,然後將所有內容貼到 SQL 主控台編輯器。 -
按一下執行 (Run) 或按 Ctrl + Enter 。等待確認已順利執行命令。
-
執行下列命令以驗證已建立表格。
SELECT table_name FROM user_tables;
作業 3:將範例資料插入表格
插入模擬 AI 代理應用程式實際案例的虛擬資料。我們將使用兩個 SQL 命令檔:
insert_products_books.sql
:將工作簿清單插入為產品,以及其各自的 EAN 與描述。invoice_data_insert.sql
:插入與客戶、產品及價格相關聯的模擬應收帳款發票記錄。
AI 代理將使用此資料來解決退貨發票中的不一致情況。
-
前往 OCI 主控台,瀏覽至 Oracle Database Autonomous Database ,然後按一下新建立執行處理的名稱。
-
按一下資料庫動作和 SQL ,即可在瀏覽器中開啟 SQL 主控台。
-
請從此處下載
insert_products_books.sql
檔案內容:insert_products_books.sql
並貼到 SQL 編輯器中。 -
按一下執行 (Run) 或按 Ctrl + Enter 。
-
現在,從此處下載
invoice_data_insert.sql
檔案內容:invoice_data_insert.sql
檔案並將其貼到編輯器中。 -
按一下執行 (Run) 或按 Ctrl + Enter 。
-
執行下列指令以檢查資料。
SELECT * FROM PRODUCTS; SELECT * FROM INVOICE; SELECT * FROM ITEM_INVOICE;
工作 4:建立及編譯資料庫中的進階搜尋函數
建立一個名為 fn_advanced_search
的 PL/SQL 函數,此函數會執行產品描述中關鍵字的智慧型搜尋。AI 代理將使用此功能作為 resolve_ean
工具的一部分,允許他們根據客戶在退貨單上提供的描述尋找最近的 EAN 代碼。
函數的功能為何?
-
輸入字詞的記號化 (範例:
harry poter stone
會變成 [harry
,poter
,stone
]) -
搜尋具有評分的技術:
-
直接搜尋,說明為
(LIKE '%term%')
→ +3 點。 -
拼音搜尋:使用
SOUNDEX
→ +2 點。 -
使用
UTL_MATCH.EDIT_DISTANCE <= 2
→ +1 點類似的拼字搜尋。
-
-
評分邏輯 :
- 每項產品的總點數。
- 僅傳回總分數大於 0 的產品。
-
傳回的格式:
產品會以
result_product
類型物件形式傳回,其中包含:code
(EAN)。description
(產品說明)。similarity
(計算的搜尋分數)。
遵循其步驟:
-
將完整的
similarity_search.sql
命令檔複製並貼到自治式資料庫 SQL 主控台。包括:
- 建立
products
表格 (如果尚未建立)。 - 建立文字索引。
- 類型
product_result
和product_result_tab
。 fn_advanced_search
函數。- 選擇性測試。
- 建立
-
執行完整命令檔。結果應為
Function created
和Type created
。 -
執行下列查詢以測試具有模擬描述的函數。
SELECT * FROM TABLE(fn_advanced_search('harry poter askaban')) ORDER BY similarity DESC;
任務 5:使用 AI 將語意搜尋的產品向量化
在這項任務中,我們將使用以語意向量為基礎的新方法來補充進階 SQL 型搜尋。這對於使用內嵌 (詞語的數值表示法) 來比較產品描述之間的相似性 (比字詞或拼音搜尋更具彈性且更聰明) 的 AI 代理來說特別有用。
為此,我們將使用連接到 Oracle 資料庫的 Python 腳本 (process_vector_products.py
),從 PRODUCTS
表格中擷取產品,將其描述轉換為向量 (嵌入),並使用 Oracle 資料庫本身建立向量索引。
命令檔的功能為何?
- 使用
oracledb
從products
表格讀取產品。 - 使用
sentence-transformers
套件中的all-MiniLM-L6-v2
模型產生內嵌項目。 - 建立
embeddings_products
表格,將向量直接儲存在 Oracle 中。 - 插入或更新記錄,並將向量儲存為二進位 BLOB (序列化的
float32
格式)。
注意:內嵌項目會轉換成位元組,其中
np.float32.tobytes()
會儲存為 BLOB。若要擷取向量,請使用np.frombuffer(blob, dtype=np.float32)
。
此格式允許未來相似性搜尋使用 SQL 直接進行,或從資料庫載入向量以進行 np.dot
、cosine_similarity
或與 LLM 整合的作業。
此命令檔會產生產品的語意內嵌項目,並將這些向量寫入 Oracle Database 23ai。主要點強調如下:
-
使用 Wallet 設定與 Oracle 的連線。
此程式碼使用
oracledb
程式庫的精簡型模式,並使用 Oracle Wallet 設定安全存取。os.environ["TNS_ADMIN"] = WALLET_PATH connection = oracledb.connect( user=USERNAME, password=PASSWORD, dsn=DB_ALIAS, ... )
-
產品表格諮詢。
products
表格包含原始資料 (ID、代碼和描述)。這些描述是用來作為產生語意向量的基礎。cursor.execute("SELECT id, code, description FROM products")
-
使用
sentence-transformers
產生內嵌項目all-MiniLM-L6-v2
模型是用來將產品描述轉換成高維度數值向量。model = SentenceTransformer('all-MiniLM-L6-v2') embeddings = model.encode(descriptions, convert_to_numpy=True)
-
建立內嵌表格 (如果不存在) 。
embeddings_products
表格使用下列欄位動態建立:id
:產品識別碼 (主索引鍵)。code
:產品代碼。description
:原始描述。vector
:包含float32
中序列化之向量的 BLOB。
CREATE TABLE embeddings_products ( id NUMBER PRIMARY KEY, code VARCHAR2(100), description VARCHAR2(4000), BLOB vector )
注意:建立作業會使用
BEGIN...EXCEPTION
內的EXECUTE IMMEDIATE
來避免表格已經存在時的錯誤。 -
使用
MERGE
插入或更新。對於每個產品,向量會轉換成位元組 (
float32
),並使用MERGE INTO
在embeddings_products
表格中插入或更新。vector_bytes = vector.astype(np.float32).tobytes()
MERGE INTO embeddings_products ...
執行指令碼:
注意:您需要下載並設定 Oracle Wallet。
在終端機中執行。
python process_vector_products.py
完成!資料庫中的產品已向量化。
這一點為何重要?
即使描述具有主觀性、不精確或自然語言,向量搜尋也非常有效地尋找產品。
瞭解程式碼:使用 MCP 伺服器進行 LLM 代理程式
此專案由 3 個主要元件組成:
- ReAct 代理程式 (含 LangGraph 和 OCI LLM) (
main.py
)。 - 具有發票解析工具的 MCP 伺服器 (
server_invoice_items.py
)。 - 使用 OCI Generative AI 和 FAISS 搜尋類似產品 (
product_search.py
)。
瞭解每一個元件的功能,並詳細說明程式碼中最重要的部分。
-
ReAct 使用 OCI LangGraph 和 LLM 的代理程式:
此元件會執行主要應用程式,使用者可以在其中根據 Oracle Cloud 的大型語言模型 (LLM) 與代理程式互動。它使用
stdio
通訊協定與 MCP 伺服器通訊。主要特點:
-
鳳凰城和 OpenTelemetry 的遙測組態。
px.launch_app() ... trace.set_tracer_provider(provider)
-
使用
ChatOCIGenAI
建立 LLM 模型。llm = ChatOCIGenAI( model_id="cohere.command-r-08-2024", ... )
-
調節商業發票的作業導向提示定義。
prompt = ChatPromptTemplate.from_messages([ ("system", """You are an agent responsible for resolving inconsistencies in invoices...""), ("placeholder", "{messages}") ])
-
使用
stdio
執行本機 MCP 伺服器。# Run the client with the MCP server async def main(): async with MultiServerMCPClient( { "InvoiceItemResolver": { "command": "python", "args": ["server_invoice_items.py"], "transport": "stdio", }, } ) as client:
-
主要使用者互動迴圈。
while True: query = input("You: ") ... result = await agent_executor.ainvoke({"messages": memory_state.messages})
-
與 MCP 伺服器公開的工具整合。
agent_executor = create_react_agent( model=llm, tools=tools, prompt=prompt, )
-
多個 MCP 伺服器。
若要使用多個 MCP 伺服器,請在此處包括伺服器:
# Run the client with the MCP server async def main(): async with MultiServerMCPClient( { "InvoiceItemResolver": { "command": "python", "args": ["server_invoice_items.py"], "transport": "stdio", }, "InvoiceItemResolver": { "command": "python", "args": ["another_mcp_server.py"], "transport": "stdio", }, ... } ) as client: tools = client.get_tools() if not tools: print("❌ No MCP tools were loaded. Please check if the server is running.") return
提示:
提示對於建立 AI 代理的流程和操作規則至關重要。
-
-
具備解析工具的 MCP 伺服器:
此伺服器提供可存取 Oracle Database 產品和發票資訊的工具來回應專員通話。
主要特點:
-
名稱為
InvoiceItemResolver
的 MCP 伺服器初始化。mcp = FastMCP("InvoiceItemResolver")
-
使用 Oracle Wallet 連線至 Oracle Database 。
connection = oracledb.connect( user=USERNAME, password=PASSWORD, dsn=DB_ALIAS, wallet_location=WALLET_PATH, ... )
-
MCP 工具的實行。
-
search_vectorized_product
:搜尋內嵌的類似產品。
@mcp.tool() def search_vectorized_product(description: str) -> dict: """ Searches for a product by description using embeddings. """ return sercher.search_similar_products(description)
-
resolve_ean
:依據描述相似性來解析 EAN。
@mcp.tool() def resolve_ean(description: str) -> dict: result = execute_search_ean(description) ... return {"ean": result[0]["code"], ...}
-
search_invoices_by_criteria
:根據多個篩選條件搜尋應收帳款發票。
@mcp.tool() def search_invoices_by_criteria(customer: str = None, state: str = None, price: float = None, ean: str = None, margin: float = 0.05) -> list: """ Searches for outbound invoices based on customer, state, EAN, and approximate price. Allows one or more fields to be omitted. As long as an EAN has not been established, it is not useful to use this service. """ query = """ SELECT nf.no_invoice, nf.name_customer, nf.state, nf.date_print, inf.no_item, inf.code_ean, inf.description_product, inf.value_unitary FROM invoice nf JOIN item_invoice inf ON nf.no_invoice = inf.no_invoice WHERE 1=1 """ params = {} #if customer: query += " AND LOWER(nf.name_customer) LIKE LOWER(:customer)" params["customer"] = f"%{customer}%" #if state: query += " AND LOWER(nf.state) = LOWER(:state)" params["state"] = state #if ean: query += " AND inf.code_ean = :ean" params["ean"] = ean if price is not None: query += " AND inf.value_unitary BETWEEN :price_min AND :price_max" params["price_min"] = price * (1 - margin) params["price_max"] = price * (1 + margin) result = execute_query(query, params) return [ dict(zip( ["no_invoice", "name_customer", "state", "date_print", "no_item", "code_ean", "description_product", "value_unitary"], row )) for row in result ]
-
-
以
stdio
模式執行伺服器。if __name__ == "__main__": mcp.run(transport="stdio")
-
-
使用 OCI Generative AI 和 Vector Database 搜尋相似產品:
本模組
product_search.py
實作 Python 類別,可讓您從文字描述搜尋語意相似的產品,使用:- 嵌入 OCI Generative AI 。
- Oracle Database 23ai 提供向量索引。
- 模糊比對 (RapidFuzz) 作為後援。
工作 6:設定 MCP 代理程式中的模型和內嵌項目
讓我們使用 OCI Generative AI 服務,根據 MCP 通訊協定設定對話代理程式使用的語言模型和內嵌內容。
-
設定語言模型 (LLM)。
語言模型負責解譯訊息、產生回應,以及作為專員的主要大腦。
-
在
main.py
檔案中設定。from langchain_community.chat_models.oci_generative_ai import ChatOCIGenAI llm = ChatOCIGenAI( model_id="cohere.command-r-08-2024", service_endpoint="https://inference.generativeai.us-chicago-1.oci.oraclecloud.com", compartment_id="ocid1.compartment.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", auth_profile="DEFAULT", model_kwargs={"temperature": 0.1, "top_p": 0.75, "max_tokens": 2000} )
Parameter - 參數 描述 model_id
生成式 AI 模型 ID,例如 cohere.command-r-08-2024
service_endpoint
生成式 AI 服務區域端點 compartment_id
OCI 區間的 OCID auth_profile
檔案中設定的設定檔名稱 ~/.oci/config
model_kwargs
溫度、top-p 和回應大小 -
列出可用的模型。
-
使用 OCI CLI:
oci generative-ai model list --compartment-id <seu_compartment_id>
-
使用 Python SDK:
from oci.generative_ai import GenerativeAiClient from oci.config import from_file config = from_file(profile_name="DEFAULT") client = GenerativeAiClient(config) models = client.list_models(compartment_id=config["compartment_id"]) for model in models.data: print(model.display_name, model.model_id)
-
-
-
設定語意搜尋的內嵌項目。
搜尋類似產品或情境資訊取決於向量內嵌。
在代理程式中使用的範例:
@mcp.tool() def search_vectorized_product(description: str) -> dict: """ Searches for a product by description using embeddings. """ return sercher.search_similar_products(description)
變更參數 (
product_search.py
),如下所示:class SimilarProductSearch: def __init__( self, top_k=5, minimum_distance=1.0, model_id="cohere.embed-english-light-v3.0", service_endpoint="https://inference.generativeai.us-chicago-1.oci.oraclecloud.com", compartment_id="ocid1.compartment.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", auth_profile="DEFAULT", wallet_path="/WALLET_PATH/Wallet_oradb23ai", db_alias="oradb23ai_high", username="USER", password="Password" ):
Parameter - 參數 描述 top_k
傳回的建議數目。 minimum_distance
考量相關結果的最大距離。 model_id
OCI 中內嵌模型的 ID (例如 cohere.embed-english-light-v3.0
)。service_endpoint
OCI Generative AI 區域端點。 compartment_id
區間 OCID。 auth_profile
~/.oci/config
檔案中的設定檔名稱。wallet_path
Oracle Database 23ai 公事包的路徑。 db_alias
資料庫別名。 username
資料庫使用者。 password
資料庫密碼。 設定 MCP 伺服器:
就像執行
process_vector_products.py
程式碼一樣,您需要為 Oracle Database 23ai 資料庫設定 Oracle Wallet。根據您的設定來修改參數 :
import os # Oracle Wallet settings WALLET_PATH = "/path/to/Wallet" DB_ALIAS = "oradb23ai_high" USERNAME = "admin" PASSWORD = "..." # Define the environment variable required for the Oracle client os.environ["TNS_ADMIN"] = WALLET_PATH
然後執行
process_vector_products.py
,將產品向量化至 Oracle Database 23ai。python process_vector_products.py
因此,MLM 模型和內嵌項目已可供 LangGraph 和 LangChain 的 MCP 代理程式使用。
任務 7:測試產品與商業發票摘要搜尋
-
使用下列指令執行
main.py
檔案。python main.py
-
當您:提示出現時,請輸入下列陳述式。
{ "customer": "Customer 108", "description": "Harry Poter askaban", "price": 82.26, "location": "SP"}
備註:Harry Potter 和 Azkaban 工作簿的名稱拼字錯誤,但引擎可以找到它,沒有任何問題。
請注意,服務已執行:
fetch_vectorized_product resolve_ean search_invoices_by_criteria
-
現在,輸入下列陳述式。
{ "customer": "Customer 108", "description": "Harry Poter askaban", "price": 82.26}
您會看到找不到發票記錄。這是因為位置是尋找發票的關鍵。
-
現在,輸入下列陳述式。
{ "customer": "Customer 108", "description": "Harry Poter", "location": "SP"}
這次我們輸入地點,但省略單價。
而且找到發票。這是因為價格不是基本的,但這有助於關閉差距以更具說服力。
以下是一些測試範例:
{ "customer": "Customer 108", "description": "Harry Poter askaban", "price": 82.26, "location": "SP"} { "customer": "Customer 108", "description": "Harry Poter askaban", "price": 82.26} { "customer": "Customer 108", "description": "Harry Poter askaban", "location": "SP"} { "customer": "Customer 108", "description": "Harry Poter askaban", "price": 82.26, "location": "RJ"} { "customer": "Customer 125", "description": "Harry Potter Chamber", "price": 79.16, "location": "SP"} { "customer": "Customer 125", "description": "Harry Potter Chamber", "price": 79.15, "location": "SP"}
任務 8:檢視鳳凰城的可觀察性
在瀏覽器中輸入 http://localhost:6006/
,即可檢視鳳凰城的可觀察性。
相關連結
確認
- 作者 - Cristiano Hoshikawa (Oracle LAD A 團隊解決方案工程師)
其他學習資源
在 docs.oracle.com/learn 上探索其他實驗室,或在 Oracle Learning YouTube 頻道上存取更多免費學習內容。此外,請造訪 education.oracle.com/learning-explorer 以成為 Oracle Learning Explorer。
如需產品文件,請造訪 Oracle Help Center 。
Build an AI Agent with Multi-Agent Communication Protocol Server for Invoice Resolution
G35148-06
Copyright ©2025, Oracle and/or its affiliates.