<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello-Agents</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Description">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@latest/lib/themes/vue.css">
<style>
.lang-switch {
position: fixed;
top: 20px;
right: 80px;
z-index: 999;
}
.lang-switch button {
background: #42b983;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: background 0.3s;
}
.lang-switch button:hover {
background: #33a06f;
}
.giscus-container {
margin-top: 60px;
padding-top: 40px;
border-top: 1px solid #eee;
}
.giscus-toggle {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
padding: 15px 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 8px;
margin-bottom: 20px;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.2);
}
.giscus-toggle:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}
.giscus-toggle-title {
font-size: 1.3em;
font-weight: 600;
color: white;
margin: 0;
display: flex;
align-items: center;
gap: 10px;
}
.giscus-toggle-icon {
font-size: 1.2em;
transition: transform 0.3s ease;
color: white;
}
.giscus-toggle-icon.expanded {
transform: rotate(180deg);
}
.giscus-content {
max-height: 0;
overflow: hidden;
transition: max-height 0.4s ease-out, opacity 0.3s ease;
opacity: 0;
}
.giscus-content.expanded {
max-height: 2000px;
opacity: 1;
transition: max-height 0.5s ease-in, opacity 0.4s ease;
}
.giscus-hint {
font-size: 0.9em;
color: rgba(255, 255, 255, 0.9);
margin: 0;
}
:root {
--dark-bg: #1a1a1a;
--dark-text: #c4c4c4;
--dark-sidebar: #141414;
--dark-code-bg: #2b2b2b;
--dark-border: #333;
--theme-color: #42b983;
}
body.dark-mode {
background-color: var(--dark-bg);
color: var(--dark-text);
}
body.dark-mode .sidebar {
background-color: var(--dark-sidebar);
border-right: 1px solid var(--dark-border);
color: var(--dark-text);
}
body.dark-mode .sidebar-nav li a {
color: #999;
}
body.dark-mode .sidebar-nav li.active > a {
color: var(--theme-color);
border-right: 2px solid var(--theme-color);
}
body.dark-mode pre {
background-color: var(--dark-code-bg) !important;
}
body.dark-mode code {
background-color: var(--dark-code-bg) !important;
color: #e0e0e0 !important;
}
body.dark-mode .markdown-section code {
color: #f08d49;
background-color: rgba(255,255,255,0.1);
}
body.dark-mode h1, body.dark-mode h2, body.dark-mode h3, body.dark-mode h4 {
color: #e0e0e0;
}
body.dark-mode blockquote {
color: #999;
background: rgba(255,255,255,0.05);
border-left-color: var(--theme-color);
}
body.dark-mode .markdown-section tr:nth-child(2n) {
background-color: rgba(255,255,255,0.03);
}
body.dark-mode .markdown-section td,
body.dark-mode .markdown-section th {
border-color: var(--dark-border);
}
body.dark-mode .mermaid {
filter: invert(1) hue-rotate(180deg);
}
body.dark-mode .giscus-container {
border-top: 1px solid var(--dark-border);
}
.sidebar-toggle-btn {
cursor: pointer;
display: block;
text-align: center;
padding: 10px 0;
margin: 0 15px 10px 15px;
font-weight: bold;
font-size: 14px;
border-radius: 4px;
background-color: rgba(0,0,0,0.05);
color: #505d6b;
border: 1px solid rgba(0,0,0,0.05);
transition: all 0.3s;
}
body.dark-mode .sidebar-toggle-btn {
background-color: rgba(255,255,255,0.1);
color: #ccc;
border: 1px solid #444;
}
.sidebar-toggle-btn:hover {
background-color: var(--theme-color);
color: white;
}
</style>
</head>
<body>
<div class="lang-switch">
<button id="langBtn" onclick="switchLanguage()">English</button>
</div>
<div id="app"></div>
<script src="//cdn.jsdelivr.net/npm/mermaid@8.0.0-rc.8/dist/mermaid.min.js"></script>
<script>
window.$docsify = {
name: 'Hello-Agents',
repo: 'https://github.com/datawhalechina/Hello-Agents',
loadSidebar: true,
auto2top: true,
subMaxLevel: 3,
relativePath: false,
alias: {
'/en/README.md': '/README_EN.md',
'/en/_sidebar.md': '/_sidebar_en.md',
'/en/.*/_sidebar.md': '/_sidebar_en.md',
'/en/chapter(\\d+)/Chapter(.*)': '/chapter$1/Chapter$2',
'/_sidebar.md': '/_sidebar.md',
'/.*/_sidebar.md': '/_sidebar.md'
},
pagination: {
previousText: '上一章节',
nextText: '下一章节',
},
count: {
countable: true,
fontsize: '0.9em',
color: 'rgb(90,90,90)',
language: 'chinese'
},
fallbackLanguages: ['en'],
nameLink: {
'/en/': '#/en/',
'/': '#/'
},
plugins: [
function(hook, vm) {
hook.doneEach(function() {
const sidebar = document.querySelector('.sidebar-nav');
if (!sidebar || document.querySelector('.sidebar-toggle-btn')) return;
const btn = document.createElement('div');
btn.className = 'sidebar-toggle-btn';
const savedTheme = localStorage.getItem('theme-mode');
if (savedTheme === 'dark') {
document.body.classList.add('dark-mode');
btn.textContent = '🌙 Switch to Light';
} else {
btn.textContent = '☀️ Switch to Dark';
}
btn.onclick = function() {
document.body.classList.toggle('dark-mode');
const isDark = document.body.classList.contains('dark-mode');
localStorage.setItem('theme-mode', isDark ? 'dark' : 'light');
btn.textContent = isDark ? '🌙 Switch to Light' : '☀️ Switch to Dark';
const iframe = document.querySelector('iframe.giscus-frame');
if (iframe) {
iframe.contentWindow.postMessage({
giscus: {
setConfig: {
theme: isDark ? 'dark' : 'light'
}
}
}, 'https://giscus.app');
}
};
sidebar.insertBefore(btn, sidebar.firstChild);
});
},
function(hook, vm) {
hook.beforeEach(function(content) {
const preferredLang = localStorage.getItem('preferredLanguage');
const currentPath = vm.route.path;
if (currentPath.includes('/en/') || preferredLang === 'en') {
window.$docsify.pagination.previousText = 'Previous';
window.$docsify.pagination.nextText = 'Next';
} else {
window.$docsify.pagination.previousText = '上一章节';
window.$docsify.pagination.nextText = '下一章节';
}
return content;
});
hook.doneEach(function() {
const currentPath = vm.route.path;
const isChapterPage = currentPath.includes('chapter') ||
currentPath.includes('Chapter') ||
currentPath.includes('第') && currentPath.includes('章');
if (!isChapterPage) {
return;
}
const oldGiscus = document.querySelector('.giscus-container');
if (oldGiscus) {
oldGiscus.remove();
}
const giscusContainer = document.createElement('div');
giscusContainer.className = 'giscus-container';
const preferredLang = localStorage.getItem('preferredLanguage');
const isEnglish = currentPath.includes('/en/') || preferredLang === 'en';
const isDarkMode = document.body.classList.contains('dark-mode');
const toggleButton = document.createElement('div');
toggleButton.className = 'giscus-toggle';
const titleDiv = document.createElement('div');
titleDiv.className = 'giscus-toggle-title';
titleDiv.innerHTML = isEnglish
? '💬 Discussion & Questions'
: '💬 讨论与提问';
const hintText = document.createElement('p');
hintText.className = 'giscus-hint';
hintText.textContent = isEnglish
? 'Click to expand/collapse'
: '点击展开/收起';
const iconSpan = document.createElement('span');
iconSpan.className = 'giscus-toggle-icon';
iconSpan.textContent = '▼';
const titleWrapper = document.createElement('div');
titleWrapper.appendChild(titleDiv);
titleWrapper.appendChild(hintText);
toggleButton.appendChild(titleWrapper);
toggleButton.appendChild(iconSpan);
const contentDiv = document.createElement('div');
contentDiv.className = 'giscus-content';
const giscusScript = document.createElement('script');
giscusScript.src = 'https://giscus.app/client.js';
giscusScript.setAttribute('data-repo', 'datawhalechina/hello-agents');
giscusScript.setAttribute('data-repo-id', 'R_kgDOPrUECg');
giscusScript.setAttribute('data-category', '💬 Exercises & Q&A');
giscusScript.setAttribute('data-category-id', 'DIC_kwDOPrUECs4Cxfyu');
giscusScript.setAttribute('data-mapping', 'pathname');
giscusScript.setAttribute('data-strict', '0');
giscusScript.setAttribute('data-reactions-enabled', '1');
giscusScript.setAttribute('data-emit-metadata', '0');
giscusScript.setAttribute('data-input-position', 'top');
giscusScript.setAttribute('data-theme', isDarkMode ? 'dark' : 'light');
giscusScript.setAttribute('data-lang', isEnglish ? 'en' : 'zh-CN');
giscusScript.setAttribute('data-loading', 'lazy');
giscusScript.crossOrigin = 'anonymous';
giscusScript.async = true;
contentDiv.appendChild(giscusScript);
giscusContainer.appendChild(toggleButton);
giscusContainer.appendChild(contentDiv);
let isExpanded = false;
toggleButton.addEventListener('click', function() {
isExpanded = !isExpanded;
if (isExpanded) {
contentDiv.classList.add('expanded');
iconSpan.classList.add('expanded');
} else {
contentDiv.classList.remove('expanded');
iconSpan.classList.remove('expanded');
}
});
const article = document.querySelector('article.markdown-section');
if (article) {
article.appendChild(giscusContainer);
}
});
}
]
}
</script>
<script src="//cdn.jsdelivr.net/npm/docsify@latest/lib/docsify.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@latest/components/prism-bash.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@latest/components/prism-python.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-pagination@latest/dist/docsify-pagination.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-copy-code"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/katex@latest/dist/katex.min.js"></script>
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/katex@latest/dist/katex.min.css" />
<script src="https://cdn.jsdelivr.net/npm/marked@3"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-katex@latest/dist/docsify-katex.js"></script>
<script src="//unpkg.com/docsify-count/dist/countable.js"></script>
<script>
const chapterMapping = {
'zh2en': {
'README.md': 'README_EN.md',
'前言.md': 'Preface.md',
'第一章 初识智能体.md': 'Chapter1-Introduction-to-Agents.md',
'第二章 智能体发展史.md': 'Chapter2-History-of-Agents.md',
'第三章 大语言模型基础.md': 'Chapter3-Fundamentals-of-Large-Language-Models.md',
'第四章 智能体经典范式构建.md': 'Chapter4-Building-Classic-Agent-Paradigms.md',
'第五章 基于低代码平台的智能体搭建.md': 'Chapter5-Building-Agents-with-Low-Code-Platforms.md',
'第六章 框架开发实践.md': 'Chapter6-Framework-Development-Practice.md',
'第七章 构建你的Agent框架.md': 'Chapter7-Building-Your-Agent-Framework.md',
'第八章 记忆与检索.md': 'Chapter8-Memory-and-Retrieval.md',
'第九章 上下文工程.md': 'Chapter9-Context-Engineering.md',
'第十章 智能体通信协议.md': 'Chapter10-Agent-Communication-Protocols.md',
'第十一章 Agentic-RL.md': 'Chapter11-Agentic-RL.md',
'第十二章 智能体性能评估.md': 'Chapter12-Agent-Performance-Evaluation.md',
'第十三章 智能旅行助手.md': 'Chapter13-Intelligent-Travel-Assistant.md',
'第十四章 自动化深度研究智能体.md': 'Chapter14-Automated-Deep-Research-Agent.md',
'第十五章 构建赛博小镇.md': 'Chapter15-Building-Cyber-Town.md',
'第十六章 毕业设计.md': 'Chapter16-Graduation-Project.md'
},
'en2zh': {
'README_EN.md': 'README.md',
'Preface.md': '前言.md',
'Chapter1-Introduction-to-Agents.md': '第一章 初识智能体.md',
'Chapter2-History-of-Agents.md': '第二章 智能体发展史.md',
'Chapter3-Fundamentals-of-Large-Language-Models.md': '第三章 大语言模型基础.md',
'Chapter4-Building-Classic-Agent-Paradigms.md': '第四章 智能体经典范式构建.md',
'Chapter5-Building-Agents-with-Low-Code-Platforms.md': '第五章 基于低代码平台的智能体搭建.md',
'Chapter6-Framework-Development-Practice.md': '第六章 框架开发实践.md',
'Chapter7-Building-Your-Agent-Framework.md': '第七章 构建你的Agent框架.md',
'Chapter8-Memory-and-Retrieval.md': '第八章 记忆与检索.md',
'Chapter9-Context-Engineering.md': '第九章 上下文工程.md',
'Chapter10-Agent-Communication-Protocols.md': '第十章 智能体通信协议.md',
'Chapter11-Agentic-RL.md': '第十一章 Agentic-RL.md',
'Chapter12-Agent-Performance-Evaluation.md': '第十二章 智能体性能评估.md',
'Chapter13-Intelligent-Travel-Assistant.md': '第十三章 智能旅行助手.md',
'Chapter14-Automated-Deep-Research-Agent.md': '第十四章 自动化深度研究智能体.md',
'Chapter15-Building-Cyber-Town.md': '第十五章 构建赛博小镇.md',
'Chapter16-Graduation-Project.md': '第十六章 毕业设计.md'
}
};
function switchLanguage() {
const currentHash = window.location.hash;
const langBtn = document.getElementById('langBtn');
if (currentHash.includes('/en/')) {
localStorage.setItem('preferredLanguage', 'zh');
let newHash = currentHash.replace('#/', '').replace('en/', '');
const parts = newHash.split('/');
const filename = parts[parts.length - 1];
if (chapterMapping.en2zh[filename]) {
parts[parts.length - 1] = chapterMapping.en2zh[filename];
newHash = '#/' + parts.join('/');
} else {
newHash = '#/';
}
window.location.hash = newHash;
langBtn.textContent = 'English';
window.$docsify.pagination.previousText = '上一章节';
window.$docsify.pagination.nextText = '下一章节';
} else {
localStorage.setItem('preferredLanguage', 'en');
let path = currentHash.replace('#/', '');
if (path === '' || path === '/') {
window.location.hash = '#/en/README_EN.md';
} else {
const parts = path.split('/');
const filename = parts[parts.length - 1];
if (chapterMapping.zh2en[filename]) {
parts[parts.length - 1] = chapterMapping.zh2en[filename];
window.location.hash = '#/en/' + parts.join('/');
} else {
window.location.hash = '#/en/README_EN.md';
}
}
langBtn.textContent = '中文';
window.$docsify.pagination.previousText = 'Previous';
window.$docsify.pagination.nextText = 'Next';
}
window.location.reload();
}
window.addEventListener('load', function() {
const currentHash = window.location.hash;
const langBtn = document.getElementById('langBtn');
const preferredLang = localStorage.getItem('preferredLanguage');
if (preferredLang) {
if (preferredLang === 'en' && !currentHash.includes('/en/')) {
let path = currentHash.replace('#/', '');
if (path === '' || path === '/') {
window.location.hash = '#/en/README_EN.md';
} else {
const parts = path.split('/');
const filename = parts[parts.length - 1];
if (chapterMapping.zh2en[filename]) {
parts[parts.length - 1] = chapterMapping.zh2en[filename];
window.location.hash = '#/en/' + parts.join('/');
}
}
} else if (preferredLang === 'zh' && currentHash.includes('/en/')) {
let newHash = currentHash.replace('#/', '').replace('en/', '');
const parts = newHash.split('/');
const filename = parts[parts.length - 1];
if (chapterMapping.en2zh[filename]) {
parts[parts.length - 1] = chapterMapping.en2zh[filename];
window.location.hash = '#/' + parts.join('/');
}
}
}
if (currentHash.includes('/en/')) {
langBtn.textContent = '中文';
} else {
langBtn.textContent = 'English';
}
});
</script>
</body>
</html>