两种新的AI交互方式
- [🎯 优化后的提示词](#🎯 优化后的提示词)
- [📖 技术博客:浏览器 AI Agent 两种交互方式的深度解析](#📖 技术博客:浏览器 AI Agent 两种交互方式的深度解析)
-
- [📋 目录](#📋 目录)
- [1. 背景与需求分析](#1. 背景与需求分析)
-
- [1.1 业务场景](#1.1 业务场景)
- [1.2 解决方案](#1.2 解决方案)
- [2. 两种交互方式概览](#2. 两种交互方式概览)
-
- [2.1 交互流程对比图](#2.1 交互流程对比图)
- [2.2 技术特性对比](#2.2 技术特性对比)
- [3. 核心原理深度解析](#3. 核心原理深度解析)
-
- [3.1 浏览器插件架构原理](#3.1 浏览器插件架构原理)
- [3.2 Content Script 注入机制](#3.2 Content Script 注入机制)
- [3.3 Shadow DOM 样式隔离原理](#3.3 Shadow DOM 样式隔离原理)
- [4. 技术架构设计](#4. 技术架构设计)
-
- [4.1 整体系统架构图](#4.1 整体系统架构图)
- [4.2 消息通信流程图](#4.2 消息通信流程图)
- [4.3 生命周期管理状态图](#4.3 生命周期管理状态图)
- [5. 关键代码实现](#5. 关键代码实现)
-
- [5.1 Manifest V3 配置文件](#5.1 Manifest V3 配置文件)
- [5.2 Bookmarklet 注入代码](#5.2 Bookmarklet 注入代码)
- [5.3 Content Script 上下文提取](#5.3 Content Script 上下文提取)
- [5.4 Shadow DOM UI 组件](#5.4 Shadow DOM UI 组件)
- [5.5 API 调用与流式响应](#5.5 API 调用与流式响应)
- [6. 技术难点与解决方案](#6. 技术难点与解决方案)
-
- [6.1 难点一:CSP (Content Security Policy) 限制](#6.1 难点一:CSP (Content Security Policy) 限制)
- [6.2 难点二:样式冲突与污染](#6.2 难点二:样式冲突与污染)
- [6.3 难点三:跨域通信安全](#6.3 难点三:跨域通信安全)
- [7. 面试介绍话术](#7. 面试介绍话术)
-
- [7.1 30 秒电梯演讲](#7.1 30 秒电梯演讲)
- [7.2 技术亮点阐述](#7.2 技术亮点阐述)
- [7.3 常见问题应答](#7.3 常见问题应答)
- [8. 总结与展望](#8. 总结与展望)
-
- [8.1 技术总结](#8.1 技术总结)
- [8.2 未来优化方向](#8.2 未来优化方向)
- [8.3 核心收获](#8.3 核心收获)
- [📎 附录:项目资源](#📎 附录:项目资源)
🎯 优化后的提示词
markdown
# 角色设定
你是一位资深前端架构师,擅长浏览器扩展开发和 AI 应用集成。
# 任务目标
撰写一篇面向前端面试官的技术博客,深入解析两种 AI Agent 交互方式的实现原理:
1. 物料拖拽到浏览器标签页的交互方式
2. 封装成浏览器插件,点击进行 AI 对话
# 内容要求
1. **技术深度**:解析 Content Script 注入、Shadow DOM 隔离、Message Passing 通信等核心原理
2. **架构设计**:提供完整的系统架构图和流程图(Mermaid 格式)
3. **代码示例**:给出关键代码片段,体现工程化思维
4. **面试价值**:突出技术难点、解决方案和个人贡献
5. **图文并茂**:至少包含 5 个 Mermaid 图表
# 输出格式
- 技术博客格式,结构清晰
- 使用 Markdown + Mermaid
- 适合中级以上前端开发者阅读
- 字数 3000+,包含实战代码
📖 技术博客:浏览器 AI Agent 两种交互方式的深度解析
作者 :前端架构师
阅读时间 :15 分钟
技术栈:Chrome Extension MV3、Shadow DOM、Message Passing、Bookmarklet
📋 目录
1. 背景与需求分析
1.1 业务场景
在现代 Web 应用中,用户经常需要在浏览网页时与 AI 进行交互,例如:
- 📄 总结当前页面内容
- 💬 基于选中文字提问
- 🔍 获取页面相关信息的扩展解答
传统的做法是:复制 → 切换标签 → 粘贴到 AI 聊天窗口,效率低下且打断用户心流。
1.2 解决方案
我们设计了两种无侵入式的交互方案:
| 方案 | 触发方式 | 适用场景 |
|---|---|---|
| 拖拽式书签 | 拖拽物料到书签栏,点击触发 | 快速体验、无需安装、临时使用 |
| 浏览器插件 | 安装扩展,点击图标触发 | 长期使用、功能完整、权限丰富 |
2. 两种交互方式概览
2.1 交互流程对比图
渲染错误: Mermaid 渲染失败: Lexical error on line 2. Unrecognized text. ... TB subgraph 方案一:拖拽式书签 A1[用户 ----------------------^
2.2 技术特性对比
完整 Web 应用 纯前端页面 浏览器插件 拖拽式书签 开发成本低 开发成本高 功能简单 功能强大 "两种方案的技术特性对比"
3. 核心原理深度解析
3.1 浏览器插件架构原理
Chrome Extension Manifest V3 的核心组件关系:
外部服务
页面进程
扩展进程
chrome.runtime.sendMessage
chrome.tabs.sendMessage
DOM 操作
读取上下文
HTTPS 请求
HTTPS 请求
Popup 页面
独立进程
Background Service Worker
后台进程
Content Script
注入到网页
目标网页 DOM
LLM API 服务
3.2 Content Script 注入机制
目标页面 Content Script manifest.json 浏览器 用户 目标页面 Content Script manifest.json 浏览器 用户 document_start document_end document_idle 访问目标网站 检查 matches 规则 匹配成功 根据 run_at 注入脚本 访问 DOM 树 读取/修改内容 显示交互界面
3.3 Shadow DOM 样式隔离原理
Shadow DOM
无法穿透
隔离
只影响
外部 CSS
Shadow Root
内部 CSS
Shadow 内组件
普通 DOM
会污染
会影响
外部 CSS
普通组件
4. 技术架构设计
4.1 整体系统架构图
服务层
核心层
注入层
用户层
拖拽书签触发
插件图标点击
Bookmarklet 注入器
Extension Content Script
UI 组件库
React/Vue
通信模块
Message Passing
上下文提取器
DOM Parser
API 客户端
LLM 调用
代理服务器
API Key 管理
LLM 服务
OpenAI/Claude
存储服务
历史记录
4.2 消息通信流程图
S LLM API Background Worker Content Script Popup/Bookmarklet S LLM API Background Worker Content Script Popup/Bookmarklet sendMessage({action: 'getContext'}) 提取页面标题/URL/选中文字 sendResponse({title, url, selectedText}) 构建 Prompt sendMessage({action: 'callAPI', prompt}) POST /chat/completions Stream Response 流式返回 AI 回复 渲染打字机效果 保存历史记录
4.3 生命周期管理状态图
未注入
注入中:用户触发
注入中
已就绪:脚本加载完成
已就绪
对话框显示:点击激活
对话框显示
对话框隐藏:点击关闭
对话框隐藏
对话框显示:再次点击
销毁:页面刷新/手动移除
销毁:页面卸载
销毁
5. 关键代码实现
5.1 Manifest V3 配置文件
json
{
"manifest_version": 3,
"name": "PageAgent AI Assistant",
"version": "1.0.0",
"description": "在任意网页上与 AI 对话",
"permissions": [
"activeTab",
"scripting",
"storage"
],
"host_permissions": [
"<all_urls>"
],
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"],
"run_at": "document_idle",
"world": "MAIN"
}
],
"background": {
"service_worker": "background.js",
"type": "module"
}
}
5.2 Bookmarklet 注入代码
javascript
// bookmarklet.js - 压缩后作为 javascript: URL
(function() {
// 单例检查
if (window.__PAGE_AGENT__) {
window.__PAGE_AGENT__.toggle();
return;
}
// 创建样式隔离容器
const host = document.createElement('div');
host.id = 'page-agent-host';
const shadow = host.attachShadow({ mode: 'open' });
document.body.appendChild(host);
// 注入核心脚本
const script = document.createElement('script');
script.src = 'https://cdn.example.com/page-agent-core.js';
script.onload = () => {
window.__PAGE_AGENT__ = new PageAgent({
shadowRoot: shadow,
apiKey: localStorage.getItem('pa_api_key')
});
};
document.head.appendChild(script);
})();
5.3 Content Script 上下文提取
javascript
// content.js
class PageContextExtractor {
extract() {
return {
title: document.title,
url: location.href,
selectedText: window.getSelection().toString(),
metaDescription: this.getMeta('description'),
mainContent: this.extractMainContent()
};
}
getMeta(name) {
const el = document.querySelector(`meta[name="${name}"]`);
return el ? el.content : '';
}
extractMainContent() {
// 智能识别文章主体
const selectors = ['article', 'main', '.content', '#content'];
for (const sel of selectors) {
const el = document.querySelector(sel);
if (el) return el.innerText.slice(0, 5000);
}
return document.body.innerText.slice(0, 5000);
}
}
// 监听来自 Popup 的消息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'getPageContext') {
const context = new PageContextExtractor().extract();
sendResponse(context);
}
return true; // 异步响应
});
5.4 Shadow DOM UI 组件
javascript
// ui-component.js
class AgentDialog {
constructor(shadowRoot) {
this.shadow = shadowRoot;
this.render();
this.bindEvents();
}
render() {
const style = `
:host { all: initial; position: fixed; bottom: 80px; right: 20px; z-index: 2147483647; }
.container { width: 380px; height: 520px; background: #fff; border-radius: 12px;
box-shadow: 0 10px 40px rgba(0,0,0,0.2); display: flex; flex-direction: column; }
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white; padding: 14px 16px; font-weight: 600; display: flex; justify-content: space-between; }
.messages { flex: 1; padding: 16px; overflow-y: auto; background: #f8f9fa; }
.input-area { padding: 12px; border-top: 1px solid #eee; display: flex; gap: 8px; }
.msg { max-width: 85%; padding: 10px 14px; border-radius: 12px; margin-bottom: 10px; }
.msg.user { align-self: flex-end; background: #667eea; color: white; margin-left: auto; }
.msg.ai { align-self: flex-start; background: white; border: 1px solid #e0e0e0; }
`;
this.shadow.innerHTML = `
<style>${style}</style>
<div class="container">
<div class="header">
<span>🤖 PageAgent</span>
<span class="close-btn" style="cursor:pointer">✕</span>
</div>
<div class="messages"></div>
<div class="input-area">
<input type="text" placeholder="输入问题..." style="flex:1;padding:8px;border:1px solid #ddd;border-radius:6px;">
<button style="background:#667eea;color:white;border:none;padding:8px 16px;border-radius:6px;cursor:pointer">发送</button>
</div>
</div>
`;
}
bindEvents() {
this.shadow.querySelector('.close-btn').onclick = () => this.hide();
}
hide() {
this.shadow.querySelector('.container').style.display = 'none';
}
show() {
this.shadow.querySelector('.container').style.display = 'flex';
}
toggle() {
const el = this.shadow.querySelector('.container');
el.style.display = el.style.display === 'none' ? 'flex' : 'none';
}
}
5.5 API 调用与流式响应
javascript
// api-client.js
class LLMApiClient {
constructor(apiKey, baseUrl) {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
}
async chatStream(prompt, context, onChunk) {
const response = await fetch(`${this.baseUrl}/v1/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`
},
body: JSON.stringify({
model: 'gpt-4',
messages: [
{ role: 'system', content: '你是网页 AI 助手,基于当前页面内容回答问题。' },
{ role: 'user', content: `页面:${context.title}\nURL: ${context.url}\n问题:${prompt}` }
],
stream: true
})
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n').filter(l => l.startsWith('data: '));
for (const line of lines) {
const data = JSON.parse(line.slice(6));
if (data.choices[0].delta.content) {
onChunk(data.choices[0].delta.content);
}
}
}
}
}
6. 技术难点与解决方案
6.1 难点一:CSP (Content Security Policy) 限制
目标网站有严格 CSP
动态脚本注入失败
方案 1: 使用 nonce
方案 2: 预加载到扩展
方案 3: 引导安装插件
需要服务器配合
推荐方案
降级方案
解决方案:
javascript
// 在插件模式下,Content Script 不受 CSP 限制
// 在 Bookmarklet 模式下,检测 CSP 并降级提示
function detectCSP() {
try {
const script = document.createElement('script');
script.src = 'data:text/javascript,';
document.head.appendChild(script);
return false; // 无 CSP 限制
} catch (e) {
return true; // 有 CSP 限制
}
}
6.2 难点二:样式冲突与污染
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 外部 CSS 覆盖组件 | 全局样式优先级高 | Shadow DOM 隔离 |
| 组件 CSS 影响页面 | 选择器过于宽泛 | 限定作用域 + 唯一前缀 |
| z-index 层级问题 | 页面有固定定位元素 | 使用最大 z-index (2147483647) |
6.3 难点三:跨域通信安全
LLM 服务 Background Popup LLM 服务 Background Popup 验证来源 chrome.runtime.id 检查 使用 chrome.runtime.sendMessage 自动验证扩展身份 发送请求 (含敏感数据) 转发请求 (隐藏 API Key) 返回响应 返回结果
7. 面试介绍话术
7.1 30 秒电梯演讲
"我开发了一个网页内嵌式 AI 助手 ,支持书签拖拽 和浏览器插件 两种交互模式。核心技术是利用 Shadow DOM 实现样式隔离 ,通过 Content Script 注入获取页面上下文,让用户在任意网页都能直接与 AI 对话,无需切换标签页。"
7.2 技术亮点阐述

7.3 常见问题应答
| 面试官问题 | 参考回答 |
|---|---|
| 为什么选择 Shadow DOM? | "相比 iframe,Shadow DOM 更轻量且通信简单;相比普通 DOM,它能完全隔离样式,避免在复杂页面上出现样式冲突。" |
| 如何处理 CSP 限制? | "插件模式下 Content Script 不受 CSP 限制;书签模式下会检测 CSP,如有限制则引导用户安装插件作为降级方案。" |
| 如何保证 API Key 安全? | "前端不直接存储 API Key,通过后端代理转发请求;插件模式下可使用 chrome.storage 加密存储。" |
| 性能如何优化? | "采用懒加载策略,用户触发时才注入脚本;使用虚拟列表渲染长对话历史;流式响应减少首字等待时间。" |
8. 总结与展望
8.1 技术总结
两种交互方式
共同核心
Shadow DOM 隔离
上下文提取
LLM API 调用
书签模式
插件模式
优势:免安装
劣势:CSP 限制
优势:功能完整
劣势:需安装
8.2 未来优化方向
- 多模态支持:截图 OCR、语音输入输出
- 协作功能:多人共享会话、操作回放
- 私有化部署:支持本地 LLM (Ollama)
- 智能上下文:自动识别页面类型,优化 Prompt
8.3 核心收获
通过这个项目,我深入理解了浏览器扩展架构 、Web Component 隔离机制 和安全通信模型 。这些技术不仅适用于 AI 助手,也可以应用到网页调试工具 、自动化测试 、数据抓取等多个场景。
📎 附录:项目资源
| 资源 | 链接 |
|---|---|
| Chrome Extension 文档 | https://developer.chrome.com/docs/extensions/ |
| Shadow DOM 指南 | https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_shadow_DOM |
| Manifest V3 迁移 | https://developer.chrome.com/docs/extensions/mv3/intro/ |
| 示例代码仓库 | https://github.com/yourname/page-agent |
💡 面试提示 :在介绍项目时,重点突出你独立解决的技术难点 和架构设计思考,而非单纯罗列功能。用数据和对比说话,例如"样式冲突问题减少 90%"、"启动速度提升 3 倍"等。