Chuyển đến nội dung chính

Qwen-Agent: Hướng dẫn kèm dự án minh họa

Tìm hiểu cách sử dụng Qwen-Agent và Qwen3 để xây dựng tiện ích tóm tắt nội dung trang web theo thời gian thực.
Đã cập nhật 5 thg 10, 2026  · 12 phút đọc

Khám phá cùng AI

ChatGPTClaudePerplexity

Trong bài viết này, tôi sẽ hướng dẫn bạn xây dựng một tiện ích trình duyệt sử dụng Qwen-Agent để tóm tắt nội dung của bất kỳ trang web nào theo thời gian thực. Chúng ta sẽ đề cập cách:

  • Sử dụng mô hình Qwen3 của Alibaba cục bộ qua Ollama
  • Dùng Qwen-Agent cho nhắc lệnh có cấu trúc và sử dụng công cụ
  • Xây dựng tiện ích Chrome với cập nhật giao diện theo luồng
  • Thêm backend FastAPI để hỗ trợ tóm tắt theo thời gian thực

Kết thúc bài, bạn sẽ có một tác nhân tóm tắt hoạt động ngoại tuyến, chạy bằng Qwen3, có thể đọc và tóm tắt trang web ngay trong trình duyệt chỉ với một cú nhấp.

Chúng tôi cập nhật cho độc giả những điều mới nhất về AI qua The Median, bản tin miễn phí mỗi thứ Sáu tóm lược các câu chuyện quan trọng trong tuần. Đăng ký và nắm bắt thông tin chỉ trong vài phút mỗi tuần:

Qwen-Agent là gì?

Qwen-Agent là một framework Python gọn nhẹ do Alibaba xây dựng để phát triển các ứng dụng LLM mạnh mẽ với họ mô hình Qwen3. Dự án tập trung hỗ trợ:

  • Tác nhân làm theo hướng dẫn
  • Sử dụng công cụ và gọi hàm
  • Bộ nhớ và lập kế hoạch đa lượt
  • Nhắc lệnh linh hoạt qua thông điệp có cấu trúc

Cốt lõi của Qwen-Agent là đơn giản hóa việc phát triển các tác nhân AI mô-đun với năng lực lập luận vững và thực thi mã. Nó bao gồm các thành phần nguyên tử như wrapper LLM và công cụ, cũng như các lớp Agent cấp cao để điều phối quy trình.

Qwen-Agent hoạt động với cả API đám mây (như Alibaba DashScope) và runtime tương thích OpenAI cục bộ như vLLM và Ollama. Nó giúp bạn xây dựng ứng dụng LLM mạnh mẽ một cách dễ dàng với:

  • Tích hợp nhanh qua FastAPI
  • Streaming tích hợp sẵn cho frontend
  • Chuỗi công cụ hàm có thể tùy biến
  • Quyền riêng tư và hiệu năng hoàn toàn ngoại tuyến

Tổng quan dự án: Tiện ích tóm tắt web thời gian thực

Trong phần này, chúng ta sẽ xây dựng một tiện ích tóm tắt theo thời gian thực sử dụng Qwen-Agent. Bao gồm:

  • Backend FastAPI nhận văn bản trang web và trả về bản tóm tắt
  • Cửa sổ pop-up của tiện ích Chrome để lấy nội dung trang đang hiển thị
  • Giao diện streaming khi bản tóm tắt được tạo
  • Backend chạy Qwen3:1.7B cục bộ qua Ollama

Hãy cùng đi qua từng phần của dự án.

Bước 1: Thiết lập backend Qwen3

Ở bước này, chúng ta sẽ xem tất cả các tệp mã cần thiết để backend hoạt động đồng bộ với tiện ích.

Bước 1.1: Phụ thuộc và thư viện 

Bắt đầu bằng cách cài đặt ollama trên hệ thống của bạn. Tiếp theo, liệt kê tất cả phụ thuộc Python cần cho backend trong requirements.txt. Việc này giúp đảm bảo môi trường nhất quán giữa các máy và container.

fastapi
uvicorn
python-dateutil
python-dotenv
qwen-agent[code_interpreter]
matplotlib

Dưới đây là vai trò của từng thư viện:

  • qwen-agent[code_interpreter]: Framework tác nhân cốt lõi hỗ trợ dùng công cụ, cho phép thực thi mã và lập luận có cấu trúc.
  • fastapi và uvicorn: Kết hợp để vận hành backend API bất đồng bộ và phục vụ logic tóm tắt.
  • python-dotenv và python-dateutil: Thư viện tiện ích xử lý biến môi trường và thời gian/ngày (hữu ích khi mở rộng sau này).
  • matplotlib: Dùng để vẽ biểu đồ hoặc hiển thị đầu ra trực quan (tùy chọn) 

Nếu muốn chạy dự án cục bộ, hãy chạy lệnh sau để cài mọi phụ thuộc:

pip install -r requirements.txt

Bước 1.2: Thiết lập DockerFile (tùy chọn)

Giờ hãy thiết lập Dockerfile tạo môi trường Python tối giản với ứng dụng của chúng ta và mở cổng 7864, cho phép tiện ích Chrome gửi yêu cầu đến backend FastAPI.

FROM python:3.10

WORKDIR /app
COPY . .

RUN pip install --no-cache-dir -r requirements.txt

EXPOSE 7864

CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7864"]

Thiết lập này là tùy chọn nếu bạn chọn chạy dự án cục bộ bằng Uvicorn thay vì Docker.

Bước 1.3: Phục vụ Qwen với Ollama

Tiếp theo, bạn cần kéo và phục vụ mô hình Qwen3 cục bộ bằng Ollama. Bước này cho phép suy luận ngoại tuyến bằng cách lưu trữ dịch vụ LLM trên máy của bạn.

ollama pull qwen3:1.7b
ollama serve 

Bước 1.4: Xây dựng máy chủ tóm tắt FastAPI

Tệp app.py định nghĩa một máy chủ FastAPI stream bản tóm tắt theo thời gian thực của nội dung trang web, sử dụng mô hình Qwen3:1.7B chạy cục bộ qua Qwen-Agent.

Bước 1.4.1: Import

Bắt đầu với việc import FastAPI, tiện ích streaming, và các thành phần Qwen-Agent như Assistant, lớp bọc mô hình và khả năng công cụ của nó.

import re
from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from typing import List, Dict, Any
from qwen_agent.agents import Assistant
import logging

Bước 1.4.2: Khởi tạo ứng dụng FastAPI

Tiếp theo, chúng ta định nghĩa schema RequestData đơn giản để nhận nội dung, và tạo một phiên bản bot của Assistant. 

app = FastAPI()
class RequestData(BaseModel):
    content: str
bot = Assistant(
    llm={
        "model": "qwen3:1.7b",
        "model_server": "http://localhost:11434/v1",
        "api_key": "EMPTY"
    },
    function_list=["code_interpreter"],
    system_message="You are a summarization assistant. Directly output the cleaned summary of the given text without any reasoning, self-talk, thoughts, or internal planning steps. Do not include phrases like 'I think', 'maybe', 'let's', 'the user wants', or anything not part of the final summary. Your output must look like it was written by an editor, not a model."
)

Trong đoạn mã trên, bot là một thể hiện của lớp Assistant từ Qwen-Agent, được cấu hình để tương tác với mô hình Qwen3:1.7B phục vụ cục bộ qua Ollama. Nó dùng công cụ tích hợp code_interpreter để lập luận qua nội dung và thực thi Python khi cần. system_message tùy chỉnh định hướng hành vi để tạo bản tóm tắt trang gọn gàng.

Lưu ý: Bạn có thể dùng các mô hình nhỏ hơn như qwen3:0.6b hoặc qwen3:1.7b để giảm đáng kể thời gian phản hồi và bộ nhớ. Điều này đặc biệt hữu ích cho các tác vụ tóm tắt nhanh không đòi hỏi nhiều lập luận.

Bước 1.4.3: Route tóm tắt

Cuối cùng, một endpoint đọc nội dung đến và phát luồng văn bản tóm tắt trực tiếp khi mô hình tạo ra. Nó dùng đầu ra streaming để người dùng không phải chờ phản hồi hoàn chỉnh.

@app.post("/summarize_stream_status")
async def summarize_stream_status(data: RequestData):
    user_input = data.content
    def stream():
        try:
            yield "🔍 Reading content on website...\n"
            print(" Received text:", user_input[:200])
            messages = [
            {"role": "system", "content": "You are a summarization assistant. Directly output the cleaned summary of the given text without any reasoning, self-talk, thoughts, or internal planning steps. Do not include phrases like 'I think', 'maybe', 'let's', 'the user wants', or anything not part of the final summary. Your output must look like it was written by an editor, not a model."},
            {"role": "user", "content": "<nothink>\nSummarize the following text clearly and concisely. Do not include any internal thoughts, planning, or reasoning. Just return the final summary:\n\n" + user_input + "\n</nothink>"}
            ]
            yield "🧠 Generating summary...\n"
            result = bot.run(messages)
            result_list = list(result)
            print(" Raw result:", result_list)
            # Extract summary
            last_content = None
            for item in reversed(result_list):
                if isinstance(item, list):
                    for subitem in reversed(item):
                        if isinstance(subitem, dict) and "content" in subitem:
                            last_content = subitem["content"]
                            break
                if last_content:
                    break
            if not last_content:
                yield " No valid summary found.\n"
                return
            summary = re.sub(r"</?think>", "", last_content)
            summary = re.sub(
                r"(?s)^.*?(Summary:|Here's a summary|The key points are|Your tutorial|This tutorial|To summarize|Final summary:)", 
                "", 
                summary, 
                flags=re.IGNORECASE
            )
            summary = re.sub(r"\n{3,}", "\n\n", summary)
            summary = summary.strip()
            yield "\n📄 Summary:\n" + summary + "\n"
        except Exception as e:
            print(" Error:", e)
            yield f"\n Error: {str(e)}\n"
    return StreamingResponse(stream(), media_type="text/plain")

Cách bộ tóm tắt của chúng ta hoạt động:

  • Hàm nhận dữ liệu POST theo schema RequestData, mong đợi trường content chứa văn bản thô của trang.
  • Một hàm sinh stream() lồng nhau được định nghĩa để phát thông điệp dần dần. Điều này cho phép gửi phản hồi theo thời gian thực về frontend trước khi bản tóm tắt hoàn tất.
  • Danh sách thông điệp bao gồm thẻ bao </nothink> trong thông điệp người dùng để chặn lập luận nội bộ, và prompt hệ thống chi tiết củng cố hành vi này.
  • Bot Qwen-Agent được gọi bằng bot.run(messages) với messages là danh sách chứa một thông điệp người dùng.
  • Phản hồi của mô hình được stream và gom vào result_list. Mã sau đó duyệt ngược danh sách để trích chuỗi nội dung mới nhất do LLM trả về.
  • Các đánh dấu lập luận nội bộ của Qwen như <think> và </think> được loại bỏ bằng regex để làm sạch bản tóm tắt cuối.
  • Nếu không tìm thấy nội dung hợp lệ, gửi thông điệp dự phòng. Ngược lại, bản tóm tắt đã làm sạch sẽ được stream ra frontend.

Bước 2: Xây dựng tiện ích Chrome

Phần này hướng dẫn các tệp cần thiết để thiết lập tiện ích, gồm giao diện frontend, logic trích xuất nội dung trang, script liên lạc nền, và siêu dữ liệu cấu hình.

Trước khi xem từng script, đây là mô tả ngắn về vai trò mỗi tệp:

  • manifest.json: Tệp cấu hình định nghĩa siêu dữ liệu, quyền hạn và script của tiện ích.
  • popup.html: Định nghĩa giao diện hiển thị của pop-up tiện ích Chrome với nút bấm và bảng kết quả.
  • popup.js: Xử lý logic frontend, lấy văn bản của thẻ đang hoạt động và stream phản hồi tóm tắt về giao diện.
  • content.js: Trích xuất nội dung trang web hiển thị khi được yêu cầu, đóng vai trò script nội dung.
  • background.js: Điều phối liên lạc với backend và chuyển tiếp bản tóm tắt theo luồng đến pop-up.
  • icon.png: Biểu tượng tiện ích hiển thị trên thanh công cụ và trình quản lý tiện ích của Chrome.

Tổng hợp lại, các tệp này giúp tiện ích tương tác, phản hồi nhanh và có thể kết nối với máy chủ mô hình cục bộ.

Bước 1: Siêu dữ liệu tiện ích

Tệp manifest.json chứa siêu dữ liệu cho Chrome. Nó định nghĩa hành vi tiện ích, quyền hạn, service worker nền, và giao diện pop-up.

{
    "manifest_version": 3,
    "name": "Web Summarizer",
    "version": "1.0",
    "description": "Summarize the content of the current page using a local LLM agent.",
    "permissions": [
      "scripting",
      "activeTab",
      "storage"
    ],
    "host_permissions": [
      "<all_urls>"
    ],
    "action": {
      "default_popup": "popup.html",
      "default_icon": "icon.png"
    },
    "background": {
      "service_worker": "background.js"
    },
    "content_scripts": [
      {
        "matches": ["<all_urls>"],
        "js": ["content.js"],
        "run_at": "document_idle"
      }
    ]
}  

Tệp này định nghĩa cấu hình và khả năng của tiện ích Chrome. Nó cấp các quyền thiết yếu như scripting (chèn JavaScript), activeTab (truy cập thẻ hiện tại), và storage (lưu tùy chọn người dùng).

Trường host_permissions với "<all_urls>" cho phép tiện ích chạy trên mọi trang. Nó cũng thiết lập giao diện qua popup.html và icon.png, và đăng ký hành vi nền bằng service worker (background.js). Cuối cùng, nó định nghĩa script nội dung (content.js) chạy trên mọi trang đã tải, cho phép tương tác với nội dung trang khi cần.

Bước 2: Xây dựng giao diện hiển thị 

popup.html định nghĩa giao diện hiển thị của tiện ích. Nó kết nối đến thẻ đang hoạt động để lấy văn bản hiển thị và gửi đến máy chủ backend của bạn. 

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Web Summarizer Assistant</title>
  <style>
    body {
      width: 500px;
      height: 600px;
      background-color: aliceblue;
      
      
      
    }
    .container {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 15px;
    }
    button {
      border: none;
      border-radius: 5px;
      background-
      color: white;
      
      
      cursor: pointer;
    }
    button:hover {
      background-
    }
    pre {
      background-
      border: 1px solid #ccc;
      border-radius: 5px;
      
      width: 90%;
      height: 350px;
      overflow: auto;
    }
    input[type="text"] {
      
      width: 90%;
      border-radius: 5px;
      border: 1px solid #ccc;
    }
  </style>
</head>
<body>
  <div class="container">
    <h2>Summarize Current Page</h2>
    <button id="summarizeBtn">Summarize</button>
    <pre id="output">Summary will appear here...</pre>
  </div>
  <script src="popup.js"></script>
</body>
</html>

Cùng tìm hiểu từng bước đoạn mã trên:

  1. Đầu tiên, thiết lập cấu trúc HTML cơ bản với thẻ <head> gồm meta charset, cài đặt viewport và thẻ <title>.
  2. Sau đó, trong thẻ <body>, một container chứa toàn bộ thành phần giao diện, gồm:
  • Tiêu đề <h2> nhắc người dùng tóm tắt trang hiện tại.
  • Nút Summarize (“#summarizeBtn”) để người dùng nhấp kích hoạt trích xuất nội dung và tóm tắt.
  • Phần tử <pre> (“#output”) làm bảng cuộn để hiển thị bản tóm tắt khi stream về.
  1. Phần style được định nghĩa bằng CSS nhúng để pop-up gọn gàng, dễ đọc. Khối pre giúp đầu ra có thể cuộn và nổi bật.
  2. Script popup.js lắng nghe sự kiện nhấp nút, trích xuất nội dung trang, gửi đến backend FastAPI, và cập nhật bảng hiển thị bằng văn bản tóm tắt theo luồng.

Bước 3: Xây dựng giao diện frontend 

popup.js đóng vai trò bộ điều khiển logic frontend: phản hồi nhấp nút, trích văn bản từ thẻ hiện tại, gửi đến backend, và stream bản tóm tắt theo thời gian thực vào vùng hiển thị.

document.addEventListener('DOMContentLoaded', function () {
    let serverAddress = '127.0.0.1'; 
    document.getElementById('summarizeBtn').addEventListener('click', async () => {
      const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
      chrome.scripting.executeScript(
        {
          target: { tabId: tab.id },
          func: () => {
            try {
              return document.body?.innerText || 'EMPTY';
            } catch (e) {
              return 'SCRIPT_ERROR';
            }
          }
        },
        async (results) => {
          const pageText = results?.[0]?.result || '';
          console.log(' Extracted text:', pageText.slice(0, 500));
          if (pageText === 'SCRIPT_ERROR') {
            document.getElementById('output').innerText = 'Could not access page content (script error).';
            return;
          }
          if (!pageText || pageText.trim() === 'EMPTY') {
            document.getElementById('output').innerText = ' No page text found.';
            return;
          }
          try {
            console.log( Sending streaming POST to http://${serverAddress}:7864/summarize_stream_status);
            const res = await fetch(http://${serverAddress}:7864/summarize_stream_status, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ content: pageText }),
            });
            const reader = res.body.getReader();
            const decoder = new TextDecoder();
            let resultText = '';
            while (true) {
            const { done, value } = await reader.read();
            if (done) break;
            const chunk = decoder.decode(value, { stream: true });
            resultText += chunk;
            document.getElementById('output').innerText = resultText;
            }
          } catch (err) {
            console.error(' Fetch error:', err);
            document.getElementById('output').innerText = ' Failed to get summary.\n' + err.message;
          }
        }
      );
    });
  });

Tệp JavaScript này cung cấp logic giao diện frontend cho tiện ích Chrome, giúp người dùng trích và tóm tắt nội dung trang web chỉ với một cú nhấp.

Cách hoạt động:

  • Khi pop-up tải xong (DOMContentLoaded), một trình lắng nghe sự kiện được gắn vào nút "Summarize".
  • Khi nhấp nút, tiện ích truy vấn thẻ đang hoạt động bằng chrome.tabs.query.
  • Sau đó chạy một script nội dung trong thẻ đó bằng chrome.scripting.executeScript, cố gắng trích innerText của phần thân trang.
  • Nếu script lỗi hoặc trả về rỗng, giao diện sẽ hiển thị thông điệp dự phòng phù hợp.
  • Nếu trích xuất thành công, văn bản được gửi bằng yêu cầu POST đến backend FastAPI tại http://127.0.0.1:7864/summarize_stream_status.
  • Phản hồi được đọc theo luồng bằng res.body.getReader(), cho phép các phần của bản tóm tắt xuất hiện theo thời gian thực trong bảng kết quả.
  • Một TextDecoder giải mã từng mảnh văn bản stream, nối trực tiếp vào phần hiển thị.
  • Bất kỳ lỗi mạng hay backend nào đều được bắt và hiển thị trong pop-up để gỡ lỗi hoặc thông báo người dùng.

Bước 4: Trích xuất nội dung trang web

Trước khi gửi nội dung trang web đến backend, ta cần cách trích xuất từ thẻ hiện tại. Script content.js lắng nghe thông điệp từ script nền hoặc pop-up và trả về văn bản hiển thị từ trang web. 

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    if (request.type === "GET_PAGE_TEXT") {
      const bodyText = document.body.innerText.trim();
      sendResponse({ text: bodyText || null });
    }
});

Script này lắng nghe thông điệp loại "GET_PAGE_TEXT" và phản hồi bằng cách trích và trả về văn bản phần thân hiển thị (document.body.innerText). Điều này cho phép worker nền dễ dàng yêu cầu nội dung trang mà không phải chèn mã mỗi lần, giữ cho liên lạc sạch và bất đồng bộ.

Bước 5: Điều phối backend

Script nền (background.js) làm cầu nối giữa giao diện pop-up và script nội dung. Nó đảm bảo việc truyền thông điệp và điều phối tóm tắt diễn ra đúng đắn ở hậu trường.

chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
    if (request.type === "SUMMARIZE_PAGE") {
      const tabId = sender.tab.id;
        chrome.scripting.executeScript(
        {
          target: { tabId },
          func: () => {
            try {
              return document.body?.innerText || 'EMPTY';
            } catch (e) {
              return 'SCRIPT_ERROR';
            }
          }
        },
        async (results) => {
          const pageText = results?.[0]?.result || '';
          if (!pageText || pageText === 'SCRIPT_ERROR') {
            chrome.runtime.sendMessage({
              type: 'SUMMARY_RESULT',
              summary: ' Failed to read page text.',
            });
            return;
          }
          chrome.storage.local.get(['database_host'], async function (result) {
            const host = result.database_host || '127.0.0.1';
            try {
              const response = await fetch(http://${host}:7864/summarize_stream_status, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ content: pageText }),
              });
              const reader = response.body.getReader();
              const decoder = new TextDecoder();
              let fullSummary = '';
              while (true) {
                const { done, value } = await reader.read();
                if (done) break;
                const chunk = decoder.decode(value, { stream: true });
                fullSummary += chunk;
                chrome.runtime.sendMessage({
                  type: 'SUMMARY_PROGRESS',
                  chunk
                });
              }
              chrome.runtime.sendMessage({
                type: 'SUMMARY_DONE',
                summary: fullSummary
              });
            } catch (err) {
              chrome.runtime.sendMessage({
                type: 'SUMMARY_RESULT',
                summary: ' Error during summarization: ' + err.message
              });
            }
          });
        }
      );
      return true; 
    }
  });
  

Đoạn mã trên đảm bảo luồng trích xuất nội dung, tóm tắt và cập nhật thời gian thực diễn ra trơn tru. Trình tự hoạt động:

  • Lắng nghe thông điệp loại "SUMMARIZE_PAGE" được kích hoạt từ nút trong pop-up.
  • Khi kích hoạt, xác định thẻ đang hoạt động bằng sender.tab.id và chạy script chèn qua chrome.scripting.executeScript để trích văn bản hiển thị từ trang.
  • Nếu không thể truy cập hoặc nội dung rỗng, gửi lại thông điệp dự phòng.
  • Nếu ổn, lấy database_host (thường là 127.0.0.1) từ bộ nhớ cục bộ của Chrome và dùng nó để gửi yêu cầu POST đến backend FastAPI với nội dung đã trích.
  • Tiếp đó mở kết nối streaming và đọc phản hồi từng mảnh bằng ReadableStreamDefaultReader.
  • Mỗi mảnh được giải mã sẽ được gửi cập nhật tạm thời đến pop-up bằng chrome.runtime.sendMessage với loại 'SUMMARY_PROGRESS'.
  • Khi luồng kết thúc, gửi thông điệp cuối với toàn bộ bản tóm tắt. Nếu có lỗi, gửi thông điệp dự phòng.

Script nền này là chìa khóa để bật tóm tắt theo luồng, thời gian thực trong tiện ích Chrome mà không chặn giao diện hay tải lại trang.

Bước 6: Thêm biểu tượng tiện ích

Chọn hoặc vẽ ảnh biểu tượng cho tiện ích và lưu là icon.png trong thư mục tiện ích. Đây là biểu tượng chúng tôi dùng:

Extension Icon

Ảnh được tạo bằng FireFly

Cấu trúc thư mục tổng thể của bạn sẽ như sau:

QWEN-WEB-SUMMARIZER/
├── backend/
│   ├── app.py
│   ├── Dockerfile
│   └── requirements.txt
├── extension/
│   ├── background.js
│   ├── content.js
│   ├── icon.png
│   ├── manifest.json
│   ├── popup.html
│   └── popup.js

Bước 3: Chạy ứng dụng

Để chạy mọi thứ cục bộ, hãy chạy lệnh sau trong terminal:

uvicorn backend.app:app --host 0.0.0.0 --port 7864

Cách này lý tưởng cho phát triển hoặc gỡ lỗi cục bộ mà không dùng Docker. Để chạy bằng Docker, lần lượt chạy các lệnh sau trong terminal:

docker build -t qwen-agent-backend .
docker run -p 7864:7864 qwen-agent-backend

Tiện ích Chrome giao tiếp qua cổng 7864.  Giờ hãy làm theo các bước sau để kích hoạt tiện ích trên Chrome:

  • Mở Chrome và nhấp vào “Extensions” (bên phải thanh tìm kiếm).
  • Bật “Developer mode” và nhấp “Load unpacked” (góc trên bên trái). 

Chrome Extension tab for activating an extension powered by Qwen-Agent

  • Tiếp theo, tải thư mục tiện ích của chúng ta chứa toàn bộ tệp và chờ xác nhận.
  • Khi pop-up xác nhận thiết lập xong, hãy nhấp biểu tượng tiện ích trên bất kỳ trang nào để nhận bản tóm tắt theo luồng từ mô hình Qwen3 cục bộ.

Cùng xem kết quả:

Qwen-Agent Extension example

Kết luận

Trong dự án này, chúng ta đã xây dựng một trợ lý tóm tắt trang web theo thời gian thực sử dụng framework Qwen-Agent và mô hình Qwen3:1.7B chạy cục bộ qua Ollama. Chúng ta phát triển backend FastAPI để xử lý suy luận LLM và tích hợp với tiện ích Chrome để lấy nội dung trang hiển thị và trình bày bản tóm tắt stream trực tiếp.

Bản demo này cho thấy Qwen-Agent có thể kích hoạt các quy trình lập luận tăng cường công cụ hoàn toàn ngoại tuyến ngay trong trình duyệt. Nó đặt nền tảng để xây dựng các tác nhân cục bộ nâng cao hơn như công cụ tự động hóa trình duyệt, cộng sự nghiên cứu, hoặc chatbot dựa trên tài liệu.

Để tìm hiểu thêm về AI agent, xem các blog sau:


Aashi Dutt's photo
Author
Aashi Dutt
LinkedIn
Twitter

Tôi là Chuyên gia Google Developers trong lĩnh vực ML (Gen AI), Chuyên gia Kaggle 3x và Đại sứ Women Techmakers với hơn 3 năm kinh nghiệm trong ngành công nghệ. Tôi đồng sáng lập một startup công nghệ y tế vào năm 2020 và hiện đang theo học thạc sĩ khoa học máy tính tại Georgia Tech, chuyên sâu về học máy.

Chủ đề
AI Agents
Trí tuệ Nhân tạo

Học AI với những khóa này!

Khóa học

Giới thiệu về AI Agents

1 giờ 30 phút
147.4K
Tìm hiểu các kiến thức cơ bản về AI agent, các thành phần của chúng và ứng dụng thực tế—không cần lập trình.
Xem chi tiếtRight Arrow
Bắt Đầu Khóa Học
Xem thêmRight Arrow
Liên quan

blog

Claude Opus 4.6: Tính năng, Điểm chuẩn, Bài kiểm tra thực hành và hơn thế nữa

Mô hình mới nhất của Anthropic dẫn đầu ở mã hóa tác tử và lập luận phức tạp. Thêm vào đó, nó có cửa sổ ngữ cảnh 1M.
Matt Crabtree's photo

Matt Crabtree

10 phút

Xem ThêmXem Thêm