Cùng bắt đầu xây dựng một tác nhân AI, cung cấp kiến thức từ hướng dẫn sử dụng của tất cả các thiết bị của mình và để nó trả lời các câu hỏi của mình khi cần. Tác nhân này chạy trên Raspberry Pi của mình và luôn sẵn sàng giúp mình. Có nhiều khuôn khổ ngoài kia giúp bạn xây dựng các tác nhân AI. LlamaIndex là khuôn khổ tôi đã chọn, nhưng bạn có thể xây dựng nó bằng bất kỳ khuôn khổ tác nhân nào. Vì tôi muốn ứng dụng này chạy miễn phí, tôi đã sử dụng LLM nguồn mở cho dự án. Ollama rất tuyệt vời cho mục đích này, cho phép bạn tải xuống LLM nguồn mở.
Trong bài viết này chúng ta đã xem xét:
- Cách xây dựng tác nhân RAG và ReAct bằng LlamaIndex.
- Các yếu tố cần cân nhắc khi chạy chương trình này trên máy có công suất thấp như Raspberry Pi.
- Sử dụng Streamlit để xây dựng giao diện người dùng đơn giản cho ứng dụng.
Chuẩn bị không gian cho hướng dẫn sử dụng
Bắt đầu bằng cách thu thập các hướng dẫn sử dụng mà bạn muốn AI truy cập và lưu chúng vào một thư mục cụ thể. Tôi chỉ cần tải mọi thứ lên trong thư mục này: docs/user_manuals.
Xây dựng một công cụ truy vấn từ các tài liệu
Tiếp theo, chúng ta cần xử lý bit RAG của tác nhân AI này. Điều này bao gồm việc lấy các tệp PDF từ thư mục, đọc và phân đoạn chúng, chuyển đổi các khối thành nhúng và lưu chúng vào cơ sở dữ liệu vector. Đây là tổng quan rất nhanh về khía cạnh chuẩn bị dữ liệu của RAG và người đọc được khuyến khích tìm hiểu sâu hơn về nó. Mặc dù quá trình này nghe có vẻ phức tạp, nhưng may mắn thay, LlamaIndex cho phép chúng ta thực hiện điều này chỉ với 3 dòng mã:
documents = SimpleDirectoryReader(“docs/user_manuals”).load_data(show_progress=True)”docs/user_manuals”).load_data(show_progress=True)
index = VectorStoreIndex.from_documents(documents, show_progress=True)
query_engine = index.as_query_engine()
Tuy nhiên, trước khi xác định chỉ mục và công cụ truy vấn, mô hình LLM nhúng cần phải được thay đổi. LlamaIndex sử dụng các mô hình OpenAI theo mặc định, nhưng bạn có thể sử dụng bất kỳ mô hình nào bạn thích. Trong trường hợp của tôi, việc sử dụng mô hình nguồn mở từ Ollama có thể được thực hiện như sau:
Settings.embed_model = OllamaEmbedding(model_name=”all-minilm:22m”)“all-minilm:22m”)
Người đọc được khuyến khích thử nghiệm với các mô hình nhúng khác nhau. Tôi đã thành công khác nhau với những mô hình tôi đã thử, chẳng hạn nhưnomic-embed-text, nhưngall-minilm:22mcho tôi thành công nhất. Với mô hình nomic, nó thường không phân tích cú pháp và nhúng một số phần nhất định của một số tài liệu. Bạn có thể thử mã khởi động 5 dòng do LlamaIndex cung cấp để kiểm tra hiệu suất của các mô hình nhúng:LlamaIndex — LlamaIndex. Tuy nhiên, tôi quyết định không sử dụng mã đó cho dự án của mình vì tôi muốn tác nhân của mình suy luận thông qua phản hồi mà nó nhận được từ công cụ truy vấn — tôi sẽ nói thêm về điều đó sau.
Xây dựng tác nhân ReAct
Mộttác nhân ReAct, viết tắt của Reason + Act, là một tác nhân lý luận suy nghĩ và hành động từng bước để giải quyết một nhiệm vụ phức tạp. Khá đơn giản để tạo một tác nhân ReAct trong LlamaIndex và cung cấp cho nó các công cụ. Đầu tiên, chúng ta sẽ chuyển đổi công cụ truy vấn được xác định trước đó thành một công cụ mà tác nhân có thể sử dụng:
user_manual_query_tool = QueryEngineTool.from_defaults(
query_engine,
name=”user_manual_query_tool”,”user_manual_query_tool”,
description=(
“A RAG engine with various user manuals of appliances.”,
“Use a detailed plain text question as input to the tool.”),
)
Bước tiếp theo là xác định tác nhân ReAct, cung cấp cho nó quyền truy cập vào công cụ truy vấn hướng dẫn sử dụng:
system_prompt = “”””””
System prompt:
You are an AI assistant specialized in answering questions about appliances using information from user manuals.
1. Always rely on the **user_manual_query_tool** to retrieve information; do not use prior knowledge.
2. If a query cannot be answered using the tool, respond with: “I cannot find this information in the user manuals provided.”
3. Do not attempt to generate answers without using the tool.
4. Give detailed responses to the user’s queries, explaining everything in steps.
5. Return the response in markdown format.
Note: The tool name is **user_manual_query_tool**, and it should be used for all queries.
“””
self.agent = ReActAgent.from_tools(
tools=[user_manual_query_tool],
verbose=True,
context=system_prompt
)
Tôi cũng đã định nghĩa một lời nhắc hệ thống cho tác nhân ở trên, để tôi có được câu trả lời nhất quán cho các truy vấn của mình từ hướng dẫn sử dụng. Nếu không có lời nhắc này, đôi khi tôi thấy tác nhân trả về phản hồi từ kiến thức của riêng mình, thay vì truy vấn chỉ mục kiến thức.
Ngoài ra, LlamaIndex sử dụng OpenAI LLM làm mặc định, nhưng chúng ta có thể dễ dàng thay đổi cài đặt để sử dụng Ollama:
Settings.llm = Ollama(model=”llama3.1″)”llama3.1″)
Tuy nhiên, tại thời điểm này, tôi bắt đầu nghi ngờ liệu điều này có thể chạy trên Raspberry Pi của tôi hay không, vì phải dựa vào llama3.1 (tham số 8b) có thể là một mô hình mạnh mẽ để chạy trên Raspberry Pi. Để kiểm tra mọi thứ, tôi đã tạo một lớp cho tác nhân:
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.llms.ollama import Ollama
from llama_index.embeddings.ollama import OllamaEmbedding
from llama_index.core.agent import ReActAgent
from llama_index.core.tools import QueryEngineTool
import time
import nest_asyncio
nest_asyncio.apply()
class UserManualAgent:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super(UserManualAgent, cls).__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self):
if not hasattr(self, ‘initialized’):
Settings.embed_model = OllamaEmbedding(model_name=”all-minilm:22m”)
Settings.llm = Ollama(model=”llama3.1″)
documents = SimpleDirectoryReader(“docs/user_manuals”).load_data(show_progress=True)
index = VectorStoreIndex.from_documents(documents, show_progress=True)
query_engine = index.as_query_engine()
user_manual_query_tool = QueryEngineTool.from_defaults(
query_engine,
name=”user_manual_query_tool”,
description=(
“A RAG engine with various user manuals of appliances.”,
“Use a detailed plain text question as input to the tool.”),
)
system_prompt = “””
System prompt:
You are an AI assistant specialized in answering questions about appliances using information from user manuals.
1. Always rely on the **user_manual_query_tool** to retrieve information; do not use prior knowledge.
2. If a query cannot be answered using the tool, respond with: “I cannot find this information in the user manuals provided.”
3. Do not attempt to generate answers without using the tool.
4. Give detailed responses to the user’s queries, explaining everything in steps.
5. Return the response in markdown format.
Note: The tool name is **user_manual_query_tool**, and it should be used for all queries.
“””
self.agent = ReActAgent.from_tools(
tools=[user_manual_query_tool],
verbose=True,
context=system_prompt
)
print(“done initializing agent”)
self.initialized = True
def query(self, question):
print(“user query: “, question)
start_time = time.time()
try:
response = self.agent.chat(question)
response_time = time.time() – start_time
print(“response time: “, response_time)
except ValueError as e:
response = “I cannot find this information in the user manuals provided.”
print(e)
return response
if __name__ == “__main__”:
agent = UserManualAgent()
response = agent.query(“How to setup the Roborock vacuum?”)
print(response)
Lưu ý rằng tôi đã tạo một singleton cho lớp này, do đó các lệnh gọi riêng biệt đến hàm tạo không khởi tạo tác nhân nhiều lần.
Bước tiếp theo là cài đặt Ollama và các mô hình phụ thuộc trên Raspberry Pi, kéo mã đã đề cập ở trên, cài đặt tất cả các phụ thuộc và chạy lớp để xem nó có hoạt động không. Và như tôi lo sợ, LLM đã hết thời gian chờ khi phản hồi. Tuy nhiên, tôi nên đề cập rằng tôi đã có thể chạy và trò chuyện với llama3.1 trên Raspberry Pi một mình. Tuy nhiên, nó không hoạt động hoàn toàn với tác nhân ReAct. Tôi bắt đầu thử nghiệm xung quanh với các mô hình Ollama khác nhau và các giá trị thời gian chờ và sự kết hợp cuối cùng đã hoạt động là:
Settings.llm = Ollama(model=”tinyllama”, request_timeout=60*5)”tinyllama”, request_timeout=60*5)
Sự kết hợp này hầu như không gây ra thời gian chờ, nhưng vẫn chậm. Đối với tôi, thời gian phản hồi nằm trong khoảng 45–60 giây. Có thể đạt được hiệu suất tốt hơn với phiên bản RAM 16 GB của Pi hoặc sử dụng SSD để lưu trữ thay vì thẻ SD và tôi có thể cân nhắc những điều này trong tương lai.
Đây là hạn chế khi sử dụng một mô hình nhỏ hơn như TinyLlama làm tác nhân lý luận và tôi nhận ra rằng tôi có thể phải thử nghiệm với các mô hình.
Cuối cùng tôi quyết định thay thế Ollama trong thiết lập của mình bằngOpenRoutervà sử dụng LLM nguồn mở từ đó. Nó có giới hạn về số lượng yêu cầu mà người dùng có thể thực hiện mỗi phút, nhưng là một giải pháp thay thế tuyệt vời khi bạn không có đủ tài nguyên phần cứng để chạy mô hình LLM lớn hơn.
LlamaIndex cũng cung cấp khả năng tích hợp dễ dàng với OpenRouter. Mã cuối cùng cho lớp hướng dẫn sử dụng như sau:
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.llms.openrouter import OpenRouter
from llama_index.embeddings.ollama import OllamaEmbedding
from llama_index.core.agent import ReActAgent
from llama_index.core.tools import QueryEngineTool
import nest_asyncio
nest_asyncio.apply()
import time
from dotenv import load_dotenv
import os
load_dotenv()
class UserManualAgent:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super(UserManualAgent, cls).__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self):
if not hasattr(self, ‘initialized’):
Settings.embed_model = OllamaEmbedding(model_name=”all-minilm:22m”)
llm = OpenRouter(
api_key=os.getenv(“OPEN_ROUTER_KEY”),
model=”meta-llama/llama-3.2-3b-instruct:free”,
request_timeout=60*5
)
Settings.llm = llm
Settings.chunk_size = 700
Settings.chunk_overlap = 20
documents = SimpleDirectoryReader(“docs/user_manuals”).load_data(show_progress=True)
index = VectorStoreIndex.from_documents(documents, show_progress=True)
query_engine = index.as_query_engine()
user_manual_query_tool = QueryEngineTool.from_defaults(
query_engine,
name=”user_manual_query_tool”,
description=(
“A RAG engine with various user manuals of appliances.”,
“Use a detailed plain text question as input to the tool.”),
)
system_prompt = “””
System prompt:
You are an AI assistant specialized in answering questions about appliances using information from user manuals.
1. Always rely on the **user_manual_query_tool** to retrieve information; do not use prior knowledge.
2. If a query cannot be answered using the tool, respond with: “I cannot find this information in the user manuals provided.”
3. Do not attempt to generate answers without using the tool.
4. Give detailed responses to the user’s queries, explaining everything in steps.
5. Return the response in markdown format.
Note: The tool name is **user_manual_query_tool**, and it should be used for all queries.
“””
self.agent = ReActAgent.from_tools(
tools=[user_manual_query_tool],
verbose=True,
context=system_prompt
)
print(“done initializing agent”)
self.initialized = True
def query(self, question):
print(“user query: “, question)
start_time = time.time()
try:
response = self.agent.chat(question)
response_time = time.time() – start_time
print(“response time: “, response_time)
except ValueError as e:
response = “I cannot find this information in the user manuals provided.”
print(e)
return response
if __name__ == “__main__”:
agent = UserManualAgent()
response = agent.query(“How to setup the Roborock vacuum?”)
print(response)
Sau khi thay đổi kích thước khối và chồng lấn khối, tôi cũng đạt được hiệu suất nhanh hơn khi nhúng tài liệu vào Raspberry Pi.
Tạo giao diện người dùng bằng streamlit để tương tác với tác nhân
Bước cuối cùng là tạo một giao diện người dùng nhanh bằng streamlit để tương tác với tác nhân. Đây là mã cho giao diện người dùng:
import streamlit as st
from user_manual_agent import UserManualAgent
@st.cache_resource
def initialize_agent():
user_manual_agent = UserManualAgent()
return user_manual_agent
# Function to cycle through messages
def display_interface(user_manual_agent):
# Streamlit app
st.title(“User Manual Agent”)
st.write(“Ask any questions you have about your appliances :sunglasses:”)
# Input text box for user query
user_query = st.text_input(“Enter your question:”)
# Button to submit the query
if st.button(“Submit”):
if user_query:
with st.spinner(“Fetching response…”):
response = user_manual_agent.query(user_query)
st.markdown(“**Response**: \n\n”)
st.markdown(response.response)
else:
st.write(“Please enter a question.”)
user_manual_agent = initialize_agent()
display_interface(user_manual_agent)
Lưu ý việc sử dụng @st.cache_resourcekhi tạo tác nhân. Điều này ngăn không cho tác nhân được khởi tạo nhiều lần nếu ứng dụng được truy cập nhiều lần.
Bây giờ bạn cũng có thể biến Raspberry Pi thành trợ lý cá nhân!
Nguôn: //medium.com/@muhammad.taha/turn-your-raspberry-pi-into-a-local-ai-agent-to-help-you-figure-out-your-appliances-4aea2d39ee91
PyMuPDF chuyển đổi tài liệu với hệ thống đa tác nhân.
//medium.com/@pankaj_pandey/b47b05aacf73
Chuyển đổi tài liệu hiệu quả là rất quan trọng đối với các tổ chức xử lý khối lượng lớn thông tin phi cấu trúc. Việc chuyển đổi tài liệu — dù là PDF, hình ảnh được quét hay tệp văn bản — thành dữ liệu có cấu trúc, có thể đọc được bằng máy theo truyền thống là một quá trình tốn nhiều công sức. Các giải pháp hiện đại hiện nay tận dụng Hệ thống đa tác nhân (MAS) , phân bổ nhiệm vụ giữa các tác nhân chuyên biệt, để hợp lý hóa và tự động hóa quy trình này.
Sự tiến hóa của việc chuyển đổi tài liệu
Phương pháp truyền thống so với phương pháp hiện đại
Phương pháp truyền thống:
- Dựa vào xử lý hàng loạt, hệ thống dựa trên quy tắc hoặc ứng dụng độc lập.
- Thường cần can thiệp thủ công và khó mở rộng quy mô hoặc thích ứng với các tài liệu khác nhau…
Kỹ thuật hiện đại:
- Sử dụng trí tuệ nhân tạo, máy học và kiến trúc MAS.
- Cung cấp các giải pháp theo mô-đun, có khả năng mở rộng và tự động hóa để xử lý nhiều loại tài liệu khác nhau với sự can thiệp tối thiểu của con người.
Xu hướng và kỹ thuật mới nhất
- Xử lý phân tán:
MAS triển khai nhiều tác nhân làm việc đồng thời trên các phần khác nhau của quy trình chuyển đổi, giúp giảm thời gian xử lý và tăng thông lượng. - Tích hợp với AI tạo sinh:
Tận dụng các mô hình ngôn ngữ lớn (LLM) cho các tác vụ như tóm tắt, nhận dạng thực thể và trích xuất nội dung giúp nâng cao độ chính xác và tính thông minh của quy trình chuyển đổi. - Hiểu tài liệu đa phương thức:
Các hệ thống như MDocAgent kết hợp phân tích văn bản, bố cục và hình ảnh để hiểu rõ hơn các tài liệu phức tạp — một bước tiến đáng kể so với các phương pháp tiếp cận đơn phương thức. - Kiến trúc đám mây gốc và kiến trúc vi dịch vụ:
Triển khai các tác nhân dưới dạng vi dịch vụ trên nền tảng đám mây cho phép mở rộng quy mô động và quản lý tài nguyên tốt hơn, đảm bảo khả năng phục hồi trong thời gian tải cao. - Xác thực dữ liệu tự động:
Kết hợp các tác nhân kiểm tra lỗi, ghi nhật ký và xác thực đảm bảo tính chính xác và độ tin cậy của dữ liệu được chuyển đổi.
Lợi ích của Hệ thống đa tác nhân trong Phát triển ứng dụng
Khả năng mở rộng và hiệu suất
- Xử lý song song:Nhiều tác nhân hoạt động đồng thời trên các tác vụ khác nhau, giúp giảm đáng kể độ trễ.
Tính linh hoạt và tính mô-đun
- Kiến trúc Plug-and-Play:MAS cho phép các nhà phát triển hoán đổi hoặc cập nhật các thành phần riêng lẻ mà không ảnh hưởng đến toàn bộ hệ thống.
Khả năng phục hồi và khả năng chịu lỗi
- Chuyển đổi dự phòng phân tán:Nếu một tác nhân bị lỗi, các tác nhân khác vẫn tiếp tục xử lý, đảm bảo hoạt động liên tục — một khía cạnh quan trọng đối với các ứng dụng quan trọng.
Chất lượng dữ liệu được nâng cao
- Đảm bảo chất lượng tự động:Các tác nhân tiền xử lý và hậu xử lý giúp cải thiện độ chính xác và tính nhất quán của dữ liệu được chuyển đổi.
Tổng quan về kiến trúc của đường ống chuyển đổi tài liệu dựa trên MAS
Một hệ thống chuyển đổi tài liệu dựa trên MAS điển hình bao gồm một số thành phần chính:
- Nhập tài liệu:Hệ thống chấp nhận nhiều định dạng tài liệu khác nhau (ví dụ: PDF, hình ảnh, tệp văn bản).
- Tác nhân tiền xử lý:Làm sạch và chuẩn hóa dữ liệu thô (loại bỏ nhiễu, chuẩn hóa định dạng).
- Công cụ trích xuất:Trích xuất nội dung cần thiết bằng các kỹ thuật như OCR cho hình ảnh hoặc NLP cho dữ liệu văn bản.
- Công cụ chuyển đổi dữ liệu:Chuyển đổi nội dung được trích xuất thành các định dạng có cấu trúc như JSON hoặc XML.
- Tác nhân xác thực và ghi nhật ký:Đảm bảo độ chính xác của đầu ra và ghi lại thông tin chi tiết về quá trình xử lý lỗi và kiểm tra trong tương lai.
- Tích hợp với mô hình AI:Các tác nhân tùy chọn tận dụng LLM để tăng cường các tác vụ như tóm tắt, dịch thuật và nhận dạng thực thể.
Triển khai Python: Một ví dụ thực tế
Ví dụ Python sau đây trình bày một MAS đơn giản để chuyển đổi tài liệu.
Trong ví dụ này, ba tác nhân làm việc cùng nhau để:
- Trích xuất văn bản từ tài liệu PDF.
- Xác định và trích xuất địa chỉ email từ văn bản.
- Chuyển đổi dữ liệu đã trích xuất sang định dạng JSON.
Thiết lập môi trường
Cài đặt thư viện cần thiết: pip install PyMuPDF
Định nghĩa các tác nhân
PDFReaderAgent:Trích xuất văn bản từ PDF bằng PyMuPDF:
import fitz # PyMuPDF
class PDFReaderAgent:
def __init__(self, file_path):
self.file_path = file_path
def extract_text(self):
text = ""
with fitz.open(self.file_path) as pdf:
for page_num in range(len(pdf)):
page = pdf.load_page(page_num)
text += page.get_text()
return text
DataExtractionAgent: Sử dụng biểu thức chính quy để trích xuất địa chỉ email:
import re
class DataExtractionAgent:
def __init__(self, text):
self.text = text
def extract_data(self):
emails = re.findall(
r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b',
self.text
)
return {"emails": emails}
FormatConversionAgent: Chuyển đổi dữ liệu đã trích xuất thành JSON:
import json
class FormatConversionAgent:
def __init__(self, data):
self.data = data
def to_json(self, output_file):
with open(output_file, 'w') as f:
json.dump(self.data, f, indent=4)
print(f"Data saved to {output_file}")Điều phối các tác nhân
Bộ điều khiển điều phối quy trình làm việc:
class DocumentConversionController:
def __init__(self, file_path, output_file):
self.file_path = file_path
self.output_file = output_file
def convert(self):
# Step 1: Extract text from PDF
reader_agent = PDFReaderAgent(self.file_path)
text = reader_agent.extract_text()
print(“Text extraction complete.”)
# Step 2: Process extracted text to extract data (emails in this case)
extraction_agent = DataExtractionAgent(text)
data = extraction_agent.extract_data()
print(“Data extraction complete.”)
# Step 3: Convert the data into JSON format
conversion_agent = FormatConversionAgent(data)
conversion_agent.to_json(self.output_file)
print(“Document conversion complete.”)
# Execute the conversion process
if __name__ == “__main__”:
file_path = “sample_document.pdf” # Ensure this file exists in your working directory
output_file = “output_data.json”
controller = DocumentConversionController(file_path, output_file)
controller.convert()
Đánh giá tính bảo mật của hệ thống bằng cách sử dụng dữ liệu được thu thập thụ động, mà không chủ động tìm cách xâm phạm dữ liệu đó.

Bài viết liên quan: