Lewati ke konten utama

Qwen-Agent: Panduan dengan Proyek Demo

Pelajari cara menggunakan Qwen-Agent dan Qwen3 untuk membangun ekstensi peringkas halaman web waktu nyata.
Diperbarui 28 Sep 2026  · 12 mnt Baca

Jelajahi bersama AI

ChatGPTClaudePerplexity

Dalam tulisan blog ini, saya akan memandu Anda membangun ekstensi peramban bertenaga Qwen-Agent yang meringkas konten halaman web apa pun secara waktu nyata. Kita akan membahas cara:

  • Menggunakan model Qwen3 dari Alibaba secara lokal melalui Ollama
  • Menggunakan Qwen-Agent untuk pemicu terstruktur dan penggunaan alat
  • Membangun ekstensi Chrome dengan pembaruan UI streaming
  • Menambahkan backend FastAPI untuk mendukung peringkasan waktu nyata

Pada akhirnya, Anda akan memiliki agen peringkas yang bisa offline, didukung oleh Qwen3, yang membaca dan meringkas halaman web di peramban Anda hanya dengan satu klik.

Kami menjaga pembaca tetap terbarui tentang hal terbaru di AI melalui The Median, buletin gratis setiap Jumat yang merangkum kisah-kisah kunci pekan ini. Berlangganan dan tetap tajam hanya dalam beberapa menit setiap minggu:

Apa itu Qwen-Agent?

Qwen-Agent adalah kerangka kerja Python ringan yang dibuat oleh Alibaba untuk mengembangkan aplikasi LLM yang andal menggunakan keluarga model Qwen3. Fokusnya adalah mendukung:

  • Agen yang mengikuti instruksi
  • Penggunaan alat dan pemanggilan fungsi
  • Memori dan perencanaan multi-putaran
  • Pemicu fleksibel melalui pesan terstruktur

Pada intinya, Qwen-Agent menyederhanakan pengembangan agen AI modular dengan kemampuan penalaran dan eksekusi kode yang kuat. Ini mencakup komponen atomik seperti pembungkus LLM dan alat, serta kelas tingkat tinggi Agent untuk mengorkestrasi alur kerja.

Qwen-Agent bekerja dengan API berbasis cloud (seperti Alibaba DashScope) dan runtime lokal yang kompatibel dengan OpenAI seperti vLLM dan Ollama. Ini memudahkan pembangunan aplikasi LLM yang andal dengan:

  • Integrasi cepat melalui FastAPI
  • Streaming bawaan untuk UI frontend
  • Rantai alat fungsi yang dapat disesuaikan
  • Privasi dan performa sepenuhnya offline

Gambaran Proyek: Ekstensi Peringkas Web Waktu Nyata

Di bagian ini, kita akan membangun ekstensi peringkas waktu nyata yang didukung oleh Qwen-Agent. Ini mencakup:

  • Backend FastAPI yang menerima teks halaman web dan mengembalikan ringkasan
  • Pop-up ekstensi Chrome untuk menangkap konten halaman yang terlihat
  • UI streaming saat ringkasan dihasilkan
  • Backend didukung oleh Qwen3:1.7B yang berjalan secara lokal melalui Ollama

Mari kita telusuri setiap bagian proyek ini.

Langkah 1: Menyiapkan Backend Qwen3

Pada langkah ini, kita akan membahas semua berkas kode yang perlu kita siapkan agar backend dapat bekerja sinkron dengan ekstensi kita.

Langkah 1.1: Dependensi dan pustaka 

Mulailah dengan memasang ollama di sistem Anda. Selanjutnya, daftar semua dependensi Python yang diperlukan untuk backend dalam requirements.txt. Ini membantu memastikan penyiapan lingkungan yang konsisten di berbagai mesin dan kontainer.

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

Berikut penjelasan singkat penggunaan masing-masing pustaka:

  • qwen-agent[code_interpreter]: Kerangka kerja agen inti dengan dukungan penggunaan alat, memungkinkan eksekusi kode dan penalaran terstruktur.
  • fastapi dan uvicorn: Keduanya menggerakkan backend API asinkron dan menyajikan logika peringkas Anda.
  • python-dotenv dan python-dateutil: Pustaka utilitas untuk menangani variabel lingkungan dan pemrosesan tanggal/waktu (berguna untuk skala di masa mendatang).
  • matplotlib: Digunakan untuk membuat plot atau menampilkan keluaran visual (opsional) 

Jika Anda ingin menjalankan proyek ini secara lokal, jalankan perintah berikut untuk memasang semua dependensi:

pip install -r requirements.txt

Langkah 1.2: Penyiapan DockerFile (opsional)

Sekarang, mari siapkan Dockerfile yang membuat lingkungan Python minimal dengan aplikasi kita dan membuka port 7864, sehingga ekstensi Chrome dapat mengirim permintaan ke 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"]

Penyiapan ini bersifat opsional jika Anda memilih menjalankan proyek secara lokal menggunakan Uvicorn alih-alih Docker.

Langkah 1.3: Menyajikan Qwen dengan Ollama

Selanjutnya, Anda perlu menarik dan menyajikan model Qwen3 secara lokal menggunakan Ollama. Langkah ini memungkinkan inferensi offline dengan menjadi host layanan LLM di mesin Anda.

ollama pull qwen3:1.7b
ollama serve 

Langkah 1.4: Membangun server peringkasan FastAPI

Berkas app.py mendefinisikan server FastAPI yang melakukan streaming ringkasan konten halaman web secara waktu nyata menggunakan model Qwen3:1.7B yang berjalan lokal melalui Qwen-Agent.

Langkah 1.4.1: Impor

Mulailah dengan mengimpor FastAPI, utilitas streaming, dan komponen Qwen-Agent seperti Assistant, yang membungkus model dan kemampuan alatnya.

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

Langkah 1.4.2: Inisialisasi Aplikasi FastAPI

Selanjutnya, kita mendefinisikan skema RequestData sederhana untuk menerima konten, dan membuat instance bot dari 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."
)

Pada kode di atas, bot adalah instance kelas Assistant dari Qwen-Agent, dikonfigurasi untuk berinteraksi dengan model Qwen3:1.7B yang dilayani secara lokal melalui Ollama. Bot menggunakan alat bawaan code_interpreter untuk menalar konten dan mengeksekusi kode Python bila diperlukan. Sebuah system_message kustom membimbing perilakunya untuk menghasilkan ringkasan halaman web yang ringkas.

Catatan: Anda dapat menggunakan model yang lebih kecil seperti qwen3:0.6b atau qwen3:1.7b untuk secara signifikan mengurangi waktu respons dan penggunaan memori. Ini sangat berguna untuk tugas peringkasan yang lebih cepat tanpa banyak beban penalaran.

Langkah 1.4.3: Rute peringkas

Terakhir, sebuah endpoint membaca konten yang masuk dan mengirimkan teks ringkasan secara langsung saat dihasilkan oleh model. Ini menggunakan keluaran streaming sehingga pengguna tidak perlu menunggu hingga seluruh respons selesai dibuat.

@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")

Begini cara kerja peringkas kita:

  • Fungsi menerima instruksi data POST menggunakan skema RequestData, yang mengharapkan field bernama content yang menampung teks mentah halaman web.
  • Sebuah fungsi generator bersarang stream() didefinisikan untuk mengirim pesan secara progresif. Ini memungkinkan umpan balik waktu nyata dikirim kembali ke frontend sebelum ringkasan akhir selesai.
  • Daftar pesan secara eksplisit menyertakan pembungkus tag </nothink> dalam pesan pengguna untuk menekan penalaran internal, dan prompt sistem terperinci memperkuat perilaku ini.
  • Bot Qwen-Agent dipanggil menggunakan bot.run(messages) di mana messages adalah daftar yang berisi satu pesan masukan pengguna. 
  • Respons model di-stream dan dikumpulkan ke dalam result_list. Kode kemudian melakukan loop melalui daftar secara terbalik untuk mengekstrak string konten terbaru yang dikembalikan oleh LLM.
  • Penanda penalaran internal Qwen seperti <think> dan </think> dihapus dari output menggunakan regex untuk membersihkan ringkasan akhir.
  • Jika tidak ada konten yang valid ditemukan, pesan fallback dikirim. Jika ada, ringkasan yang telah dibersihkan di-stream ke frontend.

Langkah 2: Membangun Ekstensi Chrome

Bagian ini menjabarkan semua berkas yang diperlukan untuk menyiapkan ekstensi, termasuk UI frontend, logika untuk mengekstrak konten halaman, skrip komunikasi latar belakang, dan metadata konfigurasi.

Sebelum melihat skrip-skripnya satu per satu, berikut ringkasan sederhana fungsi tiap berkas:

  • manifest.json: Berkas konfigurasi yang mendefinisikan metadata, izin, dan skrip ekstensi.
  • popup.html: Skrip yang mendefinisikan UI yang terlihat untuk pop-up ekstensi Chrome dengan tombol dan panel keluaran.
  • popup.js: Menangani logika frontend dan menangkap teks tab saat ini serta men-stream respons ringkasan ke UI.
  • content.js: Menarik konten halaman web yang terlihat saat diminta, bertindak sebagai skrip konten.
  • background.js: Mengoordinasikan komunikasi backend dan meneruskan ringkasan yang di-stream ke pop-up.
  • icon.png: Ikon ekstensi yang ditampilkan di bilah alat Chrome dan pengelola ekstensi.

Bersama-sama, berkas-berkas ini membuat ekstensi menjadi interaktif, reaktif, dan mampu berkomunikasi dengan server model lokal.

Langkah 1: Metadata ekstensi

Skrip manifest.json berisi metadata untuk Chrome. Ini mendefinisikan perilaku ekstensi, izin, service worker latar belakang, dan UI 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"
      }
    ]
}  

Berkas ini mendefinisikan konfigurasi dan kapabilitas ekstensi Chrome Anda. Ini memberikan izin penting seperti scripting (untuk menyuntikkan JavaScript), activeTab (untuk mengakses tab saat ini), dan storage (untuk menyimpan preferensi pengguna).

Field host_permissions dengan "<all_urls>" memungkinkan ekstensi berjalan di halaman web mana pun. Ini juga menyiapkan UI ekstensi melalui popup.html dan icon.png, serta mendaftarkan perilaku latar belakang menggunakan service worker (background.js). Terakhir, ini mendefinisikan skrip konten (content.js) untuk dijalankan pada semua halaman yang dimuat, memungkinkan interaksi dengan konten halaman web saat diperlukan.

Langkah 2: Membangun antarmuka yang terlihat 

Berkas popup.html mendefinisikan antarmuka yang terlihat dari ekstensi. Ini terhubung ke tab aktif yang menangkap teks yang terlihat dan mengirimkannya ke server backend Anda. 

<!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>

Mari pahami kode di atas selangkah demi selangkah:

  1. Pertama, kita menyiapkan struktur HTML dasar dengan tag <head> yang mencakup meta tag untuk pengodean karakter, pengaturan viewport, dan tag <title>.
  2. Lalu, di dalam tag <body>, sebuah container menampung semua elemen UI, termasuk:
  • Heading <h2> yang meminta pengguna untuk meringkas halaman saat ini.
  • Tombol Summarize (“#summarizeBtn”) yang diklik pengguna untuk memicu ekstraksi konten dan peringkasan.
  • Elemen <pre> (“#output”) yang berfungsi sebagai panel gulir untuk menampilkan ringkasan saat di-stream.
  1. Gaya ditentukan menggunakan CSS tersemat untuk membuat pop-up bersih dan mudah dibaca. Blok pre digunakan agar keluaran dapat digulir dan tampak jelas.
  2. Skrip popup.js mendengarkan klik tombol, mengekstrak konten halaman, mengirimkannya ke backend FastAPI, dan memperbarui panel output dengan teks ringkasan yang di-stream.

Langkah 3: Membangun UI frontend 

Berkas popup.js bertindak sebagai pengendali logika frontend yang merespons klik tombol, mengekstrak teks dari tab saat ini, mengirimkannya ke backend, dan men-stream ringkasan kembali ke area output secara waktu nyata.

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;
          }
        }
      );
    });
  });

Berkas JavaScript ini menggerakkan logika UI frontend dari ekstensi Chrome, memungkinkan pengguna mengekstrak dan meringkas konten halaman web dengan sekali klik.

Begini cara kerjanya:

  • Saat pop-up dimuat (DOMContentLoaded), pendengar peristiwa dipasang pada tombol "Summarize".
  • Saat tombol diklik, ekstensi menanyakan tab yang saat ini aktif menggunakan chrome.tabs.query.
  • Kemudian menjalankan skrip konten di dalam tab tersebut menggunakan chrome.scripting.executeScript, yang mencoba mengekstrak innerText dari body halaman.
  • Jika skrip gagal atau mengembalikan konten kosong, pesan fallback yang sesuai ditampilkan di UI.
  • Jika teks berhasil diekstrak, teks tersebut dikirim sebagai permintaan POST ke backend FastAPI lokal di http://127.0.0.1:7864/summarize_stream_status.
  • Respons di-stream menggunakan res.body.getReader(), yang memungkinkan potongan ringkasan muncul secara waktu nyata di panel output.
  • Sebuah TextDecoder mendekode setiap potongan teks yang di-stream, menambahkannya secara langsung ke tampilan.
  • Kesalahan jaringan atau backend akan ditangkap dan ditampilkan di antarmuka pop-up untuk debugging atau umpan balik pengguna.

Langkah 4: Mengekstrak konten halaman web

Sebelum kita dapat mengirim konten halaman web ke backend, kita memerlukan cara untuk mengekstraknya dari tab saat ini. Skrip content.js mendengarkan pesan dari skrip latar belakang atau pop-up dan mengembalikan teks konten yang terlihat dari halaman web. 

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

Skrip ini mendengarkan pesan bertipe "GET_PAGE_TEXT" dan merespons dengan mengekstrak serta mengembalikan teks body yang terlihat (document.body.innerText). Ini memungkinkan worker latar belakang dengan mudah meminta konten halaman web tanpa menyuntikkan kode setiap kali, menjaga komunikasi tetap bersih dan asinkron.

Langkah 5: Koordinasi backend

Skrip latar belakang (background.js) menjembatani UI pop-up dan skrip konten. Ini memastikan pengiriman pesan dan koordinasi peringkasan berlangsung dengan benar di belakang layar.

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; 
    }
  });
  

Kode di atas memastikan alur ekstraksi konten, peringkasan, dan pembaruan waktu nyata berjalan mulus. Berikut penjelasan langkah demi langkah cara kerjanya:

  • Mendengarkan pesan bertipe "SUMMARIZE_PAGE" yang dipicu oleh klik tombol di pop-up.
  • Setelah dipicu, ini mengidentifikasi tab aktif menggunakan sender.tab.id dan menjalankan skrip yang disuntikkan melalui chrome.scripting.executeScript untuk mengekstrak teks yang terlihat dari halaman web.
  • Jika konten tidak dapat diakses atau kosong, pesan fallback dikirim kembali.
  • Jika tidak, ia mengambil database_host (biasanya 127.0.0.1) dari penyimpanan lokal Chrome dan menggunakannya untuk mengirim permintaan POST ke backend FastAPI dengan konten yang diekstrak.
  • Lalu, membuka koneksi streaming dan membaca respons sedikit demi sedikit menggunakan ReadableStreamDefaultReader.
  • Saat setiap potongan didekode, ia mengirim pembaruan sementara ke pop-up menggunakan chrome.runtime.sendMessage dengan tipe 'SUMMARY_PROGRESS'.
  • Setelah stream berakhir, ia mengirim pesan akhir dengan ringkasan lengkap. Jika terjadi kesalahan selama proses, pesan fallback dikirim sebagai gantinya.

Skrip latar belakang ini penting untuk memungkinkan ringkasan streaming secara waktu nyata di ekstensi Chrome tanpa menghambat UI atau memuat ulang halaman.

Langkah 6: Menambahkan ikon ekstensi

Pilih atau gambar ikon untuk ekstensi dan simpan sebagai icon.png di dalam folder ekstensi. Ini yang akan kita gunakan:

Ikon Ekstensi

Gambar dibuat dengan FireFly

Struktur folder keseluruhan Anda seharusnya terlihat seperti ini:

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

Langkah 3: Menjalankan Aplikasi

Untuk menjalankan semuanya secara lokal, jalankan perintah berikut di terminal:

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

Ini ideal untuk pengembangan atau debugging lokal tanpa Docker. Untuk menjalankan di Docker, jalankan perintah berikut satu per satu di terminal Anda:

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

Ekstensi Chrome berkomunikasi melalui port 7864.  Sekarang, ikuti langkah-langkah berikut untuk menjalankan ekstensi Anda di Chrome:

  • Buka Chrome dan klik “Extensions” (di sisi kanan bilah pencarian).
  • Aktifkan “Developer mode” dan klik “Load unpacked” (pojok kiri atas). 

Tab Ekstensi Chrome untuk mengaktifkan ekstensi bertenaga Qwen-Agent

  • Selanjutnya, muat folder ekstensi kita yang berisi semua berkas dan tunggu konfirmasi.
  • Setelah pop-up mengonfirmasi penyiapan ekstensi, klik ikon ekstensi di halaman web mana pun dan dapatkan ringkasan streaming menggunakan model Qwen3 lokal Anda.

Mari kita lihat hasilnya:

Contoh Ekstensi Qwen-Agent

Kesimpulan

Dalam proyek ini, kita membangun asisten peringkas halaman web waktu nyata menggunakan kerangka kerja Qwen-Agent dan model Qwen3:1.7B yang berjalan secara lokal melalui Ollama. Kita mengembangkan backend FastAPI untuk menangani inferensi LLM dan mengintegrasikannya dengan ekstensi Chrome yang menangkap konten halaman yang terlihat dan menampilkan ringkasan yang di-stream langsung.

Demo ini menunjukkan bagaimana Qwen-Agent dapat memungkinkan alur kerja penalaran yang ditambah alat sepenuhnya offline di peramban. Ini menjadi landasan untuk membangun agen lokal yang lebih canggih seperti alat otomatisasi peramban, copilot riset, atau chatbot berbasis dokumen.

Untuk mempelajari lebih lanjut tentang agen AI, lihat blog berikut:


Aashi Dutt's photo
Author
Aashi Dutt
LinkedIn
Twitter

Saya adalah Google Developers Expert di ML (Gen AI), Kaggle 3x Expert, dan Women Techmakers Ambassador dengan pengalaman lebih dari 3 tahun di bidang teknologi. Saya ikut mendirikan startup health-tech pada 2020 dan sedang menempuh studi magister ilmu komputer di Georgia Tech dengan spesialisasi machine learning.

Topik
Agen AI
Kecerdasan Buatan

Belajar AI lewat kursus-kursus ini!

Kursus

Pengantar Agen Kecerdasan Buatan

1 jam 30 menit
143.4K
Pelajari dasar-dasar agen AI, komponennya, serta penerapannya di dunia nyata — tanpa perlu coding.
Lihat DetailRight Arrow
Mulai Kursus
Lihat SelengkapnyaRight Arrow
Terkait

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026

Kuasai pertanyaan wawancara basis data, dari konsep SQL dasar hingga skenario desain sistem tingkat lanjut. Panduan mendalam ini mencakup semua yang Anda perlukan untuk sukses di wawancara DBMS dan meraih peran berikutnya.
Dario Radečić's photo

Dario Radečić

15 mnt

blogs

12 Alternatif ChatGPT Terbaik yang Bisa Anda Coba pada 2026

Artikel ini menyajikan daftar alternatif ChatGPT yang akan meningkatkan produktivitas Anda.
Javier Canales Luna's photo

Javier Canales Luna

14 mnt

blogs

Spaghetti Plot dan Jalur Badai

Temukan alasan mengapa Anda sebaiknya (tidak) menggunakan spaghetti plot untuk menyampaikan ketidakpastian jalur prediksi badai serta dampaknya terhadap interpretasi.
Hugo Bowne-Anderson's photo

Hugo Bowne-Anderson

13 mnt

blogs

Tutorial Korelasi di R

Dapatkan pengenalan dasar-dasar korelasi di R: pelajari lebih lanjut tentang koefisien korelasi, matriks korelasi, plotting korelasi, dan sebagainya.
David Woods's photo

David Woods

13 mnt

Lihat SelengkapnyaLihat Selengkapnya