手把手代码复现Self RAG

这个项目是我在百度aistudio社区发布的一个教程,详情链接:https://aistudio.baidu.com/projectdetail/7579218,可以直接登录社区,直接按照写好的代码实操。复现过程中需要输入大模型调用的密钥,每个账号都有,在设置处可以看到

1.Self RAG和langgraph介绍

1.1 什么是Self RAG

尽管大型语言模型(LLM)具有出色的能力,但由于它们完全依赖于其所包含的参数化知识,往往会产生包含事实错误的回答。所以现在很多人开始使用检索增强生成(RAG)方法,通过检索相关知识来增强LM,从而减少这些问题。但RAG本身也存在很多难点,例如召回文档不准确、大模型的整理能力有限、大模型虚构等,受这些问题影响,RAG的回答也可能不准确。所以近期有学者提出了Slef RAG的方法,该方法通过按需检索和自我反思来改进LLM的生成质量。以下是论文链接: https://arxiv.org/abs/2310.11511

如图,左侧为基本的RAG。假设我们输入问题“美国各州是如何获得他们的名字的?”,我们检索出三个文本片段,其中文本1和3是符合问题要求,2不符合。我们在RAG过程也会经常遇到召回大量噪声片段的情况。然后我们直接把提示的问题和召回文本拼接,一起放到大模型中作答。我们会发现,受到召回文档的不准确、大模型的整理能力有限、大模型幻觉等问题影响,大模型做出的回答也可能存在不准确、虚构等情况。另外,其实一些问题是不需要RAG,可以直接用大模型的能力做回答,例如“写一篇关于你暑假的文章”。如果用基本的RAG框架,也会不分青红皂白地召回不相关文本进行回答。

那么有没有可能赋予大模型一些判断能力,让大模型判断这个问题需不需要做RAG,召回的文本是不是相关,做出的回答有没有虚构,然后不断优化呢。所以我们可以结合agent的思想,升级RAG框架,赋予它一些思考——行动的能力,检索更好的文本,生成更好的答案。

SELF-RAG就是做这样的事情,如图右侧。我们输入同样的问题,先判断,是否需要检索。这里得到3个召回文本,大模型分别根据每个召回文本,并行的生成3个子回答。然后我们用大模型去做判断,生成3个输出:召回的文本是否相关、生成的答案是不是由检索文本所支持(即有没有胡编乱造)、生成的答案是不是对回答问题有用。根据这3个输出,我们对检索文本和子回答进行排序。例如检索文档相关且没有胡编乱造的部分放在第一位。下一步,把这些新的子回答和文档片段再进行检索,如此循环,直到生成一个最佳的回复。

1.2 什么是langgraph

那上面类似agent的功能该如何实现呢?我们当然可以手写一个个判断函数,但那样太麻烦了,所以我们需要一个便捷的工具——langgraph。LangGraph是LangChain近期发布的重要功能,这也标志着LangChain向多代理框架进军。LangGraph构建于LangChain之上,帮助开发者轻松构建强大的代理运行。

这是langgraph的官方博客:

https://blog.langchain.dev/langgraph/

这是langgraph的使用文档:

https://python.langchain.com/docs/langgraph

langgraph是一种以图的方式运行的,其中有三种重要元素StateGraph、Node、Edge。StateGraph是图的状态,用于保存agent运行时的信息。在Slef RAG中,StateGraph就是运行过程中产生的召回文档、问题、子答案等,通常以字典的形式保存;Node是图的节点,是agent中运行的关键节点,例如召回文档是一个节点,根据文档生成答案是一个节点;Edge是边,用于联系各个节点,代表agent的流程去向,通常是让大模型做一个文本分类的任务。例如是否做检索,如果是,那么下一步就到检索节点,如果不是则直接让大模型回答

1.3 如何复现Self RAG

我们下一步根据上图实现一个简化版的Self RAG,逐步拆解,然后整合成一个agent,让大家体会构建的流程。

工作流主要如下:

1.输入问题,检索文档。为了方便演示,我们在这部分做了简化,召回的文档都固定好了

2.评估召回文档是否和问题相关,把相关的文档保存,不相关的删除。起到了一个二次排序的作用

3.判断是否存在相关的文档,如果相关文档列表为空,那么进行问题转写;如果相关文档列表不为空,则根据文档进行答案生成

4.判断答案是否由召回的文档所支持,即判断大模型有没有不遵循文档,胡编乱造。如果支持,则到下一步准备呈现答案;如果不支持,则重新生成回答

5.准备最终评分这个节点只做图状态的变更,不需要调用大模型

6.最后判断答案是否对解决问题有帮助,如果有,则agent结束,如果没有,则进行问题转写,重新再来

要注意的是,我们本次复现的是一个简化版。大家主要是学会其中构建的流程,后续可以根据自身需求做调整

2.测试:用ernie-3.5做意图识别

我们先试一下用文心大模型评估一个一个问题是属于数学(math)、医学(medical),日常(ordinary),学习(study)

安装相关的包

In [1]

!pip install erniebot\==0.5.3  
!pip install langchain\==0.1.11  
!pip install langgraph\==0.0.26

导入相关的包,输入大模型的密钥,密钥在AI Studio个人中心的访问令牌页面:https://aistudio.baidu.com/index/accessToken

In [2]

import erniebot  
import pprint  
from langgraph.graph import END, StateGraph  
from typing import Dict, TypedDict  
from langchain import hub  
  
erniebot.api\_type \= 'aistudio'  
erniebot.access\_token \= '这里输入你的密钥'

意图判断函数

In [3]

def judge\_question(state):  
    """  
    输入一个问题,判断属于哪个类型的问题  
    """  
  
    print("---判断问题类型---")  
    state\_dict \= state\["keys"\]  
    question \= state\_dict\["question"\]  
  
  
    prompt\_str \= f'''  
    你是一个评分员,在评估一个一个问题是属于数学(math)、医学(medical),日常(ordinary),学习(study)  
    以下是问题:  
    \\n ------- \\n  
    {question}   
    只输出'math' , 'medical', 'ordinary', 'study'其中一个词,例如输出'medical',不能输出其他分类,不能输出多余的话  
    '''  
      
    response \= erniebot.ChatCompletion.create(  
    model\='ernie-3.5',  
    messages\=\[{'role': 'user', 'content': prompt\_str}\],  
    )  
    grade \= response.get\_result()  
  
    print(grade)  
                           
    if grade \== "math":  
        print("---决策: 数学问题---")  
        return "math"  
    elif grade \== "medical":  
        print("---决策: 医学问题---")  
        return "medical"  
    elif grade \== "ordinary":  
        print("---决策: 日常问题---")  
        return "ordinary"  
    elif grade \== "study":  
        print("---决策: 学习问题---")  
        return "study"

In [4]

state\_1 \= {"keys": {"question": "小王在哪里工作"}}  
state\_2 \= {"keys": {"question": "肚子痛怎么办"}}

可以看到输入问题"肚子痛怎么办",模型准确地识别是’medical’方面的问题。测试完成

In [5]

result \= judge\_question(state\_2)  
result
\---判断问题类型---  
medical  
\---决策: 医学问题---  

‘medical’

3.节点构建

3.1 检索召回节点

这个函数用于从知识库中检索文档,但为了演示方便,我们把检索到的文档固定成3个片段

大家可以改写这个函数,替换成自己检索出来的文档

在这里插入图片描述

In [6]

def retrieve(state):  
    """  
    用于检索文档  
    """  
    print("---检索文档---")  
  
    state\_dict \= state\["keys"\]  
    question \= state\_dict\["question"\]  
      
    \# 为了方便演示,我们把检索出来的文档固定写死  
    documents \= \["小王是百度公司高管", "小王在北京工作", "小红是小王的妻子"\]  
    return {"keys": {"documents": documents, "question": question}}

In [7]

\# 这是输入,以字典的方式传入,是为了后续记录agent的状态  
state\_1 \= {"keys": {"question": "小王在哪里工作"}}  
state\_2 \= {"keys": {"question": "你好"}}

In [8]

\# 返回的文档片段以列表的形式保存,都是固定的  
result \= retrieve(state\_2)  
result
\---检索文档---  

{'keys': {'documents': \['小王是百度公司高管', '小王在北京工作', '小红是小王的妻子'\], 'question': '你好'}}

3.2 评估文档相关节点

最后会从多个文档中筛选出相关的文档

In [9]

def grade\_documents(state):  
  
    print("---检查文档相关性---")  
    state\_dict \= state\["keys"\]  
    question \= state\_dict\["question"\]  
    documents \= state\_dict\["documents"\]  
  
    \# Score  
    filtered\_docs \= \[\]  
    for context in documents:  
        prompt \= f"""你是一个评分员,正在评估检索到的文档与用户问题的相关性, \\n   
            以下是检索到的文档: \\n\\n {context} \\n\\n  
            这是用户的问题: {question} \\n      
            如果文档包含与用户问题相关的关键词或语义意义,将其评分为相关. \\n  
            只输出一个二分类的评分 'yes' 或者 'no' 用来表示文档是否与问题相关."""  
  
        score \= response \= erniebot.ChatCompletion.create(  
            model\='ernie-3.5',  
            messages\=\[{'role': 'user', 'content': prompt}\],  
            ).get\_result()  
  
        if score \== "yes":  
            print("---评分: 相关文档---")  
            filtered\_docs.append(context)  
        else:  
            print("---评分: 不相关文档---")  
            continue  
  
    return {"keys": {"documents": filtered\_docs, "question": question}}

In [10]

state \= {"keys": {"question": "小王在哪里工作",  
                  "documents": \["小王是百度公司高管", "小王在北京工作", "小红是小王的妻子"\]}}  
  
resulut \= grade\_documents(state)  
resulut
\---检查文档相关性---  
\---评分: 相关文档---  
\---评分: 相关文档---  
\---评分: 不相关文档---  

{'keys': {'documents': \['小王是百度公司高管', '小王在北京工作'\], 'question': '小王在哪里工作'}}

可以看到原文3条召回文档,现在筛选出其中相关的2条

3.3 问题转写节点

这个函数用于:如果没有检索到相关的文档,文档列表为空,则对原问题进行改写

In [11]

def transform\_query(state):  
  
    print("---问题转写---")  
    state\_dict \= state\["keys"\]  
    question \= state\_dict\["question"\]  
    documents \= state\_dict\["documents"\]  
  
    \# Create a prompt template with format instructions and the query  
      
    prompt \= f"""你在生成优化检索的问题. \\n   
        审视输入内容,并尝试推理出其潜在的语义意图/含义. \\n   
        以下是原始的问题:  
        \\n ------- \\n  
        {question}   
        \\n ------- \\n  
        制定一个优化后的问题: """  
      
    better\_question \= erniebot.ChatCompletion.create(  
            model\='ernie-3.5',  
            messages\=\[{'role': 'user', 'content': prompt}\],  
            ).get\_result()  
  
  
    return {"keys": {"documents": documents, "question": better\_question}}

In [12]

\# 输入的问题“小王工作”比较含糊  
state \= {"keys": {"question": "小王工作",  
                  "documents": \['小王是百度公司高管', '小王在北京工作', '小红是小王的妻子'\]}}  
  
resulut \= transform\_query(state)  
resulut
\---问题转写---  

{'keys': {'documents': \['小王是百度公司高管', '小王在北京工作', '小红是小王的妻子'\],  
  'question': '小王的工作是什么?或者小王具体从事什么样的工作?'}}

小王的工作是什么?或者小王具体从事什么样的工作?我们原本的输入是“小王工作”,这个问题很含糊,经过问题转写后,变成了“小王的工作是什么?或者小王具体从事什么样的工作?”,问题变得更聚焦

3.4 生成答案节点

根据检索出来的文档生成回答

In [14]

def generate(state):  
  
    print("---生成阶段---")  
    state\_dict \= state\["keys"\]  
    question \= state\_dict\["question"\]  
    documents \= state\_dict\["documents"\]  
  
    \# Prompt  
    \# 从网站https://smith.langchain.com/hub/hwchase17/rag-prompt拉取RAG的提示词  
    \# 这个网站有很多配套的提示词  
    prompt \= f'''  
    You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question.   
    If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.  
    \\nQuestion: {question}   
    \\nContext: {documents}   
    \\nAnswer:  
    '''  
      
    \# LLM  
    response \= erniebot.ChatCompletion.create(  
        model\='ernie-3.5',  
        messages\=\[{'role': 'user', 'content': prompt}\],  
        )  
      
    generation \= response.get\_result()  
  
    return {  
        "keys": {"documents": documents, "question": question, "generation": generation}  
    }

In [15]

state \= {"keys": {"question": "小王在哪里工作",  
                  "documents": \["小王是百度公司高管", "小王在北京工作", "小红是小王的妻子"\]}}  
  
resulut \= generate(state)  
resulut
\---生成阶段---  

{'keys': {'documents': \['小王是百度公司高管', '小王在北京工作', '小红是小王的妻子'\],  
  'question': '小王在哪里工作',  
  'generation': '小王在北京工作。他是百度公司的高管。'}}

3.5 呈现答案节点

这个函数用于改变图的状态,传递到最后一步判断生成的答案是否对问题有用

In [16]

def prepare\_for\_final\_grade(state):  
  
    print("---准备最后评分---")  
    state\_dict \= state\["keys"\]  
    question \= state\_dict\["question"\]  
    documents \= state\_dict\["documents"\]  
    generation \= state\_dict\["generation"\]  
  
    return {  
        "keys": {"documents": documents, "question": question, "generation": generation}  
    }

4.边的构建

4.1 决定是生成答案还是问题转写

如果检索不到任何文档,那么就转写,否则生成答案。本质就是一个简单的判断

在这里插入图片描述

In [17]

def decide\_to\_generate(state):  
  
    print("---决定是否生成---")  
    state\_dict \= state\["keys"\]  
    question \= state\_dict\["question"\]  
    filtered\_documents \= state\_dict\["documents"\]  
      
    \# 如果没有筛选出合适的文档,就返回特殊字符"transform\_query",否则返回"generate"  
    if not filtered\_documents:   
        \# All documents have been filtered check\_relevance  
        \# We will re-generate a new query  
        print("---决策: 问题转写---")  
        return "transform\_query"  
    else:  
        \# We have relevant documents, so generate answer  
        print("---决策: 生成---")  
        return "generate"

In [18]

state\_1 \= {"keys": {"question": "小王工作",  
                  "documents": \["小王是百度公司高管", "小王在北京工作", "小红是小王的妻子"\]}}  
  
state\_2 \= {"keys": {"question": "小王工作",  
                  "documents": \[\]}}

In [19]

result \= decide\_to\_generate(state\_1)  
result
\---决定是否生成---  
\---决策: 生成---  

'generate'

In [20]

result \= decide\_to\_generate(state\_2)  
result
\---决定是否生成---  
\---决策: 问题转写---  

'transform\_query'

4.2 判断是不是基于文档生成回答

In [24]

def grade\_generation\_v\_documents(state):  
  
    print("---判断是不是基于文档生成内容---")  
    state\_dict \= state\["keys"\]  
    question \= state\_dict\["question"\]  
    documents \= state\_dict\["documents"\]  
    generation \= state\_dict\["generation"\]  
  
    \# Prompt  
    prompt\=f"""你是一个评分员,在评估一个答案是否基于现有的事实依据. \\n   
        以下是事实依据:  
        \\n ------- \\n  
        {documents}   
        \\n ------- \\n  
        以下是回答: {generation}  
        只输出一个二分类的评分 'yes' 或者 'no' 用来表示答案是否基于事实的支持."""  
      
    score \= erniebot.ChatCompletion.create(  
        model\='ernie-3.5',  
        messages\=\[{'role': 'user', 'content': prompt}\],  
        ).get\_result()  
  
    if score \== "yes":  
        print("---决策: 生成的内容基于事实, 来到最后的一步---")  
        return "supported"  
    else:  
        print("---决策: 不支持, 重新生成答案---")  
        return "not supported"

In [25]

\# 生成的答案基本根据文档  
state\_1 \= {'keys': {'documents': \['小王是百度公司高管', '小王在北京工作', '小红是小王的妻子'\],  
                      'question': '小王在哪里工作',  
                      'generation': '小王在中国工作。'}}  
  
\# 生成的答案和文档不相关  
state\_2 \= {'keys': {'documents': \['小王是百度公司高管', '小王在北京工作', '小红是小王的妻子'\],  
                      'question': '小王在哪里工作',  
                      'generation': '小王在苹果公司工作。'}}

In [26]

result \= grade\_generation\_v\_documents(state\_1)  
result
\---判断是不是基于文档生成内容---  
\---决策: 生成的内容基于事实, 来到最后的一步---  

'supported'

In [27]

result \= grade\_generation\_v\_documents(state\_2)  
result
\---判断是不是基于文档生成内容---  
\---决策: 不支持, 重新生成答案---  

'not supported'

4.3 判断答案是否对解决问题有帮助

In [28]

def grade\_generation\_v\_question(state):  
  
    print("---判断答案是否对解决问题有用---")  
    state\_dict \= state\["keys"\]  
    question \= state\_dict\["question"\]  
    documents \= state\_dict\["documents"\]  
    generation \= state\_dict\["generation"\]  
  
    \# Prompt  
    prompt \= f"""你是一个评分助手用于判断回答是否解决了问题. \\n   
        以下是回答:  
        \\n ------- \\n  
        {generation}   
        \\n ------- \\n  
        H以下是问题: {question}  
        给出一个二分类评分 'yes' 或者 'no' 提示答案是否对解决问题有用."""  
      
    score \= erniebot.ChatCompletion.create(  
        model\='ernie-3.5',  
        messages\=\[{'role': 'user', 'content': prompt}\],  
        ).get\_result()  
  
    if score \== "yes":  
        print("---决策: 有用---")  
        return "useful"  
    else:  
        print("---决策: 没用---")  
        return "not useful"

In [29]

\# 这个回答与问题相关,有帮助  
state\_1 \= {'keys': {'documents': \['小王是百度公司高管', '小王在北京工作', '小红是小王的妻子'\],  
                      'question': '小王在哪里工作',  
                      'generation': '小王在中国工作。'}}  
  
\# 这个回答跟问题不相关,没有帮助  
state\_2 \= {'keys': {'documents': \['小王是百度公司高管', '小王在北京工作', '小红是小王的妻子'\],  
                      'question': '小王在哪里工作',  
                      'generation': '小王的妻子是小红。'}}

In [31]

\# 注意:答案“小王在中国工作”对于问题“小王在哪里工作”,不一定很有帮助,所以模型有时输出会变化  
result \= grade\_generation\_v\_question(state\_1)  
result
\---判断答案是否对解决问题有用---  
\---决策: 有用---  

'useful'

In [32]

result \= grade\_generation\_v\_question(state\_2)  
result
\---判断答案是否对解决问题有用---  
\---决策: 没用---  

'not useful'

5.构建agent工作流程图

5.1 定义图

本质是一个字典,里面包含了agnet的去向,agent产生的信息。必须要用langchain的类来定义这个字典

In [33]

class GraphState(TypedDict):  
  
    keys: Dict\[str, any\]  
  
\# 初始化agent工作流  
workflow \= StateGraph(GraphState)

5.2 把节点加入到图中

注意不能重复构建,不要重复执行代码

In [34]

workflow.add\_node("retrieve", retrieve)  \# retrieve  
workflow.add\_node("grade\_documents", grade\_documents)  \# grade documents  
workflow.add\_node("generate", generate)  \# generatae  
workflow.add\_node("transform\_query", transform\_query)  \# transform\_query  
workflow.add\_node("prepare\_for\_final\_grade", prepare\_for\_final\_grade)  \# passthrough

5.3 构建节点与节点之间的边

根据示意图把各个节点和边联系起来

In [35]

\# 初始节点  
workflow.set\_entry\_point("retrieve")

In [36]

\# 检索(节点)——评价文档相关性节点(节点)  
workflow.add\_edge("retrieve", "grade\_documents")

In [37]

\# 评价文档相关性(节点)——根据decide\_to\_generate的结果(边)——决定生成还是问题转写  
workflow.add\_conditional\_edges(  
    "grade\_documents",  
    decide\_to\_generate,  
    {  
        "transform\_query": "transform\_query",  
        "generate": "generate",  
    },  
)

In [38]

\# 问题转写(节点)——检索(节点)  
workflow.add\_edge("transform\_query", "retrieve")

In [39]

\# 生成(节点)——根据grade\_generation\_v\_documents的结果,生成的答案是否基于事实(边)——决定呈现最后答案(节点)还是继续生成(节点)  
workflow.add\_conditional\_edges(  
    "generate",  
    grade\_generation\_v\_documents,  
    {  
        "supported": "prepare\_for\_final\_grade",  
        "not supported": "generate",  
    },  
)

In [40]

\# 呈现最后答案(节点)——根据grade\_generation\_v\_question的结果,判断最后生成的答案是否对解决问题有用(边)——决定结束循环(END)还是转写问题(节点)  
workflow.add\_conditional\_edges(  
    "prepare\_for\_final\_grade",  
    grade\_generation\_v\_question,  
    {  
        "useful": END, \# 从组件中导入的from langgraph.graph import END  
        "not useful": "transform\_query",  
    },  
)

5.4 编译图

In [41]

app \= workflow.compile()

6.测试agent

至此,结合了agent的Self RAG简化版构建完成,我们输入一条问题,看看效果怎么样

In [42]

\# 这是一条相关的示例  
inputs \= {"keys": {"question": "小王的工作地点是哪里?"}}  
for output in app.stream(inputs):  
    for key, value in output.items():  
        \# Node  
        pprint.pprint(f"Node '{key}':")  
        \# Optional: print full state at each node  
        \# pprint.pprint(value\["keys"\], indent=2, width=80, depth=None)  
    pprint.pprint("\\n---\\n")  
  
\# Final generation  
pprint.pprint(value\["keys"\]\["generation"\])
\---检索文档---  
"Node 'retrieve':"  
'\\n---\\n'  
\---检查文档相关性---  
\---评分: 不相关文档---  
\---评分: 相关文档---  
\---评分: 不相关文档---  
"Node 'grade\_documents':"  
'\\n---\\n'  
\---决定是否生成---  
\---决策: 生成---  
\---生成阶段---  
"Node 'generate':"  
'\\n---\\n'  
\---判断是不是基于文档生成内容---  
\---决策: 生成的内容基于事实, 来到最后的一步---  
\---准备最后评分---  
"Node 'prepare\_for\_final\_grade':"  
'\\n---\\n'  
\---判断答案是否对解决问题有用---  
\---决策: 有用---  
"Node '\_\_end\_\_':"  
'\\n---\\n'  
'小王的工作地点在北京。'

7.总结

本项目利用langgraph工具,实现了一个简化版的Self RAG。langgraph是一个非常灵活的工具,我们可以通过学习这个demo,进行适配性的改造,不仅能实现更好的RAG,还可以配合其他场景,实现不同任务的agent哦

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值