From 597e068031a5313af0fb4133fa45de266dff3fda Mon Sep 17 00:00:00 2001 From: joyehuang Date: Wed, 11 Feb 2026 18:33:01 +0800 Subject: [PATCH 1/5] feat: add papers reading module --- src/components/papers/PaperHero.astro | 121 ++++++++++++++++++ src/components/papers/PaperMeta.astro | 66 ++++++++++ src/components/papers/PaperPreview.astro | 108 ++++++++++++++++ src/content.config.ts | 38 +++++- .../post.mdx | 70 ++++++++++ .../post.mdx | 57 +++++++++ src/layouts/PaperPost.astro | 63 +++++++++ src/pages/index.astro | 18 ++- src/pages/papers/[...id].astro | 29 +++++ src/pages/papers/[...page].astro | 105 +++++++++++++++ src/pages/papers/tags/[tag]/[...page].astro | 72 +++++++++++ src/pages/papers/tags/index.astro | 51 ++++++++ src/site.config.ts | 3 + 13 files changed, 799 insertions(+), 2 deletions(-) create mode 100644 src/components/papers/PaperHero.astro create mode 100644 src/components/papers/PaperMeta.astro create mode 100644 src/components/papers/PaperPreview.astro create mode 100644 src/content/papers/20260211 - attention-is-all-you-need/post.mdx create mode 100644 src/content/papers/20260211 - back-to-basics-let-denoising-models-denoise/post.mdx create mode 100644 src/layouts/PaperPost.astro create mode 100644 src/pages/papers/[...id].astro create mode 100644 src/pages/papers/[...page].astro create mode 100644 src/pages/papers/tags/[tag]/[...page].astro create mode 100644 src/pages/papers/tags/index.astro diff --git a/src/components/papers/PaperHero.astro b/src/components/papers/PaperHero.astro new file mode 100644 index 0000000..79bd264 --- /dev/null +++ b/src/components/papers/PaperHero.astro @@ -0,0 +1,121 @@ +--- +import { Image } from 'astro:assets' +import type { InferEntrySchema } from 'astro:content' + +import { FormattedDate } from 'astro-pure/user' +import { cn } from 'astro-pure/utils' + +interface Props { + data: InferEntrySchema<'papers'> + remarkPluginFrontmatter: Record +} + +const { + data: { + title, + description, + draft, + heroImage, + publishDate, + updatedDate, + status, + tags, + language, + comment: enableComment + }, + remarkPluginFrontmatter +} = Astro.props + +const dateTimeOptions: Intl.DateTimeFormatOptions = { + month: 'short' +} + +const statusText = + status === 'reading' ? 'Reading' : status === 'revisit' ? 'Need Revisit' : 'Completed' + +const statusClass = + status === 'reading' + ? 'border-amber-300/70 bg-amber-100/60 text-amber-700 dark:border-amber-700/60 dark:bg-amber-900/30 dark:text-amber-300' + : status === 'revisit' + ? 'border-sky-300/70 bg-sky-100/60 text-sky-700 dark:border-sky-700/60 dark:bg-sky-900/30 dark:text-sky-300' + : 'border-emerald-300/70 bg-emerald-100/60 text-emerald-700 dark:border-emerald-700/60 dark:bg-emerald-900/30 dark:text-emerald-300' +--- + +{ + heroImage && ( +
+ {heroImage.alt +
+ ) +} + +{draft && (Draft)} + +
+
+ + + { + updatedDate && ( + <> + / + + Update + + + + ) + } + + + {remarkPluginFrontmatter.minutesRead} + { + language && ( + <> + + {language} + + ) + } + + {statusText} +
+ +

{title}

+ +
+ {description} +
+ + {!!tags.length && ( +
+ {tags.map((tag) => ( + + #{tag} + + ))} +
+ )} + + {!draft && enableComment && ( +

+ 阅读后欢迎在评论区讨论你对这篇论文的理解和分歧。 +

+ )} +
+ +
diff --git a/src/components/papers/PaperMeta.astro b/src/components/papers/PaperMeta.astro new file mode 100644 index 0000000..bf54916 --- /dev/null +++ b/src/components/papers/PaperMeta.astro @@ -0,0 +1,66 @@ +--- +import type { InferEntrySchema } from 'astro:content' +import { cn } from 'astro-pure/utils' + +interface Props { + data: InferEntrySchema<'papers'> + class?: string +} + +const { + data: { paperLink, pdfLink, codeLink, authors, venue, year }, + class: className +} = Astro.props +--- + +
+

Paper Reference

+ +
+ + Original Link ↗ + + { + pdfLink && ( + + PDF ↗ + + ) + } + { + codeLink && ( + + Code ↗ + + ) + } +
+ +
+

+ Authors: + {authors.join(', ')} +

+

+ Venue: + {venue || 'N/A'} + {' · '} + {year} +

+
+
diff --git a/src/components/papers/PaperPreview.astro b/src/components/papers/PaperPreview.astro new file mode 100644 index 0000000..fae648b --- /dev/null +++ b/src/components/papers/PaperPreview.astro @@ -0,0 +1,108 @@ +--- +import type { CollectionEntry } from 'astro:content' +import { FormattedDate } from 'astro-pure/user' +import { cn } from 'astro-pure/utils' + +interface Props { + paper: CollectionEntry<'papers'> + detailed?: boolean + class?: string +} + +const { paper, detailed = false, class: className } = Astro.props + +const { + id, + data: { title, description, publishDate, updatedDate, status, tags, venue, year, paperLink, draft } +} = paper + +const postDate = updatedDate ?? publishDate + +const statusText = + status === 'reading' ? 'Reading' : status === 'revisit' ? 'Need Revisit' : 'Completed' + +const statusClass = + status === 'reading' + ? 'border-amber-300/70 bg-amber-100/60 text-amber-700 dark:border-amber-700/60 dark:bg-amber-900/30 dark:text-amber-300' + : status === 'revisit' + ? 'border-sky-300/70 bg-sky-100/60 text-sky-700 dark:border-sky-700/60 dark:bg-sky-900/30 dark:text-sky-300' + : 'border-emerald-300/70 bg-emerald-100/60 text-emerald-700 dark:border-emerald-700/60 dark:bg-emerald-900/30 dark:text-emerald-300' +--- + +
  • + +
    + + + {year} + {venue && ( + <> + + {venue} + + )} + + + {statusText} + +
    + +
    +

    + {draft && (Draft) } + {title} +

    + + + + +
    + +

    + {description} +

    +
    + +
    + + Original Paper ↗ + + { + tags.map((tag) => ( + + #{tag} + + )) + } +
    +
  • diff --git a/src/content.config.ts b/src/content.config.ts index 8237059..17cf58f 100644 --- a/src/content.config.ts +++ b/src/content.config.ts @@ -39,4 +39,40 @@ const blog = defineCollection({ }) }) -export const collections = { blog } +const papers = defineCollection({ + // Load Markdown and MDX files in the `src/content/papers/` directory. + loader: glob({ base: './src/content/papers', pattern: '**/*.{md,mdx}' }), + schema: ({ image }) => + z.object({ + // Required + title: z.string().max(120), + description: z.string().max(280), + publishDate: z.coerce.date(), + paperLink: z.string().url(), + authors: z.array(z.string()).min(1), + year: z.number().int(), + // Optional + updatedDate: z.coerce.date().optional(), + venue: z.string().optional(), + pdfLink: z.string().url().optional(), + codeLink: z.string().url().optional(), + heroImage: z + .object({ + src: image(), + alt: z.string().optional(), + inferSize: z.boolean().optional(), + width: z.number().optional(), + height: z.number().optional(), + color: z.string().optional() + }) + .optional(), + tags: z.array(z.string()).default([]).transform(removeDupsAndLowerCase), + status: z.enum(['reading', 'completed', 'revisit']).default('completed'), + language: z.string().optional(), + draft: z.boolean().default(false), + comment: z.boolean().default(true), + featured: z.boolean().default(false) + }) +}) + +export const collections = { blog, papers } diff --git a/src/content/papers/20260211 - attention-is-all-you-need/post.mdx b/src/content/papers/20260211 - attention-is-all-you-need/post.mdx new file mode 100644 index 0000000..004e42e --- /dev/null +++ b/src/content/papers/20260211 - attention-is-all-you-need/post.mdx @@ -0,0 +1,70 @@ +--- +title: Attention Is All You Need 精读 +description: Transformer 论文精读,聚焦 self-attention 设计动机、模型结构、训练细节与影响,并补充我在实现和阅读中的关键笔记。 +publishDate: 2026-02-11 00:00:00 +paperLink: https://arxiv.org/abs/1706.03762 +pdfLink: https://arxiv.org/pdf/1706.03762 +authors: + - Ashish Vaswani + - Noam Shazeer + - Niki Parmar + - Jakob Uszkoreit + - Llion Jones + - Aidan N. Gomez + - Lukasz Kaiser + - Illia Polosukhin +venue: NeurIPS +year: 2017 +tags: ['Transformer', 'Attention', 'NLP', 'Foundation'] +status: completed +language: en +featured: true +comment: true +--- + +## Paper Info + +- Original link: [Attention Is All You Need](https://arxiv.org/abs/1706.03762) +- Main topic: sequence modeling without recurrence/convolution +- One-line takeaway: 用全局自注意力替代 RNN/CNN,显著提升并行效率和长程依赖建模能力。 + +## Core Contributions + +1. 提出 `Encoder-Decoder + Multi-Head Self-Attention` 的完整架构。 +2. 用 `Scaled Dot-Product Attention` 稳定训练(除以 `sqrt(d_k)`)。 +3. 通过 `Positional Encoding` 注入位置信息,而非依赖循环结构。 +4. 在机器翻译任务上实现更优质量和更低训练成本。 + +## Method Breakdown + +- Attention 基本形式: + +```text +Attention(Q, K, V) = softmax(QK^T / sqrt(d_k)) V +``` + +- 关键模块组合: + - Multi-Head Attention + - Position-wise FeedForward + - Residual + LayerNorm +- 在实现层面,我最关注两点: + - head 维度切分和拼接是否保持 shape 一致 + - mask 应用顺序是否正确(softmax 前) + +## Experiment Notes + +- 论文强调训练效率:在 GPU 上并行度明显高于 RNN。 +- BLEU 指标提升说明该架构不仅更快,也更有效。 +- Ablation 里 multi-head 的收益很稳定,说明“多视角对齐”确实有效。 + +## My Notes + +- 这篇论文最“工程可迁移”的点:结构简单、扩展性高。 +- 从今天看,它也是后续 GPT/BERT 系列架构的关键起点。 +- 真正读懂它后,再看 modern LLM block 的变化(RoPE/RMSNorm/SwiGLU)会更清晰。 + +## Open Questions & Ideas + +1. 在更长上下文下,注意力复杂度如何进一步优化? +2. 不同位置编码(绝对/相对/旋转)和原版 sinusoidal 的取舍边界是什么? +3. 多头数量增大何时开始出现收益递减? diff --git a/src/content/papers/20260211 - back-to-basics-let-denoising-models-denoise/post.mdx b/src/content/papers/20260211 - back-to-basics-let-denoising-models-denoise/post.mdx new file mode 100644 index 0000000..e5d2e70 --- /dev/null +++ b/src/content/papers/20260211 - back-to-basics-let-denoising-models-denoise/post.mdx @@ -0,0 +1,57 @@ +--- +title: 'Back to Basics: Let Denoising Generative Models Denoise 精读' +description: 围绕 Kaiming He 团队这篇 denoising 生成模型论文的结构化阅读笔记,记录核心动机、方法、实验观察和后续待验证的问题。 +publishDate: 2026-02-11 00:00:00 +paperLink: https://arxiv.org/abs/2511.13720 +pdfLink: https://arxiv.org/pdf/2511.13720 +authors: + - Kaiming He + - et al. +venue: arXiv +year: 2025 +tags: ['Generative Model', 'Diffusion', 'Denoising'] +status: reading +language: en +featured: true +comment: true +--- + +## Paper Info + +- Original link: [Back to Basics: Let Denoising Generative Models Denoise](https://arxiv.org/abs/2511.13720) +- Main topic: denoising generative models 的训练与采样机制重审 +- One-line takeaway: 回到“denoise 本身”这一目标,重新定义模型该优化什么、如何优化。 + +## Core Contributions + +1. 重新审视 denoising 生成模型中的训练目标与噪声建模假设。 +2. 给出更直接贴合 denoise 任务本质的建模方式。 +3. 在实验中验证“回归本质目标”带来的质量和稳定性收益。 + +## Method Breakdown + +- 阅读阶段我重点追踪三件事: + - 目标函数相对传统 diffusion objective 的变化 + - 不同 noise level 下模型行为差异 + - 训练/推理阶段是否保持一致的 denoise 语义 +- 当前结论:该工作试图削减任务定义与优化目标之间的偏差。 + +## Experiment Notes + +- 我会重点复核以下指标: + - 生成质量指标(FID/IS 或任务对应指标) + - 采样步数与质量/速度折中 + - 稳定性与复现敏感性 +- 初步印象:论文强调“简单有效”的路径,而非堆叠复杂技巧。 + +## My Notes + +- 这篇论文对我的启发:很多时候性能瓶颈不是网络结构,而是 objective 对任务本身的错配。 +- 读这类论文时,先盯“优化目标”比先盯“模块创新”更容易抓住本质。 +- 后续我计划做一个小规模复现实验,对比 baseline 与该方法在同数据集上的差异。 + +## Open Questions & Ideas + +1. 该方法在不同数据分布(图像分辨率、类别复杂度)下是否稳健? +2. 当模型规模增大时,收益是放大还是被稀释? +3. 是否能与 consistency / flow matching 的训练范式结合? diff --git a/src/layouts/PaperPost.astro b/src/layouts/PaperPost.astro new file mode 100644 index 0000000..5276082 --- /dev/null +++ b/src/layouts/PaperPost.astro @@ -0,0 +1,63 @@ +--- +import type { MarkdownHeading } from 'astro' +import type { CollectionEntry } from 'astro:content' + +import 'katex/dist/katex.min.css' + +import { Comment, MediumZoom } from 'astro-pure/advanced' +import { ArticleBottom, Copyright, TOC } from 'astro-pure/components/pages' +import PaperHero from '@/components/papers/PaperHero.astro' +import PaperMeta from '@/components/papers/PaperMeta.astro' +import PageLayout from '@/layouts/ContentLayout.astro' +import { integ } from '@/site-config' + +interface Props { + paper: CollectionEntry<'papers'> + papers: CollectionEntry<'papers'>[] + headings: MarkdownHeading[] + remarkPluginFrontmatter: Record +} + +const { + paper: { id, data }, + papers, + headings, + remarkPluginFrontmatter +} = Astro.props + +const { description, heroImage, publishDate, title, updatedDate, draft: isDraft, comment } = data + +const socialImage = heroImage + ? typeof heroImage.src === 'string' + ? heroImage.src + : heroImage.src.src + : '/images/social-card.png' + +const articleDate = updatedDate?.toISOString() ?? publishDate.toISOString() +const primaryColor = data.heroImage?.color ?? 'hsl(var(--primary) / var(--un-text-opacity))' +--- + + + {!!headings.length && } + + + + + + + + + + + + {!isDraft && comment && } + + + + + +{integ.mediumZoom.enable && } diff --git a/src/pages/index.astro b/src/pages/index.astro index b9a4136..f6d0a18 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,13 +1,14 @@ --- import { Image } from 'astro:assets' +import type { CollectionEntry } from 'astro:content' import avatar from 'src/assets/avatar.png' import { Quote } from 'astro-pure/advanced' import { PostPreview } from 'astro-pure/components/pages' import { getBlogCollection, sortMDByDate } from 'astro-pure/server' import { Button, Card, Icon, Label } from 'astro-pure/user' +import PaperPreview from '@/components/papers/PaperPreview.astro' import PageLayout from '@/layouts/BaseLayout.astro' -import ProjectCard from '@/components/home/ProjectCard.astro' import Section from '@/components/home/Section.astro' import SkillLayout from '@/components/home/SkillLayout.astro' import config from '@/site-config' @@ -20,6 +21,9 @@ const tools = ['Curor', 'Git', 'Docker', 'Postman', 'ESlint/Prettier', 'Jest'] const MAX_POSTS = 10 const allPosts = await getBlogCollection() const allPostsByDate = sortMDByDate(allPosts).slice(0, MAX_POSTS) +const MAX_PAPERS = 5 +const allPapers = (await getBlogCollection('papers')) as CollectionEntry<'papers'>[] +const allPapersByDate = sortMDByDate(allPapers).slice(0, MAX_PAPERS) as CollectionEntry<'papers'>[] --- @@ -106,6 +110,18 @@ const allPostsByDate = sortMDByDate(allPosts).slice(0, MAX_POSTS) ) } + { + allPapersByDate.length > 0 && ( +
    +
      + {allPapersByDate.map((paper) => ( + + ))} +
    +
    + ) + }
    []) + + return papers.map((paper) => ({ + params: { id: paper.id }, + props: { paper, papers } + })) +} + +type Props = { + paper: CollectionEntry<'papers'> + papers: CollectionEntry<'papers'>[] +} + +const { paper, papers } = Astro.props +const { Content, headings, remarkPluginFrontmatter } = await render(paper) +--- + + + + diff --git a/src/pages/papers/[...page].astro b/src/pages/papers/[...page].astro new file mode 100644 index 0000000..a5c46c0 --- /dev/null +++ b/src/pages/papers/[...page].astro @@ -0,0 +1,105 @@ +--- +import type { GetStaticPaths, Page } from 'astro' +import type { CollectionEntry } from 'astro:content' + +import { Paginator } from 'astro-pure/components/pages' +import { getBlogCollection, getUniqueTags, sortMDByDate } from 'astro-pure/server' +import { Button, Icon } from 'astro-pure/user' +import PaperPreview from '@/components/papers/PaperPreview.astro' +import PageLayout from '@/layouts/BaseLayout.astro' +import { paperPageSize } from '@/site-config' + +export const prerender = true + +export const getStaticPaths = (async ({ paginate }) => { + const papers = sortMDByDate((await getBlogCollection('papers')) as CollectionEntry<'papers'>[]) + const uniqueTags = getUniqueTags(papers) + const collectionsCount = papers.length + + return paginate(papers, { + pageSize: paperPageSize, + props: { uniqueTags, collectionsCount } + }) +}) satisfies GetStaticPaths + +interface Props { + page: Page> + uniqueTags: string[] + collectionsCount: number +} + +const { page, uniqueTags, collectionsCount } = Astro.props + +const meta = { + description: 'Paper reading notes, deep dives, and annotations', + title: 'Papers' +} + +const paginationProps = { + ...(page.url.prev && { + prevUrl: { + text: '← Previous Papers', + url: page.url.prev + } + }), + ...(page.url.next && { + nextUrl: { + text: 'Next Papers →', + url: page.url.next + } + }) +} +--- + + + + + ))} + + ) : ( +

    Any tag yet.

    + ) + } + + +
    diff --git a/src/site.config.ts b/src/site.config.ts index 0a54cc4..8837445 100644 --- a/src/site.config.ts +++ b/src/site.config.ts @@ -48,6 +48,7 @@ export const theme: ThemeUserConfig = { header: { menu: [ { title: 'Blog', link: '/blog' }, + { title: 'Papers', link: '/papers' }, { title: 'Projects', link: '/projects' }, { title: 'Links', link: '/links' }, { title: 'About', link: '/about' } @@ -83,6 +84,8 @@ export const theme: ThemeUserConfig = { } } +export const paperPageSize = 8 + export const integ: IntegrationUserConfig = { // Links management // See: https://astro-pure.js.org/docs/integrations/links From e52faa265a3452c834337ab58ded033fab71d6bb Mon Sep 17 00:00:00 2001 From: joyehuang Date: Thu, 12 Feb 2026 17:25:01 +0800 Subject: [PATCH 2/5] feat: add full English i18n site under /en --- src/components/BaseHead.astro | 22 +++- src/components/papers/PaperHero.astro | 22 +++- src/components/papers/PaperMeta.astro | 4 +- src/components/papers/PaperPreview.astro | 11 +- src/content.config.ts | 45 +++++--- .../blog-en/20250701 - firstPR/post.mdx | 35 ++++++ .../20250712 - astroThemePureWaline/post.mdx | 49 ++++++++ .../20251023 - internshipExperience/post.mdx | 51 +++++++++ .../blog-en/20251216 - normalization/post.mdx | 30 +++++ .../post.mdx | 28 +++++ .../20251218 - attention-mechanism/post.mdx | 28 +++++ .../post.mdx | 32 ++++++ src/content/blog/20250701 - firstPR/post.mdx | 2 + .../20250712 - astroThemePureWaline/post.mdx | 2 + .../20251023 - internshipExperience/post.mdx | 2 + .../blog/20251216 - normalization/post.mdx | 2 + .../post.mdx | 2 + .../20251218 - attention-mechanism/post.mdx | 2 + .../post.mdx | 2 + .../post.mdx | 41 +++++++ .../post.mdx | 39 +++++++ .../post.mdx | 2 + .../post.mdx | 2 + src/i18n/locales.ts | 18 +++ src/i18n/messages.ts | 12 ++ src/i18n/routing.ts | 87 +++++++++++++++ src/layouts/BaseLayout.astro | 53 ++++++++- src/layouts/BlogPost.astro | 21 +++- src/layouts/CommonPage.astro | 3 + src/layouts/ContentLayout.astro | 3 + src/layouts/IndividualPage.astro | 6 +- src/layouts/PaperPost.astro | 24 +++- src/middleware.ts | 28 +++++ src/pages/blog/[...id].astro | 17 ++- src/pages/en/about/index.astro | 53 +++++++++ src/pages/en/archives/index.astro | 54 +++++++++ src/pages/en/blog/[...id].astro | 45 ++++++++ src/pages/en/blog/[...page].astro | 104 +++++++++++++++++ src/pages/en/index.astro | 89 +++++++++++++++ src/pages/en/links/index.astro | 73 ++++++++++++ src/pages/en/papers/[...id].astro | 45 ++++++++ src/pages/en/papers/[...page].astro | 105 ++++++++++++++++++ .../en/papers/tags/[tag]/[...page].astro | 72 ++++++++++++ src/pages/en/papers/tags/index.astro | 51 +++++++++ src/pages/en/projects/index.astro | 72 ++++++++++++ src/pages/en/rss.xml.ts | 77 +++++++++++++ src/pages/en/search/index.astro | 33 ++++++ src/pages/en/tags/[tag]/[...page].astro | 72 ++++++++++++ src/pages/en/tags/index.astro | 51 +++++++++ src/pages/en/terms/copyright.md | 11 ++ src/pages/en/terms/disclaimer.md | 11 ++ src/pages/en/terms/list.astro | 37 ++++++ src/pages/en/terms/privacy-policy.md | 11 ++ src/pages/en/terms/terms-and-conditions.md | 11 ++ src/pages/papers/[...id].astro | 22 +++- src/pages/rss.xml.ts | 4 +- src/utils/content-i18n.ts | 41 +++++++ tsconfig.json | 1 + 58 files changed, 1818 insertions(+), 54 deletions(-) create mode 100644 src/content/blog-en/20250701 - firstPR/post.mdx create mode 100644 src/content/blog-en/20250712 - astroThemePureWaline/post.mdx create mode 100644 src/content/blog-en/20251023 - internshipExperience/post.mdx create mode 100644 src/content/blog-en/20251216 - normalization/post.mdx create mode 100644 src/content/blog-en/20251217 - rope-position-encoding/post.mdx create mode 100644 src/content/blog-en/20251218 - attention-mechanism/post.mdx create mode 100644 src/content/blog-en/20251219 - feedforward-transformer-block/post.mdx create mode 100644 src/content/papers-en/20260211 - attention-is-all-you-need/post.mdx create mode 100644 src/content/papers-en/20260211 - back-to-basics-let-denoising-models-denoise/post.mdx create mode 100644 src/i18n/locales.ts create mode 100644 src/i18n/messages.ts create mode 100644 src/i18n/routing.ts create mode 100644 src/middleware.ts create mode 100644 src/pages/en/about/index.astro create mode 100644 src/pages/en/archives/index.astro create mode 100644 src/pages/en/blog/[...id].astro create mode 100644 src/pages/en/blog/[...page].astro create mode 100644 src/pages/en/index.astro create mode 100644 src/pages/en/links/index.astro create mode 100644 src/pages/en/papers/[...id].astro create mode 100644 src/pages/en/papers/[...page].astro create mode 100644 src/pages/en/papers/tags/[tag]/[...page].astro create mode 100644 src/pages/en/papers/tags/index.astro create mode 100644 src/pages/en/projects/index.astro create mode 100644 src/pages/en/rss.xml.ts create mode 100644 src/pages/en/search/index.astro create mode 100644 src/pages/en/tags/[tag]/[...page].astro create mode 100644 src/pages/en/tags/index.astro create mode 100644 src/pages/en/terms/copyright.md create mode 100644 src/pages/en/terms/disclaimer.md create mode 100644 src/pages/en/terms/list.astro create mode 100644 src/pages/en/terms/privacy-policy.md create mode 100644 src/pages/en/terms/terms-and-conditions.md create mode 100644 src/utils/content-i18n.ts diff --git a/src/components/BaseHead.astro b/src/components/BaseHead.astro index 4071b3f..412a6c1 100644 --- a/src/components/BaseHead.astro +++ b/src/components/BaseHead.astro @@ -3,15 +3,26 @@ import { prod } from 'astro-pure/server' import type { SiteMeta } from 'astro-pure/types' +import { LOCALE_META, type Locale } from '@/i18n/locales' +import { toChinesePath, toEnglishPath } from '@/i18n/routing' import config from '@/site-config' -type Props = SiteMeta +type Props = SiteMeta & { + locale?: Locale + alternatePath?: string +} -const { articleDate, description, ogImage, title } = Astro.props +const { articleDate, description, ogImage, title, locale = 'zh', alternatePath } = Astro.props const siteTitle = `${title} ${config.titleDelimiter} ${config.title}` const canonicalURL = new URL(Astro.url.pathname, Astro.site) const socialImageURL = new URL(ogImage ? ogImage : '/images/social-card.png', Astro.url).href +const localeMeta = LOCALE_META[locale] +const zhPath = toChinesePath(Astro.url.pathname) +const enPath = alternatePath && locale === 'zh' ? alternatePath : toEnglishPath(Astro.url.pathname) +const alternateZhURL = new URL(locale === 'en' && alternatePath ? alternatePath : zhPath, Astro.site) +const alternateEnURL = new URL(locale === 'en' && alternatePath ? alternatePath : enPath, Astro.site) +const rssPath = locale === 'en' ? '/en/rss.xml' : '/rss.xml' --- @@ -52,7 +63,7 @@ const socialImageURL = new URL(ogImage ? ogImage : '/images/social-card.png', As - + @@ -74,13 +85,16 @@ const socialImageURL = new URL(ogImage ? ogImage : '/images/social-card.png', As {/* Sitemap */} + + + {/* RSS auto-discovery */} diff --git a/src/components/papers/PaperHero.astro b/src/components/papers/PaperHero.astro index 79bd264..69c4fb5 100644 --- a/src/components/papers/PaperHero.astro +++ b/src/components/papers/PaperHero.astro @@ -4,10 +4,15 @@ import type { InferEntrySchema } from 'astro:content' import { FormattedDate } from 'astro-pure/user' import { cn } from 'astro-pure/utils' +import type { Locale } from '@/i18n/locales' + +type PaperSchema = InferEntrySchema<'papers'> | InferEntrySchema<'papersEn'> interface Props { - data: InferEntrySchema<'papers'> + data: PaperSchema remarkPluginFrontmatter: Record + locale?: Locale + tagBasePath?: string } const { @@ -23,7 +28,9 @@ const { language, comment: enableComment }, - remarkPluginFrontmatter + remarkPluginFrontmatter, + locale = 'zh', + tagBasePath = '/papers' } = Astro.props const dateTimeOptions: Intl.DateTimeFormatOptions = { @@ -45,11 +52,14 @@ const statusClass = heroImage && (
    {heroImage.alt
    ) @@ -103,7 +113,7 @@ const statusClass = #{tag} @@ -113,7 +123,9 @@ const statusClass = {!draft && enableComment && (

    - 阅读后欢迎在评论区讨论你对这篇论文的理解和分歧。 + {locale === 'en' + ? "After reading, feel free to share your thoughts and disagreements in the comments." + : '阅读后欢迎在评论区讨论你对这篇论文的理解和分歧。'}

    )} diff --git a/src/components/papers/PaperMeta.astro b/src/components/papers/PaperMeta.astro index bf54916..f1abf85 100644 --- a/src/components/papers/PaperMeta.astro +++ b/src/components/papers/PaperMeta.astro @@ -2,8 +2,10 @@ import type { InferEntrySchema } from 'astro:content' import { cn } from 'astro-pure/utils' +type PaperSchema = InferEntrySchema<'papers'> | InferEntrySchema<'papersEn'> + interface Props { - data: InferEntrySchema<'papers'> + data: PaperSchema class?: string } diff --git a/src/components/papers/PaperPreview.astro b/src/components/papers/PaperPreview.astro index fae648b..a069e6d 100644 --- a/src/components/papers/PaperPreview.astro +++ b/src/components/papers/PaperPreview.astro @@ -3,13 +3,16 @@ import type { CollectionEntry } from 'astro:content' import { FormattedDate } from 'astro-pure/user' import { cn } from 'astro-pure/utils' +type PaperEntry = CollectionEntry<'papers'> | CollectionEntry<'papersEn'> + interface Props { - paper: CollectionEntry<'papers'> + paper: PaperEntry detailed?: boolean class?: string + basePath?: string } -const { paper, detailed = false, class: className } = Astro.props +const { paper, detailed = false, class: className, basePath = '/papers' } = Astro.props const { id, @@ -36,7 +39,7 @@ const statusClass = className )} > - +
    @@ -96,7 +99,7 @@ const statusClass = { tags.map((tag) => ( diff --git a/src/content.config.ts b/src/content.config.ts index 17cf58f..3b2d1ea 100644 --- a/src/content.config.ts +++ b/src/content.config.ts @@ -8,17 +8,14 @@ function removeDupsAndLowerCase(array: string[]) { return Array.from(distinctItems) } -const blog = defineCollection({ - // Load Markdown and MDX files in the `src/content/blog/` directory. - loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }), - // Required - schema: ({ image }) => +const createBlogSchema = (locale: 'zh' | 'en') => + ({ image }: { image: () => z.ZodTypeAny }) => z.object({ - // Required title: z.string().max(60), description: z.string().max(160), publishDate: z.coerce.date(), - // Optional + locale: z.literal(locale), + translationKey: z.string(), updatedDate: z.coerce.date().optional(), heroImage: z .object({ @@ -27,31 +24,26 @@ const blog = defineCollection({ inferSize: z.boolean().optional(), width: z.number().optional(), height: z.number().optional(), - color: z.string().optional() }) .optional(), tags: z.array(z.string()).default([]).transform(removeDupsAndLowerCase), language: z.string().optional(), draft: z.boolean().default(false), - // Special fields comment: z.boolean().default(true) }) -}) -const papers = defineCollection({ - // Load Markdown and MDX files in the `src/content/papers/` directory. - loader: glob({ base: './src/content/papers', pattern: '**/*.{md,mdx}' }), - schema: ({ image }) => +const createPaperSchema = (locale: 'zh' | 'en') => + ({ image }: { image: () => z.ZodTypeAny }) => z.object({ - // Required title: z.string().max(120), description: z.string().max(280), publishDate: z.coerce.date(), + locale: z.literal(locale), + translationKey: z.string(), paperLink: z.string().url(), authors: z.array(z.string()).min(1), year: z.number().int(), - // Optional updatedDate: z.coerce.date().optional(), venue: z.string().optional(), pdfLink: z.string().url().optional(), @@ -73,6 +65,25 @@ const papers = defineCollection({ comment: z.boolean().default(true), featured: z.boolean().default(false) }) + +const blog = defineCollection({ + loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }), + schema: createBlogSchema('zh') +}) + +const blogEn = defineCollection({ + loader: glob({ base: './src/content/blog-en', pattern: '**/*.{md,mdx}' }), + schema: createBlogSchema('en') +}) + +const papers = defineCollection({ + loader: glob({ base: './src/content/papers', pattern: '**/*.{md,mdx}' }), + schema: createPaperSchema('zh') +}) + +const papersEn = defineCollection({ + loader: glob({ base: './src/content/papers-en', pattern: '**/*.{md,mdx}' }), + schema: createPaperSchema('en') }) -export const collections = { blog, papers } +export const collections = { blog, blogEn, papers, papersEn } diff --git a/src/content/blog-en/20250701 - firstPR/post.mdx b/src/content/blog-en/20250701 - firstPR/post.mdx new file mode 100644 index 0000000..b5b523e --- /dev/null +++ b/src/content/blog-en/20250701 - firstPR/post.mdx @@ -0,0 +1,35 @@ +--- +title: My First Pull Request +description: 'A second-year student’s first successful open-source PR journey' +publishDate: 2025-07-01 22:06:36 +locale: en +translationKey: first-pr +tags: ['Open Source', 'Frontend'] +--- +import { GithubCard } from 'astro-pure/advanced' + +## Intro +On June 27, 2025 (Melbourne time), I submitted my first pull request to the VMind project in the VisActor community. I was excited and nervous at the same time. For a long time, open source felt like something only "very advanced" developers could do. + +## How I Found the Project +I discovered VMind while scanning JavaScript-related OSPP topics. I contacted a mentor and then joined the VisActor contributors group. The collaboration flow was friendly and clear: pick an issue, comment, sync in the group, and receive feedback quickly. + + + +## What I Worked On +I picked a unit-test issue and implemented tests for `getChartSpecWithContext_boxplot`. The goal was to verify data field mapping and chart-spec generation logic for BoxPlot charts. + +## What Helped Me Most +- Reading existing tests before writing my own. +- Using AI for guidance, not for copy-paste answers. +- Asking reviewers early and iterating quickly after feedback. + +## The Merge Moment +After two rounds of updates, the PR was merged on July 1, 2025. That moment gave me confidence to keep contributing. + +## Key Takeaways +- First PRs are mostly about process, not brilliance. +- Imitating strong examples is a valid learning strategy. +- Owning an issue creates healthy pressure and momentum. + +If you are considering open source, start with one small issue and keep going. diff --git a/src/content/blog-en/20250712 - astroThemePureWaline/post.mdx b/src/content/blog-en/20250712 - astroThemePureWaline/post.mdx new file mode 100644 index 0000000..cb249d8 --- /dev/null +++ b/src/content/blog-en/20250712 - astroThemePureWaline/post.mdx @@ -0,0 +1,49 @@ +--- +title: Full Waline Setup Guide for astro-theme-pure +description: 'A practical deployment walkthrough for Waline on Astro, with common pitfalls and fixes' +publishDate: 2025-07-12 05:08:21 +locale: en +translationKey: waline-guide +tags: ['Waline', 'Tutorial'] +--- +import { Aside } from 'astro-pure/user' + +## Preface +This article records my end-to-end process of deploying Waline for an Astro blog with `astro-theme-pure`, using Vercel + LeanCloud. + + + +## Step 1: Create LeanCloud Credentials +Register a LeanCloud app and copy: +- `App ID` +- `App Key` +- `Master Key` + +## Step 2: Deploy Waline Server on Vercel +Use the official one-click template and wait for deployment to finish. + +## Step 3: Configure Environment Variables +Add these variables in Vercel project settings: +- `LEAN_ID` +- `LEAN_KEY` +- `LEAN_MASTER_KEY` + +Then redeploy. + +## Step 4: Bind a Custom Domain (Recommended) +A custom domain can prevent DNS-related issues such as initialization failures. + +## Step 5: Initialize Admin +Visit `/ui` on your Waline server URL and register your admin account. +Avoid third-party login methods during first-time admin setup. + +## Step 6: Connect Waline in Astro +Update `src/site.config.ts` with your Waline server URL and desired client options. + +## Step 7: Verify +Open any post page and confirm: +- comment widget loads correctly +- page view count is updating + +## Conclusion +Waline works very well with Astro once the server and config are aligned. If you are using `astro-theme-pure`, this setup should be straightforward with the checklist above. diff --git a/src/content/blog-en/20251023 - internshipExperience/post.mdx b/src/content/blog-en/20251023 - internshipExperience/post.mdx new file mode 100644 index 0000000..13c0349 --- /dev/null +++ b/src/content/blog-en/20251023 - internshipExperience/post.mdx @@ -0,0 +1,51 @@ +--- +title: Frontend Internship Interview Notes (SMB Teams) +description: 'A practical summary of high-frequency interview topics, data from applications, and preparation strategy' +publishDate: 2025-10-23 16:00:00 +locale: en +translationKey: internship-interview-guide +tags: ['Internship', 'Frontend', 'Interview', 'React'] +--- + +## Background +As a second-year student in Melbourne, I applied for frontend internship roles in Shanghai during the Nov-Mar holiday window. Over about one week of dense interviews, I received around 10 offers. + +## Application Snapshot +- Positions contacted: 210 +- Resume exchanges: 51 +- Interview conversion: ~15% +- Offers: ~10 +- Main channel: BOSS Zhipin + +## High-Frequency Interview Topics +### React +- Hooks and effect dependencies +- State management patterns +- Render optimization (`memo`, `useMemo`, `useCallback`) + +### JavaScript +- ES6+ fundamentals +- Async control flow and error handling +- Common hand-written problems (debounce/throttle/dedupe) + +### TypeScript +- core types, `interface` vs `type` +- basic generics and utility types + +### CSS / Layout +- responsive strategies +- Flex and Grid tradeoffs +- practical component-level layout decisions + +## Preparation Strategy +1. Spend 80% effort on React + JS + CSS fundamentals. +2. Spend 20% on TS, networking basics, and build tools. +3. Build small demos and explain tradeoffs clearly in interviews. + +## Resume Advice +- Only list technologies you can explain under pressure. +- Focus on impact and measurable outcomes. +- Keep project bullets concrete and implementation-oriented. + +## Final Takeaway +SMB frontend interviews care most about usable engineering basics. If your fundamentals are solid and your communication is structured, conversion can be surprisingly high. diff --git a/src/content/blog-en/20251216 - normalization/post.mdx b/src/content/blog-en/20251216 - normalization/post.mdx new file mode 100644 index 0000000..2d86843 --- /dev/null +++ b/src/content/blog-en/20251216 - normalization/post.mdx @@ -0,0 +1,30 @@ +--- +title: Why Transformer Needs RMSNorm +description: 'A practical deep dive into why deep networks need normalization and why RMSNorm became the LLM default' +publishDate: 2025-12-16 00:00:00 +locale: en +translationKey: transformer-normalization +tags: ['LLM', 'Transformer', 'MiniMind', 'Deep Learning', 'Normalization'] +--- + +This post is part 1 of my MiniMind learning series. + +## Core Question +Why do Transformer blocks apply normalization so frequently, and why does modern LLM training prefer RMSNorm over LayerNorm? + +## Key Points +- Deep stacks without normalization suffer from unstable activations and vanishing gradients. +- RMSNorm stabilizes scale while preserving direction, which is often enough for robust optimization. +- Compared with LayerNorm, RMSNorm is computationally lighter and widely used in modern LLM architectures. + +## Practical Perspective +In implementation terms, RMSNorm is simple and reliable: +- normalize by root-mean-square +- keep a learnable scale parameter +- avoid unnecessary centering overhead when not needed + +## Why It Matters in Transformer Blocks +Pre-norm design (`Norm -> SubLayer -> Residual`) improves training stability at depth, and RMSNorm works well with this pattern. + +## Summary +RMSNorm is not just a micro-optimization. It is a key ingredient that keeps deep Transformer training stable while reducing compute overhead. diff --git a/src/content/blog-en/20251217 - rope-position-encoding/post.mdx b/src/content/blog-en/20251217 - rope-position-encoding/post.mdx new file mode 100644 index 0000000..c8a57c5 --- /dev/null +++ b/src/content/blog-en/20251217 - rope-position-encoding/post.mdx @@ -0,0 +1,28 @@ +--- +title: RoPE Positional Encoding Explained +description: 'A concise walkthrough of why RoPE works and how it encodes relative position efficiently in modern LLMs' +publishDate: 2025-12-17 00:00:00 +locale: en +translationKey: rope-position-encoding +tags: ['LLM', 'Transformer', 'MiniMind', 'RoPE', 'Position Encoding'] +--- + +This post is part 2 of my MiniMind learning series. + +## Problem Statement +Vanilla attention is permutation-invariant. Without positional signals, token order is not represented correctly. + +## Why RoPE +RoPE injects position through rotation in paired dimensions, allowing attention to carry relative positional structure naturally. + +## Key Intuition +- Each token vector is rotated by a position-dependent angle. +- Different frequency bands encode different positional granularities. +- Relative distance emerges directly in attention score interactions. + +## Engineering Notes +- Floating-point precision and frequency scaling matter for long-context behavior. +- Correct dimension pairing and rotation implementation is essential. + +## Summary +RoPE is elegant because it introduces position with minimal architectural complexity while preserving strong performance and compatibility with standard attention blocks. diff --git a/src/content/blog-en/20251218 - attention-mechanism/post.mdx b/src/content/blog-en/20251218 - attention-mechanism/post.mdx new file mode 100644 index 0000000..1628bc4 --- /dev/null +++ b/src/content/blog-en/20251218 - attention-mechanism/post.mdx @@ -0,0 +1,28 @@ +--- +title: 'Understanding Attention: Q/K/V and Multi-Head' +description: 'A compact explanation of attention mechanics, common confusion points, and implementation-level reasoning' +publishDate: 2025-12-18 00:00:00 +locale: en +translationKey: attention-mechanism +tags: ['LLM', 'Transformer', 'MiniMind', 'Attention', 'Multi-Head'] +--- + +This post is part 3 of my MiniMind learning series. + +## Core Idea +Attention answers one question: when interpreting the current token, which other tokens should matter, and by how much? + +## Q / K / V in One Line +- `Q` asks what I need. +- `K` describes what each token offers. +- `V` carries the actual content to aggregate. + +## Why Multi-Head +Multiple heads let the model attend from different representational subspaces, improving expressiveness without changing the core attention formula. + +## Common Confusions +- Softmax in attention and normalization layers serve different purposes. +- Attention focuses on relationship weighting; normalization stabilizes optimization dynamics. + +## Summary +Once Q/K/V semantics and head-wise projection are clear, attention implementation becomes a straightforward tensor-shape problem rather than a mysterious concept. diff --git a/src/content/blog-en/20251219 - feedforward-transformer-block/post.mdx b/src/content/blog-en/20251219 - feedforward-transformer-block/post.mdx new file mode 100644 index 0000000..3bf05d7 --- /dev/null +++ b/src/content/blog-en/20251219 - feedforward-transformer-block/post.mdx @@ -0,0 +1,32 @@ +--- +title: FeedForward in Transformer Blocks +description: 'How RMSNorm, RoPE, Attention, and FeedForward cooperate inside a full Transformer block' +publishDate: 2025-12-19 00:00:00 +locale: en +translationKey: feedforward-transformer-block +tags: ['LLM', 'Transformer', 'MiniMind', 'FeedForward', 'SwiGLU', 'Architecture'] +--- + +This post is part 4 of my MiniMind learning series. + +## Why FeedForward Matters +Attention is not the whole Transformer. FeedForward layers usually take a major share of parameters and play a central role in token-wise nonlinear transformation. + +## Typical Pattern +- expand hidden dimension +- apply nonlinear gating/activation (e.g., SwiGLU) +- project back to model dimension + +## Division of Labor +- Attention: cross-token information routing. +- FeedForward: per-token feature transformation and capacity expansion. + +## Block Assembly +A modern block typically combines: +1. Pre-norm +2. Attention + residual +3. Pre-norm +4. FeedForward + residual + +## Summary +Understanding FeedForward is essential to understanding why Transformer blocks actually work at scale. diff --git a/src/content/blog/20250701 - firstPR/post.mdx b/src/content/blog/20250701 - firstPR/post.mdx index cccf612..6ab2513 100644 --- a/src/content/blog/20250701 - firstPR/post.mdx +++ b/src/content/blog/20250701 - firstPR/post.mdx @@ -2,6 +2,8 @@ title: 人生中第一个pr description: '一个大二学生第一次成功为开源社区提pr的心得感想' publishDate: 2025-07-01 22:06:36 +locale: zh +translationKey: first-pr tags: ['开源', '前端'] --- import { GithubCard } from 'astro-pure/advanced' diff --git a/src/content/blog/20250712 - astroThemePureWaline/post.mdx b/src/content/blog/20250712 - astroThemePureWaline/post.mdx index 281f247..867f243 100644 --- a/src/content/blog/20250712 - astroThemePureWaline/post.mdx +++ b/src/content/blog/20250712 - astroThemePureWaline/post.mdx @@ -2,6 +2,8 @@ title: astro-theme-pure主题部署 Waline 评论系统全流程指南 description: '个人在为astro-theme-pure主题部署 Waline 评论系统全流程指南以及踩坑' publishDate: 2025-07-12 05:08:21 +locale: zh +translationKey: waline-guide tags: ['Waline', '教程'] --- import { Aside } from 'astro-pure/user' diff --git a/src/content/blog/20251023 - internshipExperience/post.mdx b/src/content/blog/20251023 - internshipExperience/post.mdx index fb11fd6..91bb21a 100644 --- a/src/content/blog/20251023 - internshipExperience/post.mdx +++ b/src/content/blog/20251023 - internshipExperience/post.mdx @@ -2,6 +2,8 @@ title: 国内小厂前端实习面试总结与技术准备指南 description: '系统总结国内小厂前端实习面试的技术考点、投递数据分析、以及完整的技术准备清单' publishDate: 2025-10-23 16:00:00 +locale: zh +translationKey: internship-interview-guide tags: ['实习', '前端', '面试', 'React'] --- diff --git a/src/content/blog/20251216 - normalization/post.mdx b/src/content/blog/20251216 - normalization/post.mdx index 6a9e5e8..c588260 100644 --- a/src/content/blog/20251216 - normalization/post.mdx +++ b/src/content/blog/20251216 - normalization/post.mdx @@ -2,6 +2,8 @@ title: 为什么Transformer需要归一化?从梯度消失到RMSNorm description: '深入探讨为什么深层神经网络需要归一化,以及 RMSNorm 如何成为现代 LLM 的标配' publishDate: 2025-12-16 00:00:00 +locale: zh +translationKey: transformer-normalization tags: ['LLM', 'Transformer', 'MiniMind', 'Deep Learning', 'Normalization'] --- diff --git a/src/content/blog/20251217 - rope-position-encoding/post.mdx b/src/content/blog/20251217 - rope-position-encoding/post.mdx index dfb391e..701dd84 100644 --- a/src/content/blog/20251217 - rope-position-encoding/post.mdx +++ b/src/content/blog/20251217 - rope-position-encoding/post.mdx @@ -2,6 +2,8 @@ title: RoPE位置编码:从排列不变性到多频率机制 description: '深入解析 RoPE(Rotary Position Embedding)—— 现代大语言模型位置编码的标配方案,从数学原理到工程实现,特别是浮点数精度问题的深入分析' publishDate: 2025-12-17 00:00:00 +locale: zh +translationKey: rope-position-encoding tags: ['LLM', 'Transformer', 'MiniMind', 'RoPE', 'Position Encoding'] --- diff --git a/src/content/blog/20251218 - attention-mechanism/post.mdx b/src/content/blog/20251218 - attention-mechanism/post.mdx index ccecc54..b62ac8b 100644 --- a/src/content/blog/20251218 - attention-mechanism/post.mdx +++ b/src/content/blog/20251218 - attention-mechanism/post.mdx @@ -2,6 +2,8 @@ title: 深入理解Attention机制:从Q、K、V到Multi-Head description: '深入解析 Attention(注意力机制)—— Transformer 的核心引擎。用数据库查询的类比,彻底理解 Q、K、V 的含义,掌握 Multi-Head Attention 的实现,并澄清 Softmax 与 RMSNorm 的常见混淆' publishDate: 2025-12-18 00:00:00 +locale: zh +translationKey: attention-mechanism tags: ['LLM', 'Transformer', 'MiniMind', 'Attention', 'Multi-Head'] --- diff --git a/src/content/blog/20251219 - feedforward-transformer-block/post.mdx b/src/content/blog/20251219 - feedforward-transformer-block/post.mdx index 5f8c504..559b3b9 100644 --- a/src/content/blog/20251219 - feedforward-transformer-block/post.mdx +++ b/src/content/blog/20251219 - feedforward-transformer-block/post.mdx @@ -2,6 +2,8 @@ title: FeedForward与Transformer Block:Attention之外的另一半 description: '深入解析 FeedForward 前馈网络,以及如何将 RMSNorm、RoPE、Attention、FeedForward 四大组件组装成完整的 Transformer Block。读完本文,你将彻底掌握 Transformer 的完整架构' publishDate: 2025-12-19 00:00:00 +locale: zh +translationKey: feedforward-transformer-block tags: ['LLM', 'Transformer', 'MiniMind', 'FeedForward', 'SwiGLU', 'Architecture'] --- diff --git a/src/content/papers-en/20260211 - attention-is-all-you-need/post.mdx b/src/content/papers-en/20260211 - attention-is-all-you-need/post.mdx new file mode 100644 index 0000000..cd66bb3 --- /dev/null +++ b/src/content/papers-en/20260211 - attention-is-all-you-need/post.mdx @@ -0,0 +1,41 @@ +--- +title: 'Reading Notes: Attention Is All You Need' +description: 'Focused notes on Transformer motivation, core architecture, and practical implementation insights.' +publishDate: 2026-02-11 00:00:00 +locale: en +translationKey: attention-is-all-you-need +paperLink: https://arxiv.org/abs/1706.03762 +pdfLink: https://arxiv.org/pdf/1706.03762 +authors: + - Ashish Vaswani + - Noam Shazeer + - Niki Parmar + - Jakob Uszkoreit + - Llion Jones + - Aidan N. Gomez + - Lukasz Kaiser + - Illia Polosukhin +venue: NeurIPS +year: 2017 +tags: ['Transformer', 'Attention', 'NLP', 'Foundation'] +status: completed +language: en +featured: true +comment: true +--- + +## Paper Info +- Original link: [Attention Is All You Need](https://arxiv.org/abs/1706.03762) +- Main topic: sequence modeling without recurrence/convolution +- One-line takeaway: Global self-attention enables better parallelism and long-range dependency modeling. + +## Core Contributions +1. Full Encoder-Decoder architecture built around multi-head self-attention. +2. Scaled dot-product attention (`/ sqrt(d_k)`) for stable optimization. +3. Positional encoding to inject token order without recurrence. +4. Better translation quality with lower training cost than strong RNN baselines. + +## Practical Notes +- Shape handling across heads is a frequent implementation pitfall. +- Mask order (before softmax) is critical for correctness. +- This paper remains a strong reference for understanding modern LLM blocks. diff --git a/src/content/papers-en/20260211 - back-to-basics-let-denoising-models-denoise/post.mdx b/src/content/papers-en/20260211 - back-to-basics-let-denoising-models-denoise/post.mdx new file mode 100644 index 0000000..8280229 --- /dev/null +++ b/src/content/papers-en/20260211 - back-to-basics-let-denoising-models-denoise/post.mdx @@ -0,0 +1,39 @@ +--- +title: 'Reading Notes: Back to Basics - Let Denoising Generative Models Denoise' +description: 'Structured notes on objective design, method framing, and evaluation focus for this denoising generative model paper.' +publishDate: 2026-02-11 00:00:00 +locale: en +translationKey: back-to-basics-denoising +paperLink: https://arxiv.org/abs/2511.13720 +pdfLink: https://arxiv.org/pdf/2511.13720 +authors: + - Kaiming He + - et al. +venue: arXiv +year: 2025 +tags: ['Generative Model', 'Diffusion', 'Denoising'] +status: reading +language: en +featured: true +comment: true +--- + +## Paper Info +- Original link: [Back to Basics: Let Denoising Generative Models Denoise](https://arxiv.org/abs/2511.13720) +- Main topic: revisiting training and sampling assumptions in denoising generative models +- One-line takeaway: align objective design more directly with the denoising task itself. + +## Core Contributions +1. Re-examines objective mismatch in common denoising training setups. +2. Proposes a cleaner objective perspective that better reflects denoise semantics. +3. Shows quality/stability improvements without relying on complex stacked tricks. + +## My Reading Focus +- how objective design changes across noise levels +- train/infer consistency of denoise behavior +- speed-quality tradeoff under practical sampling budgets + +## Open Questions +1. How robust is the gain across more diverse datasets? +2. Does the benefit scale with model size? +3. Can the idea combine well with consistency or flow-matching style training? diff --git a/src/content/papers/20260211 - attention-is-all-you-need/post.mdx b/src/content/papers/20260211 - attention-is-all-you-need/post.mdx index 004e42e..e580197 100644 --- a/src/content/papers/20260211 - attention-is-all-you-need/post.mdx +++ b/src/content/papers/20260211 - attention-is-all-you-need/post.mdx @@ -2,6 +2,8 @@ title: Attention Is All You Need 精读 description: Transformer 论文精读,聚焦 self-attention 设计动机、模型结构、训练细节与影响,并补充我在实现和阅读中的关键笔记。 publishDate: 2026-02-11 00:00:00 +locale: zh +translationKey: attention-is-all-you-need paperLink: https://arxiv.org/abs/1706.03762 pdfLink: https://arxiv.org/pdf/1706.03762 authors: diff --git a/src/content/papers/20260211 - back-to-basics-let-denoising-models-denoise/post.mdx b/src/content/papers/20260211 - back-to-basics-let-denoising-models-denoise/post.mdx index e5d2e70..25f2843 100644 --- a/src/content/papers/20260211 - back-to-basics-let-denoising-models-denoise/post.mdx +++ b/src/content/papers/20260211 - back-to-basics-let-denoising-models-denoise/post.mdx @@ -2,6 +2,8 @@ title: 'Back to Basics: Let Denoising Generative Models Denoise 精读' description: 围绕 Kaiming He 团队这篇 denoising 生成模型论文的结构化阅读笔记,记录核心动机、方法、实验观察和后续待验证的问题。 publishDate: 2026-02-11 00:00:00 +locale: zh +translationKey: back-to-basics-denoising paperLink: https://arxiv.org/abs/2511.13720 pdfLink: https://arxiv.org/pdf/2511.13720 authors: diff --git a/src/i18n/locales.ts b/src/i18n/locales.ts new file mode 100644 index 0000000..ec3eda3 --- /dev/null +++ b/src/i18n/locales.ts @@ -0,0 +1,18 @@ +export const SUPPORTED_LOCALES = ['zh', 'en'] as const + +export type Locale = (typeof SUPPORTED_LOCALES)[number] + +export const DEFAULT_LOCALE: Locale = 'zh' + +export const LOCALE_META: Record = { + zh: { + htmlLang: 'zh-CN', + ogLocale: 'zh_CN', + label: '中文' + }, + en: { + htmlLang: 'en', + ogLocale: 'en_US', + label: 'English' + } +} diff --git a/src/i18n/messages.ts b/src/i18n/messages.ts new file mode 100644 index 0000000..fdd2eb8 --- /dev/null +++ b/src/i18n/messages.ts @@ -0,0 +1,12 @@ +import type { Locale } from './locales' + +export const messages = { + zh: { + switchLanguage: 'English', + currentLanguage: '当前:中文' + }, + en: { + switchLanguage: '中文', + currentLanguage: 'Current: English' + } +} as const satisfies Record> diff --git a/src/i18n/routing.ts b/src/i18n/routing.ts new file mode 100644 index 0000000..b6ff708 --- /dev/null +++ b/src/i18n/routing.ts @@ -0,0 +1,87 @@ +import { DEFAULT_LOCALE, type Locale } from './locales' + +export function isEnglishPath(pathname: string) { + return pathname === '/en' || pathname.startsWith('/en/') +} + +export function getLocaleFromPath(pathname: string): Locale { + return isEnglishPath(pathname) ? 'en' : DEFAULT_LOCALE +} + +export function stripEnglishPrefix(pathname: string) { + if (!isEnglishPath(pathname)) return pathname + const stripped = pathname.replace(/^\/en/, '') + return stripped.length === 0 ? '/' : stripped +} + +export function toEnglishPath(pathname: string) { + if (isEnglishPath(pathname)) return pathname + return pathname === '/' ? '/en' : `/en${pathname}` +} + +export function toChinesePath(pathname: string) { + return stripEnglishPrefix(pathname) +} + +export function toLocalePath(pathname: string, locale: Locale) { + return locale === 'en' ? toEnglishPath(pathname) : toChinesePath(pathname) +} + +export function getAlternatePath(pathname: string, locale: Locale) { + return locale === 'en' ? toChinesePath(pathname) : toEnglishPath(pathname) +} + +export function getPreferredLocaleFromHeader(acceptLanguage: string | null): Locale { + if (!acceptLanguage) return DEFAULT_LOCALE + const normalized = acceptLanguage.toLowerCase() + return normalized.includes('en') ? 'en' : DEFAULT_LOCALE +} + +export function shouldBypassLocaleRedirect(pathname: string) { + if ( + pathname.startsWith('/_astro') || + pathname.startsWith('/api') || + pathname.startsWith('/favicon') || + pathname.startsWith('/fonts') || + pathname.startsWith('/images') || + pathname.startsWith('/scripts') || + pathname.startsWith('/styles') || + pathname.startsWith('/icons') + ) { + return true + } + + // Static files + if (pathname.includes('.')) return true + + const checkPath = stripEnglishPrefix(pathname) + return !( + checkPath === '/' || + checkPath.startsWith('/about') || + checkPath.startsWith('/archives') || + checkPath.startsWith('/blog') || + checkPath.startsWith('/links') || + checkPath.startsWith('/papers') || + checkPath.startsWith('/projects') || + checkPath.startsWith('/search') || + checkPath.startsWith('/tags') || + checkPath.startsWith('/terms') + ) +} + +export function isCrawlerUserAgent(userAgent: string | null) { + if (!userAgent) return false + const ua = userAgent.toLowerCase() + return ( + ua.includes('googlebot') || + ua.includes('bingbot') || + ua.includes('duckduckbot') || + ua.includes('baiduspider') || + ua.includes('yandexbot') || + ua.includes('sogou') || + ua.includes('gptbot') || + ua.includes('claudebot') || + ua.includes('facebookexternalhit') || + ua.includes('slurp') + ) +} diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 2a06937..9d83f5b 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -3,6 +3,9 @@ import { Footer, Header, ThemeProvider } from 'astro-pure/components/basic' import type { SiteMeta } from 'astro-pure/types' import Analytics from '@vercel/analytics/astro' import BaseHead from '@/components/BaseHead.astro' +import { LOCALE_META, type Locale } from '@/i18n/locales' +import { messages } from '@/i18n/messages' +import { getAlternatePath } from '@/i18n/routing' import config from '@/site-config' // Import the global.css file here so that it is included on @@ -12,18 +15,27 @@ import '@/assets/styles/app.css' interface Props { meta: SiteMeta highlightColor?: string + locale?: Locale + alternatePath?: string } const { meta: { articleDate, description = config.description, ogImage, title }, highlightColor, + locale = 'zh', + alternatePath, ...props } = Astro.props + +const htmlLang = LOCALE_META[locale].htmlLang +const languageSwitchPath = alternatePath ?? getAlternatePath(Astro.url.pathname, locale) +const languageSwitchLabel = messages[locale].switchLanguage +const languageLabel = messages[locale].currentLanguage --- - + - + @@ -38,12 +50,49 @@ const { ) } + + {/* Set highlight color */}