掘金 人工智能 前天 10:58
AI学习笔记 — RAG 与 中医知识的碰撞
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文深入探讨了检索增强生成(RAG)技术在知识密集型NLP任务中的应用,并以中医知识问答系统为例,详细介绍了RAG的实践过程。该系统通过结合预训练模型和非参数记忆,实现了对中医知识的精准检索和回答,解决了传统模型在知识更新和幻觉方面的问题。文章还阐述了系统的架构、关键组件和实践结果,展示了RAG技术在实际应用中的潜力。

💡 RAG的核心思想是将语言模型的记忆分为参数化记忆和非参数化记忆,以应对知识动态更新和幻觉问题。

📚 系统利用预训练的检索器(Retriever)结合预训练的seq2seq模型,通过最大内积查找在知识库中检索相关文档切片。

🔍 该系统使用Eino框架构建知识处理流水线,包括数据提取、转换、嵌入和生成等步骤,以实现中医知识的精准检索。

🗣️ 系统通过用户提问,结合检索到的相关知识,生成对问题的回答,实现了症状到关键知识的精准检索。

RAG [Retrieval-Augmented Generation]

原文

《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》

proceedings.neurips.cc/paper/2020/…

预训练的自然语言模型能够从数据学习到大量深度知识,使其仅需访问参数化的隐性数据库而无需访问外部数据;但无法简单的扩展和修改记忆,同时可能有幻觉现象的产生;将参数记忆和非参数记忆相结合构建混合模型,利用其直接修改和拓展记忆;REALM 和 ORQA 将语言模型和可微分的检索器(Retriever) 相结合,取得不错的结果;

将预训练的检索器(Retriever) 与预训练的seq2seq模型结合,并进行微调;检索器(Retriever) 对于输入的Query使用最大内积查找(MIPS)找到前K个文档切片(z);对于最终预测结果y,将文档切片(z)作为潜在变量,根据不同文档切片对seq2seq预测边缘化;

这种通⽤微调⽅法将参数记忆(parametric-memory)⽣成模型⾮参数记忆(non-parametric memory),我们称之为检索增强⽣成(RAG);

总结

    核心思想是将自然语言模型的记忆分为参数化记忆非参数化记忆,解决记忆动态更新和幻像问题;

      参数化记忆: 存储了通过预训练学习到的语言模式和通用知识。非参数化记忆: 使用一个可检索的动态知识库。

    检索器(Retriever) 承载定制化索引知识库(Embedding) 和输入内容的检索能力,对知识库进行拆分和向量化存储称之为索引数据库;用户输入的提示词(User Prompt),检索器会对内容也进行一次向量化处理,再到向量化数据库检索出k片相关性高的切片;

    生成器(Generator) 承载大语言模型,对每一片切片、用户提示词和系统提示词(System Prompt)作为上下文,返回结果;

RAG 实践

实践结果

倪海夏针灸专题为数据源,设计包含下针方法、对应视频节点的元数据结构作为索引知识库,实现症状到关键知识的精准检索

问题1: 病人中风怎么办回答: 如果病人中风,出现舌强不语、手握拳的症状,可找到廉泉穴进行治疗。找穴方法为:用大拇指指尖顶到下巴处,指尖到处即为廉泉穴。下针时,针要对着舌根,而不是直针下,下针深度一寸到一寸半即可。该穴位大部分用针治疗,一般不用灸。 问题2: 对应视频时间节点是多少回答: 文档中提到病人中风相关内容的视频时间是 2-00:43:13 。(第二集的43分13秒)

系统架构

数据准备

视频字幕提取

火山引擎申请音视频字幕生成能力,对本地视频进行批量字幕提取;

www.volcengine.com/docs/6561/8…

markdown文件生成

使用AI归纳总结内容并生成markdown文件,效果如下:

# 任脉与督脉##time (1-02:18:45)我们开始介绍任脉。**任**,女子妊也,女人会怀孕是靠任脉。十二经络开始介绍之前,要从任脉开始介绍。找穴道要从任、督二脉为基准,找到标准,就可以很快速的找到穴道。我最怕就是鸡同鸭讲,心里知道答案,结果穴道找错了。- **任脉**:是所有阴汇积的地方- **督脉**:是诸阳之会!全身的动能,能量,都在督脉上面> 我最常跟病人讲一句话就是,无论如何不要让别人碰你的脊椎骨,督脉不能碰,脊椎骨像龙骨一样,有人椎间盘凸出,有人去开刀,开完反而更坏。MAS 根本就是疫苗引起的。造成一开始脊椎就弯的,你想想,疫苗可以把所有阳气所在的督脉都打烂,这种人就不长寿。比如说我们叫天柱倾,脖子都歪过去,这样的人命在旦夕,一两天就走了。女人怀孕全靠任脉。督脉走在后面,诸阳之会,脊椎骨上面,任督二脉交会在鼻子人中这边。刚好嘴巴讲话,讲话时任督二脉是开的,你在听课的时候,舌头是顶着上颚。这是你的牙龈,这牙齿,侧面看哦,然后这是下牙,这是嘴唇。简单的概念,舌头顶到上颚的时候,任督二脉是通的。注意看乌龟,乌龟就是这样。所以,乌龟很长寿。我在讲课的时候,嘴巴会动,而你们在听课时,是把舌头顶上去的,脑筋会很清醒,阴电阳电相通。## 任脉穴位任脉有三八二十四个穴道,任脉三八起会阴。……

KnowledgeIndexing

使用Eino-dev插件构建向量知识库Workflow,提供常用的 AI 组件以及集成组件编排能力; 编排后改自己申请的模型配置即可;

www.cloudwego.io/zh/docs/ein…

编排后可以看到生成了代码文件,如图上串联;入口文件是orchestration.go;输入文件路径返回ids;

Transformer

主要对输入知识库进行分割,构建向量数据的元数据;主要对标题和时间进行存储和索引;

func newDocumentTransformer(ctx context.Context) (tfr document.Transformer, err error) {    config := &markdown.HeaderConfig{        Headers: map[string]string{            "#":      "title",            "##time": "time",        },        TrimHeaders: false}    tfr, err = markdown.NewHeaderSplitter(ctx, config)    if err != nil {        return nil, err    }    return tfr, nil}

元数据(metadata)存储title和time,content为段落内容;

Main

main函数批量读本地知识库文件数据,并调用orchestration.go内的函数,传入需要处理的文件路径即可;

func main() {    ctx := context.Background()    err := indexMarkdownFiles(ctx, "./docs")    if err != nil {        panic(err)    }}func indexMarkdownFiles(ctx context.Context, dir string) error {    runner, err := knowledgeindexing.BuildKnowledgeIndexing(ctx)    if err != nil {        return fmt.Errorf("build index graph failed: %w", err)    }    err = filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {        if err != nil {            return fmt.Errorf("walk dir failed: %w", err)        }        if d.IsDir() {            return nil        }        ids, err := runner.Invoke(ctx, document.Source{URI: path})        if err != nil {            return fmt.Errorf("invoke index graph failed: %w", err)        }        return nil    })    return err}

执行main函数,我们可以看到Redis数据库已经写入向量数据,如图:

RAG System

Main

简单实现一个交互式问答系统,启动RAG系统并将用户输入内容传入;

func main() {    // 定义命令行参数    useRedis := flag.Bool("redis", true, "是否使用Redis进行检索增强")    topK := flag.Int("topk", 3, "检索的文档数量")    flag.Parse()    // 构建RAG系统    ctx := context.Background()    ragSystem, err := rag.BuildRAG(ctx, *useRedis, *topK)    if err != nil {        fmt.Fprintf(os.Stderr, "构建RAG系统失败: %v\n", err)        os.Exit(1)    }    // 显示启动信息    if *useRedis {        fmt.Println("启动RAG系统 (使用Redis检索)")    } else {        fmt.Println("启动RAG系统 (不使用检索)")    }    fmt.Println("输入问题或输入'exit'退出")    // 创建输入扫描器    scanner := bufio.NewScanner(os.Stdin)    // 主循环    for {        fmt.Print("\n问题> ")        // 读取用户输入        if !scanner.Scan() {            break        }        input := strings.TrimSpace(scanner.Text())        if input == "" {            continue        }        // 检查退出命令        if strings.ToLower(input) == "exit" {            break        }        // 处理问题        answer, err := ragSystem.Answer(ctx, input)        if err != nil {            fmt.Fprintf(os.Stderr, "处理问题时出错: %v\n", err)            continue        }        // 显示回答        fmt.Println("\n回答:")        fmt.Println(answer)    }    if err := scanner.Err(); err != nil {        fmt.Fprintf(os.Stderr, "读取输入时出错: %v\n", err)    }}

实践总结

开发效率
基于Eino框架可快速构建知识处理流水线,显著降低实现复杂度。

效果验证
• 成功实现知识精准定位(内容+时间节点)
• 有效解决中医知识结构化检索需求
• 待优化:上下文对话能力(后续版本迭代)

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

RAG 检索增强生成 NLP 中医问答系统
相关文章