中宏安科技 大模型训练工程师 一面

1.自我介绍

2. 文章分类大概有多少文章?数据规模怎么影响方案?

答案:

如果文章量只有几千篇,我一般不会一上来就训练很复杂的模型,而是先用预训练模型微调,或者用 embedding 加传统分类器做一个强 baseline。因为数据量太小的时候,复杂模型很容易过拟合,线上效果不稳定。

如果有几十万到几百万篇文章,就可以考虑训练一个更稳定的分类模型,包括 BERT 微调、领域继续预训练、层级分类模型,甚至做多任务学习。数据量越大,越要关注标签噪声,因为文章分类里的标注经常不是绝对干净的,尤其是多维度分类,一个文档可能同时属于多个业务类别。

实际项目里我会先看三个东西:类别数量、每个类别样本分布、单篇文档长度。因为分类方案不是只由文章数量决定的,文档长度和标签体系对模型设计影响更大。

3. 文章自动分类具体是怎么做的?整体链路怎么实现?

答案:

文章分类一般不会直接从文件进模型,而是先做文档解析,把 Word、PDF、HTML、TXT 等格式统一转成结构化文本。然后做清洗、去噪、分段,提取标题、摘要、正文、目录、章节名等字段,再进入分类模型。

如果是短文档,可以直接用 BERT 类模型做分类。如果是长文档,就会先切 chunk,每个 chunk 单独编码,然后把 chunk 级别的表示再聚合成文档级表示,最后做分类。线上一般还会加规则兜底,比如标题里出现非常强的业务关键词时,可以提高某个类别的权重。

代码上,一个简单的文本分类流程大概是这样:

from transformers import AutoTokenizer, AutoModel
import torch
import torch.nn as nn

class DocClassifier(nn.Module):
    def __init__(self, model_name, num_labels):
        super().__init__()
        self.encoder = AutoModel.from_pretrained(model_name)
        self.dropout = nn.Dropout(0.1)
        self.classifier = nn.Linear(self.encoder.config.hidden_size, num_labels)

    def forward(self, input_ids, attention_mask):
        outputs = self.encoder(input_ids=input_ids, attention_mask=attention_mask)
        cls = outputs.last_hidden_state[:, 0, :]
        logits = self.classifier(self.dropout(cls))
        return logits

这个只适合短文本或者截断后的文本。如果文档很长,就不能只靠这个结构。

4. 用 BERT 做文章分类时,是把整篇文章都放进去吗?

答案:

一般不会。BERT 的输入长度通常是 512 token,中文文章稍微长一点就会超过这个长度。如果直接截断,只保留前 512 个 token,可能会丢掉正文后面的关键信息。比如合同、标书、审计报告、技术文档,重要结论不一定在开头。

比较常见的做法是把文章切成多个 chunk,每个 chunk 送进 BERT 得到一个向量,然后再把这些 chunk 向量聚合成文档向量。聚合方式可以是 mean pooling、max pooling、attention pooling,也可以用一个上层 Transformer 建模 chunk 之间的关系。

简单实现如下:

def split_text(text, max_len=400, stride=100):
    chunks = []
    start = 0
    while start < len(text):
        chunks.append(text[start:start + max_len])
        start += max_len - stride
    return chunks

这里用 stride 是为了避免切分边界把一句话或者一个关键信息截断。实际业务里还会优先按标题、段落、章节来切,而不是纯按长度切。

5. 如果 Word 文档有多个分类维度,自动分类应该怎么做?

答案:

多维度文档分类一般不是单标签分类,而是多任务或者多标签问题。比如一个文档既要判断所属业务线,又要判断文档类型,还要判断风险等级、保密等级、适用部门,这些维度之间可能有关联,但不能简单合成一个超大类别。

我会倾向于共享一个文档编码器,然后每个维度接一个独立分类头。这样底层语义表示可以共享,上层每个任务单独学习自己的标签空间。比如业务类型是 20 类,风险等级是 4 类,文档来源是 6 类,那就接三个 head。

class MultiTaskDocClassifier(nn.Module):
    def __init__(self, encoder, hidden_size, task_labels):
        super().__init__()
        self.encoder = encoder
        self.heads = nn.ModuleDict({
            task: nn.Linear(hidden_size, num_labels)
            for task, num_labels in task_labels.items()
        })

    def forward(self, doc_vector):
        return {
            task: head(doc_vector)
            for task, head in self.heads.items()
        }

如果某些维度允许一个文档属于多个标签,就不能用 softmax,而要用 sigmoid + BCEWithLogitsLoss。多维度分类的核心不是把标签硬拼起来,而是把标签体系设计清楚。

6. 如果一个文档有 5000 页,怎么做分类?

答案:

5000 页的文档不能直接丢给任何常规分类模型。这个时候要把分类问题变成一个层级证据聚合问题,先从文档中找出对分类最有用的部分,再基于这些证据做判断。

比较合理的流程是先解析目录、标题、页眉页脚、章节结构,然后按章节或页面分块。每个块先做粗筛,判断它和目标分类维度有没有关系。只保留高相关 chunk,再进行精排、摘要和分类。最后模型不是基于全文判断,而是基于“关键证据片段 + 结构信息 + 摘要”判断。

这种任务里,最重要的是不要平均处理所有页面。5000 页里可能只有几十页真正决定分类,比如摘要、目录、结论、风险提示、技术方案、财务表格说明等。工程上可以设计两阶段模型:第一阶段召回相关片段,第二阶段做文档级分类。

7. 你会怎么给上千页甚至 2GB 的大文档打分?

答案:

大文档打分不能直接让模型读全文后给分,而是要把评分标准拆成若干可验证的评分项。比如合规性、完整性、风险程度、技术可行性、证据充分性,每一项都要对应可检索的证据。

实际做法是先把文档切块并建立索引,然后针对每个评分项生成查询,从文档中召回相关片段。模型只基于这些片段给单项分,并要求输出引用依据。最后再把各项分数按权重汇总成总分。

def final_score(item_scores, weights):
    score = 0
    for item, value in item_scores.items():
        score += value * weights.get(item, 0)
    return round(score, 2)

item_scores = {
    "completeness": 82,
    "risk": 65,
    "feasibility": 78
}

weights = {
    "completeness": 0.4,
    "risk": 0.3,
    "feasibility": 0.3
}

print(final_score(item_scores, weights))

对于 2GB 文件,重点不是模型有多大,而是文档解析、分块索引、证据召回和评分一致性。否则模型给出来的分数很容易变成主观判断,难以复核。

8. 你处理过的文档一般有多大?不同大小的文档方案有什么区别?

答案:

如果是几页到几十页的文档,可以直接按段落切分,召回关键段落后分类。几百页的文档就需要明显的章节结构处理,因为全文 chunk 数量已经比较多,不能全部送入

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

AI-Agent面试实战专栏 文章被收录于专栏

本专栏聚焦 AI-Agent 面试高频考点,内容来自真实面试与项目实践。系统覆盖大模型基础、Prompt工程、RAG、Agent架构、工具调用、多Agent协作、记忆机制、评测、安全与部署优化等核心模块。以“原理+场景+实战”为主线,提供高频题解析、标准答题思路与工程落地方法,帮助你高效查漏补缺.

全部评论

相关推荐

大二玩了半年RAG,我发现最靠谱的解法,居然是百年图书馆逻辑本人大二,接触Agent开发从RAG入门,摸过GraphRAG、RAGFlow这些热门项目,也啃过LlamaIndex、LangChain框架,踩了不少坑,也有了些不一样的想法,纯分享思路,不做落地。先说说我看到的核心问题:RAGFlow的溯源功能能标清信息出处,解决了模型胡编的问题,却缺了LangChain那样的隐私数据守卫——检索时只过滤正文,溯源链接还留着,等于给隐私泄露、外网信息跳转留了后门。同时现在的RAG大多是文档乱塞一锅炖,海量数据根本管不住,开源框架要么太笨重新手难维护,要么功能太简陋撑不起场景。想通这些的时候我正在学校图书馆,突然发现:我们卷破头的RAG问题,现代图书馆这套人类用了上百年的「信息管理系统」,早就完美解决了。核心思路完全对标图书馆逻辑,分三点:1.&nbsp;先分级管控,从根源堵隐私漏洞像图书馆分普通阅览区、内部资料室、涉密档案室一样,给文档做分级。敏感内容直接拦在库外,内部文档没权限连检索都搜不到,自然不会有溯源链接泄露的问题,只有合规公开内容才开放完整溯源。2.&nbsp;先分类入库,解决海量数据混乱图书馆新书不会直接堆书架,会先验收、查重、按标准分类标引再上架。对应到RAG里,就是文档先自动清洗、去重、分类打标,再分到独立向量库物理隔离,再多文档也井井有条,不会越用越臃肿。3.&nbsp;统一规范做开源生态,解决「各玩各的」的痛点图书馆能跨馆互通,核心是有统一的编目规则。我们也可以定一套极简统一的开源RAG库规范,实现两个核心:一是人人都能按规范分享自己的RAG库,开箱即用不用二次处理;二是符合规范的任意两个RAG库,都能无缝拼接,自动对齐分类、去重、更新索引,不用手动改配置。现在RAG圈总在卷框架、卷算法,却忘了做RAG的初衷,是让普通人用最低成本让AI落地。这套图书馆逻辑的思路,不用高算力不堆复杂技术,刚好能让本地小模型配上标准化RAG库,真正变得可用。纯思路分享,不打算自己落地做项目,玩RAG的朋友有想法,欢迎一起交流。大模型&nbsp;&nbsp;开源思路&nbsp;#大学生编程
空想天使:有的兄弟有的,rag有这些技术,第一点叫做二级权限校验,在用户输入,调向量库之前,先去用户数据库找找有没有这用户,如果没有就挡住,第二部就是调知识库之前再去用户数据库核对一下,他的读库权限和检索库名是否对应,不对应也挡住。第二点叫做分库管理+元数据过滤。核心就是用户问2024或者指定v0.1版本的文档,那检索的时候就筛选对应的文档标签。第三点我还没听说过倒是,毕竟rag这玩意做出来的主要目的就是赋能企业的知识库,而企业知识库一般都是私有的,比较讲究私有化部署,有啥需要共享内容的直接调用web search得了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务