Nhật ký công việc cho nhiệm vụ "Xem xét lại cấu trúc trang web, cải tiến nó và xây dựng lại nội dung"

16 июл. 2026 г., 02:24:51

Đã thêm một tính năng AI rất hay :-) - chỉnh sửa nội dung kèm theo liên kết chéo nội bộ. Điểm chính là truyền toàn bộ tập hợp các liên kết nội bộ cho tác nhân (agent) và nó sẽ tự động thay thế văn bản thuần túy thành các liên kết trong nội dung. Nhưng như thường lệ, AI đôi khi hoạt động chưa hoàn toàn chính xác và tự bịa ra các liên kết không tồn tại. Tuy nhiên, điều này có thể khắc phục được - tôi chỉ cần thêm bước xử lý hậu kỳ (post-processing) cho nội dung và nó sẽ làm sạch nội dung khỏi các liên kết nội bộ bị hỏng (may mắn là toàn bộ nội dung ở định dạng Markdown nên việc này dễ hơn rất nhiều so với HTML thuần).

import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remarkMdx from 'remark-mdx'
import remarkStringify from 'remark-stringify'
import { visit } from 'unist-util-visit'
import type { Link, Text } from 'mdast'
import type { Parent } from 'unist'

export interface ConceptLink {
  uri: string
}

export interface InvalidLink {
  url: string
  position?: {
    start: { line: number; column: number }
    end: { line: number; column: number }
  }
}

export interface ValidateInternalLinksResult {
  invalidLinks: InvalidLink[]
}

function isInternalLink(url: string): boolean {
  return url.startsWith('/')
}

export function buildValidUrisSet(concepts: ConceptLink[]): Set<string> {
  return new Set(concepts.map((c) => c.uri))
}

export async function removeInvalidLinks(
  content: string,
  validUris: Set<string>,
): Promise<string> {
  const tree = unified().use(remarkParse).use(remarkMdx).parse(content)

  visit(tree, 'link', (node: Link, index, parent: Parent | undefined) => {
    if (!parent || index === undefined) {
      return
    }

    const url = node.url

    if (isInternalLink(url) && !validUris.has(url)) {
      if (process.env.NODE_ENV === 'development') {
        console.error('Invalid url', url)
      }

      const textNode: Text = {
        type: 'text',
        value: node.children
          .filter((child): child is Text => child.type === 'text')
          .map((child) => child.value)
          .join(''),
      }

      parent.children.splice(index, 1, textNode)
    }
  })

  const result = unified()
    .use(remarkStringify, {
      bullet: '-',
      emphasis: '_',
      strong: '*',
    })
    .stringify(tree)

  return result
}

Dưới đây là một ví dụ về bài viết đã được xử lý: https://vietnamguru.ru/content/reference/aktualniy-spisok-provintsiy-vetnama

Ban đầu bài viết được viết mà không có lấy một liên kết nội bộ nào. Trong khi lẽ ra phải có rất nhiều liên kết ở đó, vì đây là danh sách các tỉnh (và đôi khi là cả các thành phố). Tự tay chỉnh sửa nó khá là phiền phức (bạn không chỉ phải tìm các liên kết trên trang web của mình mà còn phải kiểm tra xem tỉnh đó có thực sự tồn tại trong danh mục của chúng tôi hay không). Nhân tiện, đây cũng là một điểm cộng phụ - chúng ta có ngay danh sách các tỉnh còn thiếu, nhờ đó biết rõ những gì cần bổ sung vào danh mục. Và kết quả là chúng ta thu được nội dung như thế này:

13.07.2026