1 Introduction
Recently, I have been thinking about what new features can be added to the blog structure, such as the content structure prompt newly added below the article page (see article:From Content to Structure: A Low-Cost Approach to Blog Context Evolution)。
However, there are still many further capabilities, such as automatically recommending content-related articles, aggregating content by topic, and even letting the blog gradually form a “knowledge network” style structure, which cannot be achieved solely by relying on simple “tags”, “categories”, or even the “structure prompts” mentioned earlier.
Because these solutions essentially share a common problem: they rely onartificially defined structures, rather than the relationships formed between content based on the text itself—tags can be labeled, but the granularity is coarse; categories can be divided, but the dimensions are limited; even the “structure prompts” I am currently trying are essentially still a kind of “mapping after human abstraction.”
This is not to say that tags or categories have no value. On the contrary, they themselves are an already existing “structural signal” and are still very effective in many scenarios. But the problem is: as the blog scale gradually expands, if the relationships between contentrely entirely on these artificial structures to be maintained, a very realistic problem will gradually be exposed—they cannot evolve automatically。
To give a very concrete example: when I write a new article, it may be associated with several past pieces of content in some aspects, but if I do not deliberately apply the same tags or incorporate it into an existing structure, then this article is actually “isolated” in the overall structure of the blog.
In other words, although the blog already “has content” now, it still lacks an ability to automatically organize content relationships.
What I really want is actually another state: when an article is written, it is not just displayed, but can also be organized by the blog “itself” into the overall structure—knowing which content it is close to, which topic direction it belongs to, and roughly where it stands in the entire content system.
Once this capability is in place, many features that originally required manual maintenance will naturally emerge, such as automatically recommending content-related articles, aggregating based on content rather than tags, and even further expanding into knowledge graphs, AI Q&A, and other capabilities in the future.
In many technical contexts, once “content understanding” or “semantic relationships” are mentioned, people often directly associate them with vector representation (embedding)—a more expressive and versatile way of semantic modeling.
But such solutions usually mean introducing additional models, computing processes, and new data storage methods. For large-scale systems, these costs are reasonable, but for a personal blog with content at its core and a relatively limited scale, this is not necessarily the most appropriate starting point.
Looking at it from another angle, if it is just to answer a more specific question—“which articles are closer to each other”—then whether a complete vector semantic representation is absolutely necessary is actually open to debate.
In this article, I did not directly introduce embedding, but chose a more engineered and lightweight approach: by compressing the representation of content and building association relationships between articles on this basis.
It needs to be emphasized that this approach does not completely abandon the existing tag system, but ratherintroduces representation based on the content itself in addition to tags, so that the establishment of relationships no longer relies entirely on artificial structures。
From this perspective, this set of methods is more like adding another layer of “lightweight knowledge index” based on content relationships outside the existing structure of the blog: it does not pursue complete semantic understanding capabilities, but rather, at a lower cost, allows content to form an association structure that can be calculated, organized, and referenced.
In other words, we are not pursuing the “strongest semantic expression capability” here, but are trying to build a set ofcontent association schemes that are more balanced among cost, complexity, and effectiveness: tags can still exist as a structural signal, but they are no longer the sole basis, and the content itself also begins to participate in relationship calculations.
Then the question becomes very clear: how to build a structured index for the blog that can describe content relationships? And this is precisely a direction I have been working on lately—adding a layer ofLightweight Knowledge Index。
What needs to be done next can actually be summarized in one sentence:
Transform the article content, which was originally only human-friendly, into a structured representation that is also machine-friendly.
But the question is—how should this “structured representation” actually be designed? Should we continue to enhance the existing tag and category systems? Or introduce a brand new data structure? Or simply leverage off-the-shelf search or vectorization solutions?
These all seem like feasible paths, but if viewed from the perspectives of “maintainability” and “actual implementation cost”, the differences between them are actually very large.
2 From “Feasible Path” to “Implementable Solution”
If we want to introduce a layer of “structured representation” for the blog, what are the realistically feasible paths?
The most intuitive way is actually to continue enhancing the existing tag and category systems: for example, refining tags, adding dimensions, or even manually unifying some naming rules to make the “associations” between content more obvious.
But I quickly found that this path essentially just pushes the problem one step back—it still relies on manual maintenance, and this “association” is discrete and coarse-grained: either it exists or it doesn't, making it hard to express subtle differences like “somewhat related” or “highly related”. Once the number of articles increases, the maintenance cost and inconsistency of this approach will quickly amplify.
What if we do not continue to rely on tags, but instead introduce a more complete content structure? For example, establishing clearer hierarchical relationships for articles, or manually maintaining “related articles” and “series articles”, or even, as I tried before, adding structure prompts in articles to make the content present a clearer context as a whole.
This approach is effective locally—especially at the moment of writing, it indeed helps clarify thoughts. But the problem is that it still highly relies on human design: which content is related, how they are associated, and at which level they are placed are essentially still judgments made by the author. Once the scale expands, or old articles need to be retroactively adjusted, this structure will gradually evolve into an ongoing burden. In other words, this path merely builds “structural capability” on top of continuous human investment, rather than enabling the system itself to possess this capability.
Taking it a step further, we could actually change our thinking entirely—no longer trying to define the structure ourselves, but directly leveraging off-the-shelf search or vectorization capabilities to let machines “understand” the relationships between content. For example, by vectorizing article content, mapping text into a semantic space, and then judging the similarity between content based on distance. In terms of capability, this type of solution is almost perfect: whether it is full-text retrieval or vector-based semantic similarity calculation, it can solve the “content association” problem very well, and even bring a more natural search experience.
But the problem is equally obvious: this means introducing additional services, storage, and computing processes, and even requires a certain degree of modification to the existing blog architecture. For a blog that is content-oriented and has a relatively simple structure, such a solution, though powerful, is somewhat “overweight”.
Arriving at this point, one actually discovers a very realistic contradiction: on one hand, lightweight solutions (tags, manual structures) struggle to express true semantic relationships; on the other hand, powerful solutions (search, vectorization) introduce excessive complexity. What I actually need is a solution that falls right between the two—one that does not rely on heavy manual maintenance and can evolve naturally with the content; does not require introducing complex backend systems and can be directly implemented on the existing blog structure; while also being able to express “relationships between content” to some extent, providing a foundation for subsequent features.
Looking at it from another perspective, this problem can actually be reformulated as: is there a way to add a layer of “machine-understandable” representation to the content without changing the overall architecture of the blog? If the answer is yes, then this representation layer itself should be lightweight, independent, and capable of being generated and consumed offline.
Under this line of thought, the question has actually shifted from “which solution to choose” to another, more specific question:If we treat “semantic representation” as an independent data artifact, in what form should it exist? In other words, we are no longer concerned with “which system to use for implementation,” but instead need to first determine:Whether there exists a data representation method that is simple and universal enough, while also being directly consumable by the frontend.
3 Choice of Form for Structured Representation
If we treat “semantic representation” as an independent data artifact, then the question becomes very specific:In what form should this data exist? Intuitively, this seems to be just a matter of “format choice,” but when combined with the constraints mentioned in Chapter 2, it is actually already confined to a relatively narrow range.
First, this data needs to be directly consumable by the frontend. This means its representation cannot rely on complex parsing processes, nor should it be bound to a specific runtime environment. Ideally, when the browser needs to use this data, it can fetch it just like loading any ordinary resource and have it directly participate in the page logic—for example, to generate recommended content, enhance structural hints, or serve as a data source for search. It is worth noting that “direct use” here does not mean the frontend must load the entire dataset all at once, but rather that the data structure itself should be naturally friendly to the frontend, allowing it to be loaded and used in an appropriate manner depending on the actual scenario.
Secondly, this data should be generated during the build phase rather than dynamically calculated when a user visits. This might seem like just an implementation detail, but it actually has a huge impact. If we choose to calculate it at request time, performance, caching, and overall architectural complexity will all rise rapidly; whereas once changed to offline generation, this data becomes more like a “build artifact” that can be deployed, cached, and distributed along with the pages.
Going a step further, this data needs to have a certain degree of independence. It should not be attached to the existing database structure, nor should it be hidden behind some backend API; instead, it should exist as an “explicit presence”—something that can be accessed, debugged, replaced individually, or even migrated between different environments. This point is actually crucial for subsequent evolution.
Looking at these conditions together, they actually imply a fairly clear form: it should be an independently existing data file that can be directly loaded by the browser and is generated during the build phase.
Up to this point, we have not discussed any specific technology choices, but the “space of options” has actually been compressed to a very small size. Because once it is defined as a “file,” it implies the need for a structured representation; and once it needs to be directly used by the frontend, this representation must be naturally supported by the browser; if we also want to balance readability and ease of debugging, the format itself cannot be too obscure.
Under these constraints, some options can be naturally ruled out: for example, custom serialization formats, though flexible, lack universality; some more compact encoding methods, while advantageous in size, introduce additional parsing costs; and some solutions that rely on specific runtime environments struggle to meet the premise of “direct frontend consumption.”
In other words, once these limitations are layered one after another, the question is no longer “choosing one from many solutions,” but rather more like:Only a few representation methods remain that do not feel awkward.
Following this line of thought, a very natural candidate emerges—JSON. Its advantage does not lie in any single outstanding capability, but in its high compatibility with these constraints: it can be directly parsed and used by the browser, is inherently designed as an expression for structured data, can naturally carry nested relationships, and is almost the “default language” in the current front-end ecosystem, with highly mature toolchains and usage habits.
Of course, this is not to say there are no other options. One could also use formats that similarly possess structural expression capabilities (such as XML, YAML, CSV, or even binary structures), but these either lack direct support on the browser side, requiring an extra parsing process; or they are somewhat distant from the current front-end ecosystem in terms of readability or usage habits; and while some solutions offer advantages in performance or size, they seem somewhat overkill for the current scenario where “maintainability” and “simplicity of implementation” are prioritized.
Under these trade-offs, JSON is not the only possibility, but it is the choice that requires almost no extra explanation and can be directly accepted—it has no obvious shortcomings and rarely introduces extra complexity. In other words, the key here is not that “I chose JSON,” but rather: when “semantic representation” is defined as an offline-generated data file that can be directly consumed by the front end, JSON is almost a natural landing point.
And once this is determined, the focus of在这份 JSON 中,我们应该如何表达一篇文章的语义信息?
也就是说,从这一刻开始,问题已经从“形式选择”,转变为了“数据建模”。而这,才是整个语义表示层设计中,真正需要花力气的部分
4 Structural Design of Semantic Representation
在确定使用 JSON 作为“语义表示”的载体之后,问题很快变得具体起来:这份 JSON,到底应该包含哪些信息?
从最直观的角度来看,最容易想到的往往是一些基础字段,比如标题、链接、标签之类。但如果只是这些内容,其实并不需要额外引入一层结构化表示,因为这些信息在现有的博客系统中本身就已经存在。
这也意味着,这一层 JSON 的意义,并不在于重复已有数据,而在于把那些原本存在于内容之中、但系统无法直接利用的信息抽取出来——也就是所谓的“语义”。
如果从最基础的形态去看,一篇文章首先需要能够被唯一识别,并且可以被访问,因此最初的结构往往会非常简单,只包含标题和链接:
{
"title": "...",
"url": "..."
}
但这种结构仍然停留在“描述层面”,它只是告诉系统这是什么,而没有提供任何“理解”的能力。
如果希望往前走一步,通常会先引入的是摘要。因为正文本身过长,不适合直接用于处理,而摘要可以在保留核心信息的同时大幅压缩表达:
{
"title": "...",
"url": "...",
"summary": "..."
}
这里的 summary 并不是正文的替代,而是一个更适合计算与比较的语义入口,它为后续处理提供了一个统一且可控的输入。
在此基础上,如果希望进一步抽象文章的主题,就会自然引入关键词(keywords)。关键词本质上是对内容的一种离散化表达,它比摘要更抽象,但也更容易用于分类与筛选:
{
"title": "...",
"url": "...",
"summary": "...",
"keywords": ["...", "..."]
}
到这里为止,这份结构已经能够比较完整地描述一篇文章本身。但需要注意的是,这一切仍然围绕“单篇文章”展开,它回答的是“这篇文章是什么”,而不是“它与其他内容之间是什么关系”。
一旦开始考虑“文章之间的关系”,一个更基础的问题就不可避免地出现了:在结构化数据中,应该如何稳定地指向一篇文章?
The most direct way is to use URLs, but a URL is essentially an access path that binds “identity” and “location” together; once the path changes, the entire relationship system is affected. Another way is to use internal system IDs, such as primary keys in a database, but although this approach is stable, it relies on specific implementations and lacks semantic readability.
In this case, introducing an independent identifier field id becomes reasonable. It does not depend on the access path, nor does it depend on the database structure, but simply exists as a stable unit of reference:
{
"id": "...",
"title": "...",
"url": "...",
"summary": "...",
"keywords": ["...", "..."]
}
"id": "...", id “title”: "...",
“url”: "...",
{
"id": "current-article",
"title": "...",
"url": "...",
"summary": "...",
"keywords": ["...", "..."],
"related": [
{ "id": "article-1", "score": 0.91 },
{ "id": "article-2", "score": 0.84 },
{ "id": "article-3", "score": 0.76 }
]
}
这里的 "keywords": ["...", "..."] } When this appears, the nature of the structure begins to change. An article is no longer just an object being described, but a node that can be referenced—and it is precisely from this moment that "relationships" truly have the possibility of being expressed.
Once this structure emerges, the perspective actually undergoes a leap: articles are no longer isolated content units, but nodes in a network, and "keywords": ["...", "..."] defines the connections between these nodes.
Viewed as a whole, this structure implies a network of relationships between content. However, this network is not dynamically calculated at runtime; rather, it is already determined during the build phase. In practice, each article only needs to read the portion of connections relevant to itself, without having to recalculate the entire relationship structure.
In other words, instead of “calculating associations” at access time, it “solidifies associations” during the generation phase.
As for how the weights of these connections are obtained, that is not a problem this layer of the structure needs to solve. For this layer, what matters most is not “how the scores are calculated,” but that this representation itself already provides a foundation that can be directly used for ranking and recommendation.
From a more holistic perspective, the fields in this layer can be naturally divided into two categories: one comes from the blog system itself, representing existing structured data such as titles and links; the other comes from further extraction or calculation of the content, such as summaries, keywords, and the relationships between articles. The former provides the basic informational skeleton, while the latter supplements semantic capabilities, together forming the complete state of this semantic representation layer.
5 Generation Process of Semantic Relationships
Once this network of relationships is established, the next question becomes inevitable: how are these relationships constructed?
If we go back to the initial input, there are essentially only two things: the structured information of the articles, and the content of the articles themselves. The former is already structured and can be used directly, while the latter is the true source of the entire semantic layer. This also means that the JSON in Chapter 4 was not “directly generated,” but rather underwent a process of transformation from content to structure.
From the perspective of data sources, this process is not complicated. Fields like titles and links can be obtained directly from the blog system; the only part that truly needs to be processed is the body content of the articles. And that is precisely where the problem begins. The body text is naturally designed for human reading; its information is continuous and unstructured. If used directly for computation, the results—both in terms of efficiency and effectiveness—would be far from satisfactory.
Therefore, before building relationships, the first step is to transform this content into a representation more suitable for processing. The most direct way is to compress the body text and extract a summary that represents the core content. This process does not aim for complete reproduction, but rather to preserve “semantic density” as much as possible, making the text shorter and more focused to provide a stable input for subsequent processing. Building on the summary, keywords can be further abstracted. Compared to the continuous expression of a summary, keywords are a discrete semantic representation that breaks down content into several taggable thematic units, making them better suited for filtering and preliminary judgment.
Once these two representations are in place, the calculation of relationships truly has a foundation. In the most intuitive sense, whether two articles are related can be judged by the overlap of their keywords: the more shared keywords, the closer the topics usually are. This approach is simple to implement and highly explainable, but its limitations are equally obvious—keywords are discrete; they can indicate “whether they are related,” but struggle to express the “degree of relevance.”
Therefore, to make the relationships more nuanced, a more continuous form of representation must be introduced. A common practice is to calculate similarity directly based on the text—for example, by converting the text into comparable numerical representations using term frequencies or weights. Compared to keywords, this approach is more stable and better at reflecting differences in “similarity.”
Going a step further, the text can be mapped into a unified semantic space. In this space, the distance between texts can itself represent their degree of association. Compared to previous methods, this approach no longer relies on whether specific words match, but focuses more on the closeness of the overall semantics. But regardless of the specific method used, they are essentially doing the same thing:Transforming the question of “whether content is related”—which originally relied on human judgment—into a process that can be computed.
Once this process is complete, each article obtains a set of “other articles closest to itself” along with their corresponding association strengths. These results are precisely the source of the "keywords": ["...", "..."] fields in Chapter 4—those weighted citation relationships are not manually defined, but are obtained through computation.
It is worth noting that this process typically occurs during the offline phase. In other words, it is not executed in real-time when a user visits the page, but is completed all at once during the build phase. When new articles are added or old content changes, a new set of results is regenerated.
A direct result of this approach is that the runtime system can be greatly simplified: the frontend does not need to participate in any computation, but only needs to read the prepared data to complete operations such as sorting and recommendation. Looking back from this perspective, the JSON in Chapter 4 is not actually an “intermediate structure,” but the final product of the entire process. It both carries the semantic information of individual articles and solidifies the relationships between them.
Precisely because of this, the “semantic representation layer” here is not essentially about introducing a complex online system, but rather adding an offline processing step: it extracts information originally scattered throughout the content, converts it into structured data, and completes all necessary computations during the build phase. From this perspective, this process is actually introducing a layer of “offline computing capability” to the blog.
Once this process is complete, the form of the blog itself undergoes a slight change: it is no longer just a collection of content organized by time or category, but gains an additional layer of structure based on semantic relationships. And this layer of structure is precisely the foundation upon which various subsequent capabilities are realized.
However, it should be noted that what is described here is still only the “computation results themselves,” rather than how this process actually runs in the system. In other words, how the above semantic information is constructed step-by-step and organized into a complete processing pipeline is itself the problem that needs to be solved next.
6 Construction Process of the Semantic Index
1 Overall Process Overview
In the previous chapters, we determined the final form of the semantic representation: an offline index file based on JSON. However, between design and implementation, a clear execution process is still needed to actually build it. In my implementation, this process is converged into an independently running script, whose role is very straightforward: to retrieve article data from WordPress, process it, and generate the final JSON semantic index file.
Overall, this process can be abstracted into four consecutive phases:
- Step one: retrieve article data from WordPress;
- Step two: process and semantically transform the retrieved article data;
- Step three: build relationships between articles based on semantic information;
- Step four: output the final results into a unified JSON structure.
These phases seem very linear, but the key point lies in:Each step does not rely on WordPress's own runtime mechanism, but instead completely takes over and reconstructs the data within the script itselfIn other words, WordPress here merely plays the role of a “data source” and no longer participates in any logical computation.
The entire process does not rely on the blog's runtime environment, but completes a one-time computation in an offline state. Therefore, it is more like an independent data processing pipeline rather than a part of the system's operation. In this pipeline, different phases assume different responsibilities and jointly complete the conversion from “content” to “structured semantics.”
If we break it down further from an engineering perspective, we can see that the essence of this pipeline is actually doing one thing:Reorganizing the content data scattered across the CMS into a data structure oriented toward “relationship computation”Fields originally used for display (title, body, tags) are recombined here into inputs that can participate in computation; whereas fields that did not originally exist (abstracts, keywords, relationships) are gradually “generated” during this process.
Precisely because of this, the script itself is not a simple data-moving tool, but rather more like a “builder”: it is responsible for converting the relatively loose content structure in WordPress into a data product with a stable structure and clear semantic boundaries.
In terms of execution, this build process is typically a batch task completed all at once. When articles are added or updated, you only need to rerun the script to regenerate a complete index file. Therefore, in terms of its runtime model, it is closer to the “build phase” than the “service phase,” which also determines that the complexity of the entire system can be kept at a very low level.
2 Fetching Article Content from WordPress
In the entire process, the first step is to retrieve the complete post data from WordPress. This step seems simple, but it actually determines the input boundaries for all subsequent processing, so prioritizing the establishment of a stable and controllable data retrieval method is necessary.
Among the available options, the most intuitive choice is actually RSS, but it is not suitable for this layer of implementation here. The reason is simple: RSS is designed for content distribution, not data processing. It usually only contains summary information, and the fields are relatively fixed, making it difficult to obtain the full text, let alone flexibly control the returned data structure.
In contrast, the REST API provided by WordPress is closer to the positioning of a “data interface.” Through it, one can directly obtain the complete information of articles, including fields such as titles, links, content, and tags, and it supports capabilities like pagination and filtering, making it more suitable as an input source for offline processing workflows.
In the actual implementation, the interface used is:
/wp-json/wp/v2/posts
By default, this interface returns a list of articles, with each record containing the main fields of an article. The more critical ones include:
id: The unique identifier of the article in the systemtitle.rendered: Article titlelink: The article access URLcontent.rendered: The article content (HTML format)tags: List of tag IDs
It should be noted that this interface returns paginated results by default. That is to say, a single request cannot retrieve all articles; instead, you need to traverse them step-by-step using pagination parameters.
In the request, you can use the per_page parameter to control the number of items per page (maximum 100), and use the page parameter to specify the page number. Therefore, a complete data retrieval process typically manifests as a pagination loop: starting from the first page, requesting subsequent pages in sequence until all articles have been retrieved.
In this process, there are two details to note: first, how to determine “whether all data has been retrieved.” A straightforward way is to terminate the loop based on whether the returned result is empty; a more robust approach is to use the X-WP-TotalPages field in the response headers to obtain the total number of pages in advance, thereby clarifying the traversal range; second, the retrieved body content is usually in HTML format, which requires extra attention in subsequent processing. At the current stage, it can be kept as raw data first and then cleaned and extracted in subsequent steps.
In this way, the script can retrieve all article data from the blog at once and use it as input for subsequent semantic processing. Up to this point, the entire process is still just “data retrieval” and does not yet involve any semantic-level computation, but it has already provided a complete and stable data foundation for all subsequent steps.
3 Processing and Semantic Transformation of Fetched Article Data
After obtaining the raw article data from WordPress, the next step is to organize this content into a unified structure and, on this basis, generate semantic information that can participate in subsequent calculations.
The core of this stage is not “adding data,” but rather reorganizing existing content to transform it from “content for display” into “input that can be used for computation.”
Structurally, the first thing that needs to be completed is field alignment. In the data obtained through the REST API, information such as titles, links, body text, and tags already exists, but their organization is still oriented toward page display. Therefore, these fields need to be mapped to a more stable internal structure. For example, converting title.rendered into a unified title field, using link as the access address, and keeping content.rendered as the raw content.
On this basis, the body content needs a certain degree of processing. Since the body text returned by the REST API is usually in HTML format, it needs to be converted into a plain text format more suitable for processing before subsequent calculations. This process itself is not complex, and its goal is not to “perfectly restore the content,” but rather to remove structural tags so that the text can serve as a unified input for subsequent steps.
After completing the basic cleaning, the next step is to generate a simplified representation of the article. The most direct way is to extract a summary from the body text that can represent the main content. This process can adopt very simple strategies, such as intercepting the first part of the text or performing lightweight compression. The key is not precision, but providing a semantic carrier with higher information density and a more controllable length.
Compared to summaries, keywords provide another form of expression. In this implementation, tags themselves are a natural starting point and can be used directly as keywords. At the same time, additional words can be extracted from the body text or summary as needed to enhance the expressive capability.
After these treatments, each article is no longer just a collection of raw content, but is transformed into a data record with a unified structure. It both retains basic access information and possesses semantic fields that can participate in calculations, thereby providing a foundation for building relationships in the next step.
4 Building Association Relationships Between Articles Based on Semantic Information
In the previous section, each article was organized into a data record with a unified structure and possessed semantic information that can participate in calculations. On this basis, the next problem to be solved becomes very clear:How exactly are these articles related to each other?
If the previous processing was answering “what each article is,” then what needs to be done in this stage is to answer “what is its relationship with other content.”
From an implementation perspective, the core idea of this step is actually not complex: compare each article with all other articles, and calculate the degree of similarity between them based on semantic information. The “semantic information” here mainly comes from the summaries and keywords generated in the previous stage, which respectively provide two different forms of expression: continuous text and discrete features.
An elegant way to split this is:Line 5: "It is also during this process that the"Line 6: “fields defined in the previous structure are filled. For each article, it is no longer just an independent node, but forms an implicit network of connections with other content through these relationships.”
Wait, the Chinese is:
Line 5: "也正是在这一过程中,前面结构中定义的" -> "It is also during this process that the [fields] defined in the previous structure..." "keywords": ["...", "..."] And Line 6 as: "fields defined in the previous structure are filled. For each article, it is no longer just an independent node, but forms an implicit network of connections with other content through these relationships."
Yes, this is perfect. It maintains the exact flow and grammatical correctness when read together.
Line 5: “It is also during this process that the”
Line 6: "fields defined in the previous structure are filled. For each article, it is no longer just an independent node, but forms an implicit network of connections with other content through these relationships."
5 Outputting the Final Result as a Unified JSON Structure
Yes, "前面结构中定义的" (defined in the previous structure) is in Line 5.So:
Line 5: “It is also during this process that the [fields] defined in the previous structure” -> wait,
在当前的实现中,这一步的处理方式非常直接:将所有文章的结构化结果整理为一个数组,并统一输出为一份 JSON 文件。
之所以选择这种形式,而不是继续依赖接口或引入额外的存储系统,原因在于这一层数据本身具有非常明确的使用场景。它并不是一个需要频繁更新或动态查询的数据源,而是在构建阶段一次性生成,并在运行时被直接读取。因此,将其固化为一个静态文件,反而是最简单且稳定的方案。
从系统角度来看,这份 JSON 文件可以被理解为整个语义表示层的“最终产物”。它既包含了每一篇文章的基础信息,也包含了文章之间的关联关系,从而形成了一份完整的内容索引。
在实际使用中,前端只需要加载这份文件,并根据当前文章的标识查找对应的数据记录,即可获取相关推荐等信息,而无需参与任何额外的计算过程。也正因为如此,前面所有复杂的处理步骤,最终都被收敛为一次简单的数据读取。
至此,从数据获取、语义处理,到关系构建,再到结果输出,整个流程已经形成了一个完整的闭环。而这一闭环的最终形态,就是这份可以被直接消费的 JSON 结构。
7 Summary: From Structural Design to Runnable Semantic Index
到这里为止,这个语义索引的设计已经形成了一个完整的闭环:从 WordPress 获取文章数据的思路,到结构整理、语义生成,再到关联关系的构建方式,最终收敛为一份可以被直接消费的 JSON 结构。
从结构上看,这一套设计已经具备了一个非常关键的能力:它不再只是“文章的集合”,而是一个可以描述文章之间关系的索引结构。每一篇文章都拥有自己的语义信息,并通过 "keywords": ["...", "..."] 字段与其他内容建立了连接,从而在整体上形成了一张隐含的内容网络。
在这个过程中,我们刻意控制了复杂度,保留了最核心的结构与处理逻辑,使整套方案能够以较低成本落地。这也意味着,它并不是一个依赖复杂系统的完整工程方案,而是一种可以被实现的基础形态。
But when this structure actually enters the implementation phase, some more realistic problems will also arise, and these problems are often not prioritized during the design phase.
For example:
- How should data acquisition be organized? How to stably traverse all articles?
- How specifically should the generation of semantic information be handled? What kind of strategy is more appropriate?
- How should the relevance between articles be calculated and sorted?
- How should the finally generated JSON file be used by the blog system?
These problems do not change the rationality of this structure itself, but they determine how this solution performs in a real environment. In other words, up to now, what we have completed is a “deterministic design at the structural level”; and what needs to be solved next is “how to transform this design into a piece of code that can run stably.” It is also at this dividing point that the focus of the problem begins to shift: from “how to define the semantic structure” to “how to implement this structure in a specific environment.”
These topics will be further expanded in the next part.