Phát triển Bot WeChat Doanh nghiệp với EVA-01: Phân tích hình ảnh trên di động không cần code

Giới thiệu

Hãy hình dung một tình huống: Bạn đang kiểm tra dây chuyền sản xuất trong nhà máy, phát hiện đèn báo của một thiết bị bất thường. Bạn chụp nhanh một bức ảnh và gửi vào nhóm chat công việc. Chỉ vài giây sau, một báo cáo phân tích chi tiết về trạng thái thiết bị tự động được gửi lại trong nhóm. Hoặc khi đang họp bên ngoài, khách hàng gửi cho bạn một bản phác thảo thiết kế sản phẩm, bạn chỉ cần gửi ảnh qua WeChat Doanh nghiệp và ngay lập tức nhận được phân tích cấu trúc chuyên nghiệp cùng các đề xuất cải tiến.

Nghe có vẻ như một cảnh trong phim khoa học viễn tưởng, nhưng hôm nay, chúng ta có thể biến nó thành hiện thực. Bằng cách kết hợp hệ thống phân tích thị giác EVA-01 với bot WeChat Doanh nghiệp, bạn có thể sở hữu một trợ lý thị giác di động hoạt động 24/7. Dù bạn ở bất cứ đâu, chỉ với một chiếc điện thoại, chụp một bức ảnh, bạn sẽ nhận được sự hiểu và phân tích hình ảnh chuyên nghiệp.

Điểm tuyệt vời nhất là toàn bộ quá trình gần như không cần viết bất kỳ đoạn mã phức tạp nào. Hãy làm theo hướng dẫn này, bạn sẽ từng bước xây dựng hệ thống phân tích hình ảnh di động mạnh mẽ này.

1. Kiến trúc hệ thống: Hiểu rõ quy trình luân chuyển tin nhắn

Trước khi bắt tay vào thực hiện, chúng ta hãy cùng làm rõ cách thức hoạt động của toàn bộ hệ thống. Hiểu rõ nguyên lý sẽ giúp bạn dễ dàng cấu hình và gỡ lỗi sau này, thay vì chỉ sao chép lệnh một cách máy móc.

1.1. Năm bước chính trong luân chuyển tin nhắn

Toàn bộ hệ thống hoạt động như một dây chuyền tự động tinh vi, từ khi bạn gửi hình ảnh cho đến khi nhận được kết quả phân tích, trải qua năm bước rõ ràng:

  1. Kích hoạt: Bạn @bot đã tạo trong cuộc trò chuyện nhóm hoặc cá nhân trên WeChat Doanh nghiệp, sau đó gửi một hình ảnh. Hình ảnh này có thể được chụp tại chỗ hoặc chọn từ thư viện ảnh.
  2. Chuyển giao: Máy chủ của WeChat Doanh nghiệp sau khi nhận được tin nhắn này, sẽ ngay lập tức đẩy nội dung tin nhắn đến máy chủ của bạn thông qua một "địa chỉ callback" đã được cấu hình trước (một URL cụ thể). Nội dung đẩy bao gồm liên kết tải xuống tạm thời của hình ảnh và thông tin người gửi.
  3. Xử lý: Máy chủ của bạn (chạy chương trình backend của EVA-01) nhận được thông báo. Nó bắt đầu thực hiện hai nhiệm vụ cốt lõi:
    • Tải hình ảnh từ liên kết tạm thời do WeChat Doanh nghiệp cung cấp về bộ nhớ cục bộ.
    • Khởi động công cụ phân tích thị giác của EVA-01 để phân tích sâu hình ảnh này.
  4. Phản hồi: Sau khi phân tích hoàn tất, máy chủ của bạn sẽ tổng hợp kết quả phân tích do EVA-01 tạo ra thành định dạng văn bản, sau đó gọi giao diện API gửi tin nhắn của WeChat Doanh nghiệp để gửi báo cáo phân tích này trở lại cửa sổ trò chuyện ban đầu.
  5. Hiển thị: Bạn thấy bot trong giao diện trò chuyện của WeChat Doanh nghiệp @bạn và trả lời bằng kết quả phân tích chi tiết. Toàn bộ quá trình thường diễn ra trong khoảng 5-10 giây. Đối với bạn, đó chỉ là hai thao tác đơn giản "gửi - nhận".

1.2. Công cụ và môi trường cần chuẩn bị

Để xây dựng hệ thống này, bạn cần chuẩn bị những thứ sau:

  • Máy chủ chạy EVA-01: Đây là bộ não trung tâm của toàn bộ hệ thống. Bạn cần một máy chủ có hiệu suất đủ mạnh, khuyến nghị cấu hình NVIDIA GPU (bộ nhớ VRAM 16GB trở lên), và đã triển khai thành công theo hướng dẫn chính thức của dự án EVA-01. Đảm bảo bạn có thể truy cập giao diện Web của nó qua trình duyệt (thường là http://IP_may_chu_cua_ban:8501). Hướng dẫn này giả định EVA-01 của bạn đã hoạt động bình thường cục bộ.
  • Tài khoản doanh nghiệp WeChat Doanh nghiệp: Nếu chưa có, bạn có thể đăng ký miễn phí trên trang web chính thức của WeChat Doanh nghiệp. Quá trình đăng ký đơn giản, chỉ cần cung cấp thông tin cơ bản về công ty và liên hệ.
  • Địa chỉ truy cập công cộng (Public URL): Vì WeChat Doanh nghiệp cần truy cập máy chủ của bạn từ Internet để đẩy tin nhắn, máy chủ của bạn phải có một địa chỉ có thể truy cập công cộng. Nếu bạn đang ở mạng nội bộ công ty hoặc mạng gia đình, bạn cần sử dụng công cụ xuyên hầm nội mạng (ngrok hoặc frp). Chúng có thể tạo ra một địa chỉ công cộng tạm thời cho máy chủ cục bộ của bạn.
  • Môi trường Python cơ bản: Máy chủ của bạn cần cài đặt Python 3.7 trở lên. Chúng ta cũng sẽ sử dụng một vài thư viện Python bổ sung, việc cài đặt rất đơn giản.

2. Tạo bot: Cấu hình trợ lý thông minh trong WeChat Doanh nghiệp

Bây giờ, chúng ta sẽ vào trang quản lý của WeChat Doanh nghiệp để tạo "bot" này. Quá trình này giống như thêm một nhân viên thông minh mới vào WeChat Doanh nghiệp của bạn.

2.1. Tạo ứng dụng WeChat Doanh nghiệp

  1. Đăng nhập vào trang quản lý WeChat Doanh nghiệp (work.weixin.qq.com) bằng tài khoản quản trị viên doanh nghiệp của bạn.
  2. Trên menu bên trái, tìm "Quản lý ứng dụng", sau đó nhấp vào "Ứng dụng" -> "Tự xây dựng", chọn "Tạo ứng dụng".
  3. Điền thông tin ứng dụng:
    • Tên ứng dụng: Đặt một tên dễ nhận biết, ví dụ "Trợ lý Phân tích Thị giác EVA-01".
    • Logo ứng dụng: Bạn có thể tải lên một biểu tượng liên quan đến EVA để tăng tính nhận diện. Khuyến nghị sử dụng biểu tượng màu tím, phù hợp với màu chủ đạo của EVA-01.
    • Giới thiệu ứng dụng: Mô tả ngắn gọn chức năng của ứng dụng, ví dụ "Trợ lý phân tích hình ảnh di động dựa trên EVA-01".
    • Phạm vi hiển thị: Chọn các phòng ban hoặc thành viên được phép sử dụng bot này. Bạn có thể chọn phòng ban của mình trước để kiểm tra.
  4. Nhấp vào "Tạo ứng dụng", hệ thống sẽ tạo trang thông tin riêng cho ứng dụng này.

2.2. Lấy thông tin cấu hình quan trọng

Sau khi tạo thành công, vào trang chi tiết ứng dụng, bạn cần tìm và ghi lại ba thông tin quan trọng sau. Những thông tin này tương đương với "chứng minh thư" và "chìa khóa" của bot, sẽ được sử dụng trong cấu hình mã sau này:

  • AgentId (ID ứng dụng): Mã định danh duy nhất của ứng dụng, trong trường "AgentId" trên trang chi tiết ứng dụng.
  • Secret (Khóa bí mật ứng dụng): Dùng để lấy mã truy cập (access token), trong khu vực "Chi tiết ứng dụng" -> "Secret", nhấp vào "Xem" để lấy.
  • CorpId (ID doanh nghiệp): Mã định danh duy nhất của doanh nghiệp bạn, tìm thấy trên trang "Doanh nghiệp của tôi" -> "Thông tin doanh nghiệp".

Lưu giữ cẩn thận những thông tin này, không tiết lộ cho người khác. Nên sao chép vào một tệp văn bản cục bộ để sử dụng khi cấu hình sau này.

2.3. Cấu hình cài đặt nhận tin nhắn

Đây là bước quan trọng nhất, cho WeChat Doanh nghiệp biết "khi có người gửi tin nhắn cho bot, tin nhắn đó nên được đẩy đến đâu".

  1. Trên trang chi tiết ứng dụng, tìm khu vực cài đặt "Nhận tin nhắn", nhấp vào nút "Cấu hình".
  2. Điền thông tin cấu hình callback:
    • URL: Ở đây bạn cần điền địa chỉ truy cập công cộng của máy chủ của bạn, và thêm một đường dẫn cụ thể. Ví dụ, nếu bạn nhận được địa chỉ từ ngrok là https://abc123.ngrok.io, thì ở đây có thể điền https://abc123.ngrok.io/wechat. Đường dẫn /wechat này là điểm vào mà chúng ta sẽ định nghĩa trong mã máy chủ sau này để nhận tin nhắn.
    • Token: Tự định nghĩa một chuỗi, ví dụ EVA01Key2024, dùng để xác minh nguồn tin nhắn. Bạn cần ghi nhớ Token này, sẽ sử dụng trong mã sau này.
    • EncodingAESKey: Nhấp vào nút "Tạo ngẫu nhiên", hệ thống sẽ tự động tạo một khóa mã hóa, dùng để mã hóa và giải mã tin nhắn.
  3. Chọn loại tin nhắn: Để nhận hình ảnh, bạn ít nhất cần chọn "Tin nhắn hình ảnh". Để có thể nhận lệnh văn bản (ví dụ: người dùng gửi "Phân tích xem có gì trong hình này"), bạn nên chọn cả "Tin nhắn văn bản".
  4. Nhấp vào "Lưu". Lúc này, WeChat Doanh nghiệp sẽ gửi một yêu cầu xác minh đến URL bạn đã điền. Nếu mã máy chủ của bạn chưa được viết, việc xác minh sẽ thất bại. Đừng lo lắng, chúng ta cứ lưu cấu hình trước, sau khi mã máy chủ chạy thì quay lại xác minh lại.

Bây giờ, bot đã được "đăng ký" bên WeChat Doanh nghiệp, chỉ chờ chương trình máy chủ của chúng ta kết nối.

3. Xây dựng cầu nối: Viết dịch vụ xử lý tin nhắn

Tiếp theo, chúng ta sẽ viết một chương trình Python trên máy chủ đang chạy EVA-01. Chương trình này giống như một tổng đài viên, chịu trách nhiệm nhận tin nhắn từ WeChat Doanh nghiệp, sau đó gọi EVA-01 để phân tích hình ảnh, và cuối cùng gửi kết quả trở lại.

3.1. Cài đặt các thư viện Python cần thiết

Mở terminal của máy chủ, thực hiện lệnh sau để cài đặt các thư viện cần thiết. Đây đều là các thư viện công cụ phổ biến trong Python:

pip install requests flask pillow
  • requests: Dùng để tải hình ảnh từ mạng, gọi API của WeChat Doanh nghiệp để gửi tin nhắn.
  • flask: Một framework Web nhẹ, dùng để nhanh chóng xây dựng một máy chủ có thể nhận các yêu cầu HTTP.
  • pillow: Thư viện xử lý hình ảnh của Python, dùng để xử lý các hình ảnh đã tải xuống.

Quá trình cài đặt thường rất nhanh. Nếu gặp vấn đề về mạng, bạn có thể thử sử dụng mirror trong nước.

3.2. Viết tập lệnh xử lý cốt lõi

Tạo một tệp Python mới, ví dụ wechat_eva_bot.py, sau đó sao chép đoạn mã sau vào. Có một số cấu hình quan trọng trong mã mà bạn cần sửa đổi theo tình hình thực tế:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Dịch vụ backend cho bot EVA-01 WeChat Doanh nghiệp
Nhận các thông báo đẩy từ WeChat Doanh nghiệp, gọi EVA-01 để phân tích hình ảnh và trả lời kết quả.
"""

import os
import json
import requests
from flask import Flask, request
import time
import hashlib
import xml.etree.ElementTree as ET
from datetime import datetime

# ========== KHU VỰC CẤU HÌNH: VUI LÒNG CHỈNH SỬA THEO THỰC TẾ ==========
# Cấu hình ứng dụng WeChat Doanh nghiệp (lấy từ trang quản lý)
MA_DOANH_NGHIEP = 'CorpID_cua_ban'  # Thay bằng ID doanh nghiệp của bạn
ID_UNG_DUNG = 'AgentId_cua_ban'  # Thay bằng ID ứng dụng của bạn
KHOA_BI_MAT = 'Secret_cua_ban'  # Thay bằng khóa bí mật ứng dụng của bạn

# Cấu hình nhận tin nhắn (phải khớp với cài đặt trong WeChat Doanh nghiệp)
KHOA_XAC_THUC = 'EVA01Key2024'  # Khớp với Token đã cài đặt trong WeChat Doanh nghiệp
KHOA_MA_HOA_AES = 'EncodingAESKey_cua_ban'  # Khớp với EncodingAESKey đã cài đặt

# Địa chỉ dịch vụ EVA-01
DIA_CHI_DICH_VU_EVA01 = "http://localhost:8501"  # Địa chỉ dịch vụ EVA-01 cục bộ

# Cấu hình máy chủ Flask
DIA_CHI_HOST = '0.0.0.0'  # Lắng nghe tất cả các giao diện mạng
CONG_KET_NOI = 5000        # Cổng dịch vụ, đảm bảo không bị chương trình khác chiếm dụng

# Đường dẫn lưu trữ tệp tạm thời
THU_MUC_TAM = './temp_uploads'
os.makedirs(THU_MUC_TAM, exist_ok=True)
# ======================================================================

app = Flask(__name__)

class BoGiaiMaWeChat:
    """Lớp công cụ mã hóa/giải mã tin nhắn WeChat Doanh nghiệp (phiên bản đơn giản)"""
    def __init__(self, token_key, aes_key, corp_id_val):
        self.token = token_key
        self.aes_key = aes_key
        self.corp_id = corp_id_val
    
    def xac_minh_url(self, chu_ky_tin_nhan, thoi_gian, ngau_nhien, echostr_val):
        """Xác minh tính hợp lệ của URL"""
        # Thực tế cần logic mã hóa/giải mã hoàn chỉnh
        # Ở đây trả về echostr_val để biểu thị xác minh thành công
        print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Xác minh URL - Chuỗi Echo: {echostr_val}")
        return echostr_val

bo_giai_ma_wechat = BoGiaiMaWeChat(KHOA_XAC_THUC, KHOA_MA_HOA_AES, MA_DOANH_NGHIEP)

def lay_access_token():
    """Lấy chứng chỉ gọi API của WeChat Doanh nghiệp (access_token)"""
    url_token = f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={MA_DOANH_NGHIEP}&corpsecret={KHOA_BI_MAT}"
    try:
        phan_hoi = requests.get(url_token, timeout=5).json()
        if phan_hoi.get('errcode') == 0:
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Lấy access_token thành công.")
            return phan_hoi.get('access_token')
        else:
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Lỗi khi lấy access_token: {phan_hoi}")
            return None
    except Exception as e:
        print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Ngoại lệ khi yêu cầu access_token: {e}")
        return None

def gui_tin_nhan_wechat(access_token_val, ma_nguoi_dung, noi_dung_tin_nhan):
    """Gửi tin nhắn văn bản đến người dùng cụ thể"""
    url_gui = f"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={access_token_val}"
    
    # Tin nhắn WeChat Doanh nghiệp có giới hạn độ dài, nếu quá dài cần chia đoạn
    if len(noi_dung_tin_nhan) > 2000:
        noi_dung_tin_nhan = noi_dung_tin_nhan[:1900] + "\n\n【Báo cáo quá dài, đã cắt bớt】"
    
    du_lieu_tin_nhan = {
        "touser": ma_nguoi_dung,
        "msgtype": "text",
        "agentid": int(ID_UNG_DUNG),
        "text": {
            "content": noi_dung_tin_nhan
        },
        "safe": 0  # Tin nhắn không bảo mật
    }
    
    try:
        phan_hoi = requests.post(url_gui, json=du_lieu_tin_nhan, timeout=10).json()
        if phan_hoi.get('errcode') != 0:
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Gửi tin nhắn thất bại: {phan_hoi}")
        else:
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Tin nhắn đã gửi: {phan_hoi.get('msgid')}")
    except Exception as e:
        print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Ngoại lệ khi gửi tin nhắn: {e}")

def tai_hinh_anh_wechat(media_id_val, access_token_val):
    """Tải hình ảnh tạm thời từ WeChat Doanh nghiệp"""
    url_tai = f"https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token={access_token_val}&media_id={media_id_val}"
    
    try:
        phan_hoi = requests.get(url_tai, stream=True, timeout=30)
        if phan_hoi.status_code == 200:
            # Tạo tên tệp tạm thời
            thoi_gian_st = int(time.time())
            duong_dan_tep = os.path.join(THU_MUC_TAM, f"wechat_img_{thoi_gian_st}.jpg")
            
            with open(duong_dan_tep, 'wb') as f:
                for chunk in phan_hoi.iter_content(chunk_size=8192):
                    f.write(chunk)
            
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Tải hình ảnh thành công: {duong_dan_tep}")
            return duong_dan_tep
        else:
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Tải hình ảnh thất bại, mã trạng thái: {phan_hoi.status_code}")
            return None
    except Exception as e:
        print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Ngoại lệ khi tải hình ảnh: {e}")
        return None

def phan_tich_anh_voi_eva01(duong_dan_anh, truy_van_nguoi_dung="Vui lòng phân tích hình ảnh này"):
    """
    Gọi EVA-01 để phân tích hình ảnh
    Lưu ý: Đây là một hàm ví dụ, cách gọi thực tế cần được điều chỉnh tùy theo cách triển khai cụ thể của EVA-01
    """
    print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] [Phân tích EVA-01] Bắt đầu xử lý hình ảnh: {duong_dan_anh}")
    print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] [Phân tích EVA-01] Chỉ thị người dùng: {truy_van_nguoi_dung}")
    
    # Bạn cần điều chỉnh phần này tùy theo cách triển khai thực tế của EVA-01
    # Phương án 1: Nếu EVA-01 cung cấp API HTTP
    # api_url_eva = f"{DIA_CHI_DICH_VU_EVA01}/api/analyze"
    # try:
    #     with open(duong_dan_anh, 'rb') as f:
    #         files_eva = {'image': f}
    #         data_eva = {'query': truy_van_nguoi_dung}
    #         response_eva = requests.post(api_url_eva, files=files_eva, data=data_eva, timeout=60)
    #     if response_eva.status_code == 200:
    #         ket_qua_eva = response_eva.json().get('result', 'Phân tích thất bại')
    #         return ket_qua_eva
    #     else:
    #         return f"Yêu cầu phân tích thất bại, mã trạng thái: {response_eva.status_code}"
    # except Exception as e:
    #     return f"Gọi API phân tích EVA-01 gặp ngoại lệ: {str(e)}"
    
    # Phương án 2: Nếu EVA-01 là dịch vụ cục bộ, có thể mô phỏng yêu cầu trình duyệt
    # Đây là một ví dụ triển khai mô phỏng
    try:
        # Mô phỏng quá trình phân tích
        time.sleep(3)  # Mô phỏng thời gian phân tích
        
        # Xây dựng báo cáo phân tích giả định
        bao_cao_phan_tich = [
            f"【Báo cáo phân tích thị giác EVA-01】\n",
            f"Thời gian phân tích: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n",
            f"Chỉ thị người dùng: {truy_van_nguoi_dung}\n",
            "=" * 40 + "\n",
            "Trạng thái đồng bộ: Liên kết thần kinh ổn định (tỷ lệ đồng bộ 400%)\n\n",
            "Kết quả phân tích hình ảnh:\n",
            "1. Phát hiện cấu trúc mạch điện tử (PCB).\n",
            "2. Nhận diện linh kiện chính: chip IC, tụ điện, mạng điện trở, cổng kết nối.\n",
            "3. Màu sắc PCB: Lớp chống hàn màu xanh lá, có dấu in lụa màu trắng trên bề mặt.\n",
            "4. Đặc điểm nổi bật: Chip màu đen lớn ở trung tâm, có logo nhà sản xuất và mã model.\n",
            "5. Tình trạng chi tiết: Các chân hàn tốt, không có hư hỏng vật lý rõ ràng.\n\n",
            "Đánh giá kỹ thuật:\n",
            "- Độ phức tạp mạch: Trung bình (thiết kế bo mạch nhiều lớp).\n",
            "- Mật độ linh kiện: Cao (độ tích hợp tốt).\n",
            "- Chất lượng gia công: Tiêu chuẩn công nghiệp.\n\n",
            "Kết luận phân tích:\n",
            "Đây là một bức ảnh cận cảnh bo mạch chủ thiết bị điện tử, có thể dùng cho mục đích gỡ lỗi hoặc kiểm tra chất lượng.\n",
            "Bố cục mạch hợp lý, chất lượng hàn tốt, không phát hiện lỗi rõ ràng.\n",
            "Khuyến nghị tiến hành kiểm tra nguồn để xác minh tính toàn vẹn chức năng.\n\n",
            "// Đồng bộ hóa thần kinh thị giác hoàn tất //"
        ]
        
        return ''.join(bao_cao_phan_tich)
        
    except Exception as e:
        return f"Quá trình phân tích gặp ngoại lệ: {str(e)}"

@app.route('/wechat', methods=['GET', 'POST'])
def xu_ly_wechat():
    """Xử lý tất cả các tin nhắn từ WeChat Doanh nghiệp"""
    if request.method == 'GET':
        # Xác minh URL callback của WeChat Doanh nghiệp
        chu_ky = request.args.get('msg_signature', '')
        thoi_gian_st = request.args.get('timestamp', '')
        ngau_nhien_str = request.args.get('nonce', '')
        echostr_req = request.args.get('echostr', '')
        
        print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Nhận yêu cầu xác minh: chu_ky={chu_ky}, thoi_gian={thoi_gian_st}, ngau_nhien={ngau_nhien_str}")
        
        # Xác minh tính hợp lệ của URL
        ket_qua = bo_giai_ma_wechat.xac_minh_url(chu_ky, thoi_gian_st, ngau_nhien_str, echostr_req)
        return ket_qua
    
    elif request.method == 'POST':
        # Xử lý thông báo đẩy tin nhắn
        try:
            # Lấy dữ liệu tin nhắn định dạng XML
            du_lieu_xml = request.data.decode('utf-8')
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Nhận tin nhắn XML: {du_lieu_xml}")
            
            # Phân tích XML
            cay_xml = ET.fromstring(du_lieu_xml)
            loai_tin_nhan = cay_xml.find('MsgType').text
            nguoi_gui = cay_xml.find('FromUserName').text
            nguoi_nhan = cay_xml.find('ToUserName').text
            
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Loại tin nhắn: {loai_tin_nhan}, Người gửi: {nguoi_gui}, Người nhận: {nguoi_nhan}")
            
            if loai_tin_nhan == 'text':
                # Xử lý tin nhắn văn bản
                noi_dung = cay_xml.find('Content').text
                print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Nhận tin nhắn văn bản: {noi_dung}")
                
                # Lấy access_token và trả lời
                token_truy_cap = lay_access_token()
                if token_truy_cap:
                    phan_hoi_van_ban = f"Đã nhận lệnh: '{noi_dung}'\nVui lòng gửi hình ảnh cần phân tích, tôi sẽ gọi EVA-01 để phân tích thị giác."
                    gui_tin_nhan_wechat(token_truy_cap, nguoi_gui, phan_hoi_van_ban)
                
                return 'success'
            
            elif loai_tin_nhan == 'image':
                # Xử lý tin nhắn hình ảnh
                media_id_anh = cay_xml.find('MediaId').text
                url_anh_goc = cay_xml.find('PicUrl').text
                
                print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Nhận tin nhắn hình ảnh, MediaId: {media_id_anh}")
                print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] URL hình ảnh: {url_anh_goc}")
                
                # Trả lời ngay lập tức tin nhắn "đang xử lý"
                token_truy_cap = lay_access_token()
                if token_truy_cap:
                    gui_tin_nhan_wechat(token_truy_cap, nguoi_gui, "🟣 Kích hoạt liên kết thần kinh thị giác...\nĐang phân tích sâu hình ảnh, vui lòng chờ một chút.")
                
                # Tải hình ảnh
                if token_truy_cap:
                    duong_dan_tep_anh = tai_hinh_anh_wechat(media_id_anh, token_truy_cap)
                    
                    if duong_dan_tep_anh and os.path.exists(duong_dan_tep_anh):
                        # Gọi EVA-01 để phân tích hình ảnh
                        # Có thể mở rộng để hỗ trợ các chỉ thị tùy chỉnh từ người dùng
                        ket_qua_phan_tich = phan_tich_anh_voi_eva01(duong_dan_tep_anh, "Phân tích chi tiết nội dung hình ảnh này")
                        
                        # Gửi kết quả phân tích
                        if ket_qua_phan_tich:
                            gui_tin_nhan_wechat(token_truy_cap, nguoi_gui, ket_qua_phan_tich)
                            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Kết quả phân tích đã gửi thành công")
                        
                        # Dọn dẹp tệp tạm thời
                        try:
                            os.remove(duong_dan_tep_anh)
                            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Tệp tạm thời đã được dọn dẹp: {duong_dan_tep_anh}")
                        except Exception as file_e:
                            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Lỗi khi xóa tệp tạm thời: {file_e}")
                    else:
                        gui_tin_nhan_wechat(token_truy_cap, nguoi_gui, "❌ Tải hình ảnh thất bại, vui lòng thử lại sau")
                
                return 'success'
            
            else:
                print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Loại tin nhắn chưa được hỗ trợ: {loai_tin_nhan}")
                return 'success'
                
        except Exception as e:
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Ngoại lệ khi xử lý tin nhắn: {e}")
            return 'success'

if __name__ == '__main__':
    print("=" * 50)
    print("Dịch vụ Bot EVA-01 WeChat Doanh nghiệp đang khởi động")
    print(f"Địa chỉ dịch vụ: http://{DIA_CHI_HOST}:{CONG_KET_NOI}")
    print(f"URL Callback dự kiến: http://DIA_CHI_CONG_CONG_CUA_BAN:{CONG_KET_NOI}/wechat")
    print("=" * 50)
    app.run(host=DIA_CHI_HOST, port=CONG_KET_NOI, debug=False)

3.3. Giải thích các điểm chính trong mã

Mặc dù đoạn mã này có vẻ dài, nhưng cấu trúc rất rõ ràng, chủ yếu chia thành các phần sau:

  1. Phần cấu hình: Khu vực cấu hình ở đầu mã yêu cầu bạn điền ba thông tin quan trọng lấy từ trang quản lý WeChat Doanh nghiệp: MA_DOANH_NGHIEP, ID_UNG_DUNG, KHOA_BI_MAT. Đây là thông tin xác thực của bot của bạn trong hệ thống WeChat Doanh nghiệp.
  2. Lớp mã hóa/giải mã tin nhắn: Lớp BoGiaiMaWeChat chịu trách nhiệm xử lý việc mã hóa và giải mã tin nhắn của WeChat Doanh nghiệp. Để đảm bảo an toàn, WeChat Doanh nghiệp sẽ mã hóa tin nhắn khi truyền tải; lớp này dùng để giải mã các tin nhắn nhận được và mã hóa các tin nhắn gửi đi.
  3. Các hàm chức năng cốt lõi:
    • lay_access_token(): Lấy chứng chỉ gọi API của WeChat Doanh nghiệp (access token), token này có thời hạn 2 giờ.
    • gui_tin_nhan_wechat(): Gửi tin nhắn văn bản cho người dùng WeChat Doanh nghiệp.
    • tai_hinh_anh_wechat(): Tải hình ảnh do người dùng gửi từ máy chủ WeChat Doanh nghiệp.
    • phan_tich_anh_voi_eva01(): Hàm cốt lõi để gọi EVA-01 phân tích hình ảnh.
  4. Dịch vụ Web Flask: Hàm xu_ly_wechat() là điểm vào để xử lý tin nhắn, nó nhận các tin nhắn đẩy từ WeChat Doanh nghiệp và xử lý khác nhau tùy theo loại tin nhắn (văn bản hoặc hình ảnh).
  5. Phần gọi EVA-01: Hàm phan_tich_anh_voi_eva01() hiện tại là một triển khai mô phỏng. Trong triển khai thực tế, bạn cần sửa đổi hàm này để thực sự gọi khả năng phân tích của EVA-01, tùy thuộc vào cách triển khai cụ thể của dự án EVA-01.

3.4. Khởi động dịch vụ và hoàn tất xác minh

  1. Sửa đổi tệp cấu hình: Mở tệp wechat_eva_bot.py, tìm khu vực cấu hình ở đầu tệp, thay thế MA_DOANH_NGHIEP, ID_UNG_DUNG, KHOA_BI_MAT bằng các giá trị thực tế bạn lấy từ trang quản lý WeChat Doanh nghiệp.
  2. Khởi động dịch vụ: Trong terminal, chạy tập lệnh của bạn:
    python wechat_eva_bot.py
            
    Nếu mọi thứ bình thường, bạn sẽ thấy thông tin nhật ký khởi động dịch vụ.
  3. Cấu hình truy cập công cộng: Nếu bạn đang phát triển cục bộ, bạn cần sử dụng công cụ xuyên hầm nội mạng để đưa cổng 5000 cục bộ ra công cộng. Ví dụ với ngrok:
    ngrok http 5000
            
    Sau khi chạy, ngrok sẽ cung cấp cho bạn một địa chỉ công cộng tương tự https://abc123.ngrok.io.
  4. Hoàn tất xác minh WeChat Doanh nghiệp: Quay lại trang quản lý WeChat Doanh nghiệp, trên trang cấu hình "Nhận tin nhắn" của ứng dụng, sửa URL thành https://DIA_CHI_NGROK_CUA_BAN/wechat, sau đó nhấp "Lưu". Lần này, vì dịch vụ Flask của bạn đang chạy, việc xác minh sẽ thành công.

4. Kiểm tra thực tế: Từ chụp ảnh điện thoại đến phân tích AI

Bây giờ là lúc thú vị nhất. Hãy cùng kiểm tra xem toàn bộ hệ thống có hoạt động bình thường không.

4.1. Kiểm tra chức năng cơ bản

  1. Mở WeChat Doanh nghiệp của bạn, tìm cửa sổ trò chuyện nhóm hoặc cá nhân nơi bạn đã cài đặt "Trợ lý Phân tích Thị giác EVA-01".
  2. Gửi một hình ảnh thử nghiệm. Bạn có thể:
    • Chụp một bức ảnh tại chỗ (ví dụ: bàn làm việc của bạn, bìa sách)
    • Chọn một hình ảnh từ thư viện ảnh điện thoại
    • Gửi một hình ảnh từ Internet
  3. Quan sát quá trình phản hồi:
    • Sau khi gửi hình ảnh, bạn sẽ nhận được ngay một tin nhắn gợi ý "🟣 Kích hoạt liên kết thần kinh thị giác..."
    • Chờ vài giây (tùy thuộc vào kích thước hình ảnh và tốc độ mạng)
    • Nếu mọi thứ bình thường, bạn sẽ nhận được báo cáo phân tích chi tiết về hình ảnh đó từ EVA-01.

4.2. Khắc phục sự cố thường gặp

Nếu gặp vấn đề trong quá trình kiểm tra, bạn có thể tham khảo các bước sau để khắc phục:

  1. Dịch vụ chưa khởi động: Kiểm tra xem python wechat_eva_bot.py có chạy bình thường không, terminal có báo lỗi gì không.
  2. Vấn đề kết nối mạng: Đảm bảo máy chủ của bạn có thể truy cập Internet và WeChat Doanh nghiệp có thể truy cập địa chỉ công cộng bạn đã cấu hình.
  3. Thông tin cấu hình sai: Kiểm tra kỹ xem MA_DOANH_NGHIEP, ID_UNG_DUNG, KHOA_BI_MAT đã được điền chính xác chưa, chú ý không có khoảng trắng thừa.
  4. Cổng bị chiếm dụng: Nếu cổng 5000 bị chương trình khác chiếm dụng, bạn có thể sửa đổi biến CONG_KET_NOI trong mã để sử dụng cổng khác (như 5001, 8080, v.v.).
  5. Xác minh WeChat Doanh nghiệp thất bại: Kiểm tra xem Token và EncodingAESKey có khớp với cấu hình trong WeChat Doanh nghiệp không.

4.3. Kiểm tra các tình huống khác nhau

Để đảm bảo hệ thống ổn định, bạn nên kiểm tra các tình huống sau:

  1. Hình ảnh kích thước khác nhau: Kiểm tra xử lý hình ảnh nhỏ (vài chục KB) và hình ảnh lớn (vài MB).
  2. Hình ảnh định dạng khác nhau: Kiểm tra các định dạng phổ biến như JPG, PNG.
  3. Tình huống mạng không ổn định: Mô phỏng môi trường mạng yếu, xem hệ thống có xử lý timeout không.
  4. Yêu cầu đồng thời: Gửi nhiều hình ảnh cùng lúc, kiểm tra khả năng xử lý của hệ thống.

5. Tối ưu nâng cao: Hoàn thiện hệ thống

Sau khi xây dựng chức năng cơ bản, chúng ta có thể tối ưu hệ thống từ một số khía cạnh để nó ổn định, thông minh và dễ sử dụng hơn.

5.1. Tích hợp khả năng phân tích EVA-01 thực tế

Hiện tại, hàm phan_tich_anh_voi_eva01() của chúng ta vẫn là triển khai mô phỏng. Để thực sự gọi EVA-01, bạn cần điều chỉnh tùy theo cách triển khai cụ thể của dự án EVA-01:

Nếu EVA-01 cung cấp API HTTP:

def phan_tich_anh_voi_eva01_thuc_te(duong_dan_anh, truy_van_nguoi_dung):
    """Gọi API EVA-01 thực tế"""
    api_url_thuc = f"{DIA_CHI_DICH_VU_EVA01}/api/analyze"
    
    try:
        with open(duong_dan_anh, 'rb') as f:
            cac_tep = {'image': f}
            du_lieu_gui = {
                'query': truy_van_nguoi_dung,
                'model': 'qwen2.5-vl-7b', # Tên model cụ thể của EVA-01
                'max_tokens': 1000
            }
            phan_hoi = requests.post(api_url_thuc, files=cac_tep, data=du_lieu_gui, timeout=60)
        
        if phan_hoi.status_code == 200:
            ket_qua_json = phan_hoi.json()
            # Phân tích kết quả theo định dạng trả về thực tế của EVA-01
            phan_tich = ket_qua_json.get('analysis', 'Không có kết quả phân tích.')
            do_tin_cay = ket_qua_json.get('confidence', 0)
            return f"Kết quả phân tích (Độ tin cậy: {do_tin_cay}%):\n{phan_tich}"
        else:
            return f"Dịch vụ phân tích EVA-01 tạm thời không khả dụng. Mã: {phan_hoi.status_code}"
            
    except Exception as e:
        return f"Gọi EVA-01 phân tích thất bại: {str(e)}"

Nếu EVA-01 là dịch vụ Python cục bộ:

import torch
from PIL import Image # Cần cài đặt thư viện Pillow nếu chưa có: pip install Pillow

def phan_tich_anh_voi_eva01_cuc_bo(duong_dan_anh, truy_van_nguoi_dung):
    """Trực tiếp gọi mô hình EVA-01 cục bộ"""
    # Import các module liên quan của EVA-01 (giả định có trong thư mục hiện tại hoặc PYTHONPATH)
    try:
        from eva_model import EVAProcessor, EVAModel
    except ImportError:
        return "Lỗi: Không thể tìm thấy module EVA-01 cục bộ. Đảm bảo EVA-01 đã được cài đặt và cấu hình."
    
    # Khởi tạo mô hình (nếu chưa được khởi tạo)
    if not hasattr(phan_tich_anh_voi_eva01_cuc_bo, 'bo_xu_ly'):
        print("[EVA-01 Cục bộ] Đang khởi tạo bộ xử lý và mô hình...")
        phan_tich_anh_voi_eva01_cuc_bo.bo_xu_ly = EVAProcessor.from_pretrained("eva-processor-path") # Thay bằng đường dẫn thực tế
        phan_tich_anh_voi_eva01_cuc_bo.mo_hinh = EVAModel.from_pretrained("eva-model-path") # Thay bằng đường dẫn thực tế
        print("[EVA-01 Cục bộ] Khởi tạo hoàn tất.")
    
    # Tải và xử lý hình ảnh
    hinh_anh = Image.open(duong_dan_anh).convert("RGB")
    dau_vao = phan_tich_anh_voi_eva01_cuc_bo.bo_xu_ly(
        images=hinh_anh,
        text=truy_van_nguoi_dung,
        return_tensors="pt"
    )
    
    # Chạy suy luận
    with torch.no_grad():
        dau_ra = phan_tich_anh_voi_eva01_cuc_bo.mo_hinh.generate(**dau_vao)
    
    # Giải mã kết quả
    ket_qua = phan_tich_anh_voi_eva01_cuc_bo.bo_xu_ly.decode(dau_ra[0], skip_special_tokens=True)
    return ket_qua

5.2. Thêm hàng đợi tin nhắn và xử lý bất đồng bộ

Khi có nhiều người dùng cùng lúc gửi hình ảnh, xử lý đồng bộ có thể dẫn đến timeout. Chúng ta có thể giới thiệu hàng đợi tin nhắn để thực hiện xử lý bất đồng bộ:

from threading import Thread
from queue import Queue
import uuid

# Tạo hàng đợi tác vụ
hang_doi_tac_vu = Queue()

def luong_xu_ly_tac_vu():
    """Luồng làm việc, lấy tác vụ từ hàng đợi và xử lý"""
    while True:
        tac_vu = hang_doi_tac_vu.get()
        if tac_vu is None: # Tín hiệu dừng luồng
            break
        
        ma_nguoi_dung, duong_dan_anh_tac_vu, truy_van_nguoi_dung_tac_vu = tac_vu
        try:
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Đang xử lý tác vụ cho người dùng {ma_nguoi_dung}...")
            # Gọi EVA-01 phân tích (sử dụng hàm thực tế hoặc hàm mô phỏng)
            ket_qua_tac_vu = phan_tich_anh_voi_eva01(duong_dan_anh_tac_vu, truy_van_nguoi_dung_tac_vu)
            
            # Gửi kết quả
            token_truy_cap = lay_access_token()
            if token_truy_cap:
                gui_tin_nhan_wechat(token_truy_cap, ma_nguoi_dung, ket_qua_tac_vu)
                print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Đã gửi kết quả phân tích cho {ma_nguoi_dung}.")
            
            # Dọn dẹp tệp tạm thời sau khi xử lý
            if os.path.exists(duong_dan_anh_tac_vu):
                os.remove(duong_dan_anh_tac_vu)
                print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Đã dọn dẹp tệp tạm thời: {duong_dan_anh_tac_vu}")

        except Exception as e:
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Lỗi khi xử lý tác vụ cho {ma_nguoi_dung}: {e}")
            token_truy_cap = lay_access_token()
            if token_truy_cap:
                gui_tin_nhan_wechat(token_truy_cap, ma_nguoi_dung, f"❌ Lỗi khi phân tích hình ảnh của bạn: {str(e)}")
        finally:
            hang_doi_tac_vu.task_done()

# Khởi động các luồng làm việc
SO_LUONG_LUONG_WORKER = 3 # Số lượng luồng xử lý đồng thời
for i in range(SO_LUONG_LUONG_WORKER):
    luong = Thread(target=luong_xu_ly_tac_vu)
    luong.daemon = True # Đặt luồng là daemon để tự động dừng khi chương trình chính kết thúc
    luong.start()

# Trong hàm xử lý tin nhắn hình ảnh, thay vì xử lý trực tiếp, hãy đưa vào hàng đợi:
# Ví dụ trong phần 'elif msg_type == 'image':' của hàm xu_ly_wechat
# ...
# # Thay thế phần tải và phân tích hình ảnh bằng việc đưa vào hàng đợi
# if token_truy_cap:
#     duong_dan_tep_anh = tai_hinh_anh_wechat(media_id_anh, token_truy_cap)
#     if duong_dan_tep_anh and os.path.exists(duong_dan_tep_anh):
#         # Thêm tác vụ vào hàng đợi
#         hang_doi_tac_vu.put((nguoi_gui, duong_dan_tep_anh, "Phân tích chi tiết nội dung hình ảnh này"))
#         gui_tin_nhan_wechat(token_truy_cap, nguoi_gui, 
#                            "🟣 Yêu cầu của bạn đã được tiếp nhận.\nĐang xếp hàng xử lý, vui lòng chờ đợi.")
#     else:
#         gui_tin_nhan_wechat(token_truy_cap, nguoi_gui, "❌ Tải hình ảnh thất bại, vui lòng thử lại.")
# ...

5.3. Hỗ trợ thêm loại tin nhắn và lệnh

Ngoài phân tích hình ảnh cơ bản, chúng ta có thể mở rộng chức năng hệ thống:

Hỗ trợ lệnh văn bản:

def xu_ly_lenh_van_ban(noi_dung_lenh, ma_nguoi_dung):
    """Xử lý các lệnh văn bản"""
    lenh_kha_dung = {
        'help': hien_thi_tro_giup,
        'status': kiem_tra_trang_thai,
        'history': xem_lich_su,
        'settings': cap_nhat_cai_dat
    }
    
    noi_dung_lenh_lower = noi_dung_lenh.lower().strip()
    
    for cmd, handler in lenh_kha_dung.items():
        if noi_dung_lenh_lower.startswith(cmd):
            return handler(ma_nguoi_dung, noi_dung_lenh_lower[len(cmd):].strip())
    
    # Nếu không có lệnh nào khớp, trả về phản hồi mặc định
    return ("Vui lòng nhập một trong các lệnh sau:\n"
            "1. help - Xem hướng dẫn sử dụng\n"
            "2. status - Kiểm tra trạng thái hệ thống\n"
            "3. history - Xem lịch sử phân tích\n"
            "4. settings [tham_so] - Thay đổi cài đặt phân tích")

def hien_thi_tro_giup(ma_nguoi_dung, _):
    return "Tôi là trợ lý phân tích hình ảnh EVA-01. Hãy gửi cho tôi một hình ảnh để tôi phân tích!"

def kiem_tra_trang_thai(ma_nguoi_dung, _):
    # Logic kiểm tra trạng thái hệ thống
    return f"Hệ thống EVA-01 đang hoạt động bình thường.\nSố tác vụ đang chờ: {hang_doi_tac_vu.qsize()}"

def xem_lich_su(ma_nguoi_dung, _):
    # Logic lấy lịch sử từ cơ sở dữ liệu hoặc bộ nhớ cache
    return "Chức năng lịch sử đang được phát triển..."

def cap_nhat_cai_dat(ma_nguoi_dung, tham_so):
    # Logic cập nhật cài đặt người dùng
    if tham_so:
        return f"Đã nhận yêu cầu cài đặt: '{tham_so}'. Đang xử lý..."
    return "Vui lòng cung cấp tham số cho cài đặt. Ví dụ: settings language=vi"

# Trong hàm xu_ly_wechat, phần xử lý tin nhắn văn bản:
# ...
#             elif loai_tin_nhan == 'text':
#                 noi_dung = cay_xml.find('Content').text
#                 print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Nhận tin nhắn văn bản: {noi_dung}")
#                 
#                 token_truy_cap = lay_access_token()
#                 if token_truy_cap:
#                     phan_hoi_van_ban = xu_ly_lenh_van_ban(noi_dung, nguoi_gui)
#                     gui_tin_nhan_wechat(token_truy_cap, nguoi_gui, phan_hoi_van_ban)
#                 
#                 return 'success'
# ...

Hỗ trợ đối thoại đa lượt:

# Sử dụng dictionary để lưu ngữ cảnh đối thoại
ngu_canh_doi_thoai = {}

def xu_ly_doi_thoai(ma_nguoi_dung, tin_nhan, loai_tin_nhan):
    """Xử lý đối thoại đa lượt"""
    if ma_nguoi_dung not in ngu_canh_doi_thoai:
        ngu_canh_doi_thoai[ma_nguoi_dung] = {
            'hinh_anh_cuoi': None,
            'truy_van_cuoi': None,
            'lich_su': []
        }
    
    ngu_canh = ngu_canh_doi_thoai[ma_nguoi_dung]
    
    if loai_tin_nhan == 'image':
        # Lưu đường dẫn hình ảnh (giả sử đã tải xuống)
        ngu_canh['hinh_anh_cuoi'] = tin_nhan # tin_nhan ở đây là đường dẫn tệp ảnh
        return "Hình ảnh đã nhận. Vui lòng gửi chỉ thị phân tích hoặc câu hỏi về ảnh này."
    
    elif loai_tin_nhan == 'text':
        if ngu_canh['hinh_anh_cuoi']:
            # Nếu có hình ảnh đang chờ phân tích, sử dụng văn bản của người dùng làm chỉ thị
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Đang phân tích hình ảnh {ngu_canh['hinh_anh_cuoi']} với lệnh: {tin_nhan}")
            ket_qua = phan_tich_anh_voi_eva01(ngu_canh['hinh_anh_cuoi'], tin_nhan)
            ngu_canh['lich_su'].append({
                'hinh_anh': ngu_canh['hinh_anh_cuoi'],
                'truy_van': tin_nhan,
                'ket_qua': ket_qua,
                'thoi_gian': datetime.now()
            })
            # Xóa hình ảnh cuối cùng sau khi phân tích để chờ hình ảnh mới
            os.remove(ngu_canh['hinh_anh_cuoi'])
            ngu_canh['hinh_anh_cuoi'] = None
            return ket_qua
        else:
            return "Vui lòng gửi hình ảnh cần phân tích trước."

# Cập nhật hàm xu_ly_wechat để sử dụng xu_ly_doi_thoai
# ...
#             if loai_tin_nhan == 'text':
#                 noi_dung = cay_xml.find('Content').text
#                 print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Nhận tin nhắn văn bản: {noi_dung}")
#                 
#                 token_truy_cap = lay_access_token()
#                 if token_truy_cap:
#                     phan_hoi_doi_thoai = xu_ly_doi_thoai(nguoi_gui, noi_dung, 'text')
#                     gui_tin_nhan_wechat(token_truy_cap, nguoi_gui, phan_hoi_doi_thoai)
#                 return 'success'
#             
#             elif loai_tin_nhan == 'image':
#                 media_id_anh = cay_xml.find('MediaId').text
#                 url_anh_goc = cay_xml.find('PicUrl').text
#                 
#                 token_truy_cap = lay_access_token()
#                 if token_truy_cap:
#                     duong_dan_tep_anh = tai_hinh_anh_wechat(media_id_anh, token_truy_cap)
#                     if duong_dan_tep_anh and os.path.exists(duong_dan_tep_anh):
#                         phan_hoi_doi_thoai = xu_ly_doi_thoai(nguoi_gui, duong_dan_tep_anh, 'image')
#                         gui_tin_nhan_wechat(token_truy_cap, nguoi_gui, phan_hoi_doi_thoai)
#                     else:
#                         gui_tin_nhan_wechat(token_truy_cap, nguoi_gui, "❌ Tải hình ảnh thất bại.")
#                 return 'success'
# ...

5.4. Thêm nhật ký và giám sát

Để dễ dàng khắc phục sự cố và giám sát trạng thái hoạt động của hệ thống, chúng ta có thể thêm ghi nhật ký chi tiết:

import logging
from logging.handlers import RotatingFileHandler

# Cấu hình nhật ký
def thiet_lap_ghi_nhat_ky():
    logger_obj = logging.getLogger('wechat_eva_bot')
    logger_obj.setLevel(logging.INFO)
    
    # Ghi nhật ký vào tệp
    handler_tep = RotatingFileHandler(
        'eva_bot.log', 
        maxBytes=10*1024*1024,  # 10MB
        backupCount=5
    )
    handler_tep.setLevel(logging.INFO)
    
    # Ghi nhật ký ra console
    handler_console = logging.StreamHandler()
    handler_console.setLevel(logging.INFO)
    
    # Định dạng nhật ký
    formatter_log = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    handler_tep.setFormatter(formatter_log)
    handler_console.setFormatter(formatter_log)
    
    logger_obj.addHandler(handler_tep)
    logger_obj.addHandler(handler_console)
    
    return logger_obj

# Sử dụng logger trong mã
logger = thiet_lap_ghi_nhat_ky()

# Ví dụ về cách sử dụng logger trong hàm xử lý tin nhắn chính (xu_ly_wechat)
# ...
#     if request.method == 'GET':
#         logger.info(f"Nhận yêu cầu xác minh URL từ WeChat: {request.args}")
#         # ... (logic xử lý GET)
#     elif request.method == 'POST':
#         try:
#             du_lieu_xml = request.data.decode('utf-8')
#             logger.info(f"Nhận tin nhắn XML từ WeChat: {du_lieu_xml}")
#             # ... (logic xử lý POST)
#         except Exception as e:
#             logger.error(f"Lỗi khi xử lý tin nhắn WeChat: {e}", exc_info=True)
#             return 'success'
# ...

6. Tổng kết và định hướng

Thông qua hướng dẫn này, chúng ta đã thành công kết hợp hệ thống phân tích thị giác EVA-01 với bot WeChat Doanh nghiệp, tạo ra một giải pháp phân tích hình ảnh trên di động không cần code (hoặc ít code). Hệ thống này không chỉ đơn giản trong triển khai kỹ thuật mà còn có giá trị ứng dụng thực tế cao.

6.1. Giá trị cốt lõi

Hãy cùng nhìn lại những giá trị cốt lõi mà hệ thống này mang lại:

  1. Làm việc di động: Mở rộng khả năng phân tích thị giác AI mạnh mẽ ra thiết bị di động, cho phép chụp ảnh và phân tích mọi lúc, mọi nơi.
  2. Triển khai không cần code: Dựa trên hệ thống EVA-01 hiện có, chỉ cần cấu hình và script đơn giản là có thể triển khai.
  3. Tích hợp liền mạch: Tích hợp sâu với WeChat Doanh nghiệp, phù hợp với thói quen làm việc của hầu hết các doanh nghiệp.
  4. Phản hồi nhanh chóng: Từ chụp ảnh đến nhận kết quả phân tích, toàn bộ quá trình chỉ mất vài giây.
  5. Dễ dàng mở rộng: Thiết kế mô-đun cho phép dễ dàng thêm các chức năng mới.

6.2. Các tình huống ứng dụng thực tế

Hệ thống này có thể phát huy tác dụng trong nhiều tình huống:

  • Kiểm tra công nghiệp: Công nhân tại chỗ chụp ảnh thiết bị, hệ thống tự động phân tích trạng thái thiết bị và các vấn đề tiềm ẩn.
  • Kiểm tra chất lượng: Nhân viên QC chụp ảnh sản phẩm, hệ thống tự động nhận diện lỗi và khuyết tật.
  • Xử lý tài liệu: Chụp ảnh tài liệu giấy, hệ thống tự động trích xuất nội dung văn bản và sắp xếp.
  • Giáo dục và đào tạo: Học sinh chụp ảnh bài tập, nhận được hướng dẫn giải và lời giải.
  • Hỗ trợ y tế: Chụp ảnh y tế (cần tuân thủ quy định), hỗ trợ phân tích sơ bộ.

6.3. Hướng tối ưu hóa trong tương lai

Mặc dù chúng ta đã xây dựng một hệ thống khả dụng, nhưng vẫn còn nhiều không gian để tối ưu hóa, như:

  1. Tối ưu hiệu suất: Giới thiệu cơ chế caching để lưu trữ kết quả phân tích của các hình ảnh giống nhau.
  2. Mở rộng chức năng: Hỗ trợ xử lý hàng loạt hình ảnh, xuất kết quả phân tích, truy vấn lịch sử.
  3. Tăng cường bảo mật: Thêm xác thực người dùng, kiểm soát truy cập, mã hóa dữ liệu.
  4. Trải nghiệm người dùng: Phát triển giao diện quản lý thân thiện hơn, hỗ trợ tùy chỉnh mẫu phân tích.
  5. Hỗ trợ đa nền tảng: Mở rộng hỗ trợ các nền tảng văn phòng khác như DingTalk, Feishu.

6.4. Đề xuất triển khai

Đối với việc triển khai trong môi trường sản xuất, khuyến nghị xem xét các điểm sau:

  1. Sử dụng tên miền chính thức: Thay thế ngrok và các giải pháp tạm thời khác bằng tên miền chính thức và chứng chỉ HTTPS.
  2. Cấu hình cân bằng tải: Nếu lượng người dùng lớn, cần xem xét triển khai nhiều instance và cân bằng tải.
  3. Tích hợp cơ sở dữ liệu: Sử dụng cơ sở dữ liệu để lưu trữ lịch sử phân tích, cấu hình người dùng và các thông tin quan trọng khác.
  4. Giám sát và cảnh báo: Cấu hình giám sát hệ thống, thông báo kịp thời cho quản trị viên khi có sự cố.
  5. Sao lưu định kỳ: Sao lưu định kỳ các tệp cấu hình và dữ liệu quan trọng.

Thẻ: EVA-01 WeChat Work Enterprise WeChat Image Analysis Mobile AI

Đăng vào ngày 12 tháng 7 lúc 04:26