基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (十一)
LlaMA 3 系列博客
基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (一)
基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (二)
基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (三)
基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (四)
基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (五)
基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (六)
基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (七)
基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (八)
基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (九)
基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (十)
构建安全的GenAI/LLMs核心技术解密之大模型对抗攻击(一)
构建安全的GenAI/LLMs核心技术解密之大模型对抗攻击(二)
构建安全的GenAI/LLMs核心技术解密之大模型对抗攻击(三)
构建安全的GenAI/LLMs核心技术解密之大模型对抗攻击(四)
构建安全的GenAI/LLMs核心技术解密之大模型对抗攻击(五)
你好 GPT-4o!
大模型标记器之Tokenizer可视化(GPT-4o)
大模型标记器 Tokenizer之Byte Pair Encoding (BPE) 算法详解与示例
大模型标记器 Tokenizer之Byte Pair Encoding (BPE)源码分析
大模型之自注意力机制Self-Attention(一)
大模型之自注意力机制Self-Attention(二)
大模型之自注意力机制Self-Attention(三)
在前面的博客中谈到,这些行从不同来源获取文本数据,包括 Web URL 和 PDF 文档。 WebBaseLoader 用于从 URL 加载内容,而 PyPDFDirectoryLoader 用于从本地目录加载 PDF 文件。
##sources
#url
urls = [
"https://lilianweng.github.io/posts/2023-06-23-agent/",
"https://lilianweng.github.io/posts/2023-03-15-prompt-engineering/",
"https://lilianweng.github.io/posts/2023-10-25-adv-attack-llm/",
]
docs = [WebBaseLoader(url).load() for url in urls]
docs_list = [item for sublist in docs for item in sublist]
#pdf
loader = PyPDFDirectoryLoader("C://Users//ASUS//Downloads//sources//")
data = loader.load()
docs_list.extend(data)
带领大家学习了OpenAI公司AI 安全经理Lilian Weng 三个链接文档的内容。接下来,继续看基于 LlaMA 3 + LangGraph 的代码。
#splitter
text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
chunk_size=1000, chunk_overlap=200
)
doc_splits = text_splitter.split_documents(docs_list)
在这里,文本分割器被初始化以将文档分割成更小的块以进行高效处理。此步骤对于向量化和检索等任务至关重要,在这些任务中处理大型文档可能会带来性能挑战。
# 添加到vectorDB
vectorstore = Chroma.from_documents(
documents=doc_splits,
collection_name= "rag-chroma" ,
embedding=embeddings,
)
retriever = vectorstore.as_retriever()
这些行使用 Chroma 创建向量存储,Chroma 是 Langchain 的一个组件,负责存储和查询文档嵌入。使用指定的嵌入对文档进行向量化,并添加到向量存储中,从而实现基于语义相似性的高效检索。
### Retrieval Grader
prompt = PromptTemplate(
template="""system You are a grader assessing relevance
of a retrieved document to a user question. If the document contains keywords related to the user question,
grade it as relevant. It does not need to be a stringent test. The goal is to filter out erroneous retrievals. \n
Give a binary score 'yes' or 'no' score to indicate whether the document is relevant to the question. \n
Provide the binary score as a JSON with a single key 'score' and no preamble or explaination.
user
Here is the retrieved document: \n\n {document} \n\n
Here is the user question: {question} \n assistant
""",
input_variables=["question", "document"],
)
retrieval_grader = prompt | llm | JsonOutputParser()
template= """system 您是一名评分员,评估检索
到的文档与用户问题的相关性。如果文档包含与用户问题相关的关键字,
则将其评分为相关。不需要目标是过滤掉错误的检索。 \n
给出二进制分数“是”或“否”分数以指示文档是否与问题相关。 \n
以 JSON 形式提供二进制分数。单个键“分数”,没有序言或解释
user
这是检索到的文档: \n\n {document} \n\n
这是用户问题: {question} \n Assistant
""" ,
input_variables=[ "问题" , "文档" ],
本节定义了一个提示模板,用于对检索到的文档与用户问题的相关性进行评分。该模板概述了评分标准,并提示用户提供指示文档相关性的二进制分数。分数使用 Langchain 的 ChatOllama 实例进行处理,并解析为 JSON 格式以供进一步评估。
### Generate
prompt = PromptTemplate(
template="""system 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 user
Question: {question}
Context: {context}
Answer: assistant""",
input_variables=["question", "document"],
)
template= """system 你是问答任务的助手。
使用以下检索到的上下文来回答问题。如果你不知道答案,就说你不知道
最多使用三个句子并保持答案简洁 用户问题
:{question}
上下文:{context}
答案:assistant"""
该提示模板旨在根据检索到的上下文生成用户问题的答案。它指示助手利用检索到的文档作为上下文,使用最多三个句子提供简洁的答案。该模板有助于 Langchain 框架内的问答任务。
# 后处理
def format_docs ( docs ):
return "\n\n" .join(doc.page_content for doc in docs)
此函数对检索到的文档执行后处理,将其格式化为可读的文本格式。它将每个文档的页面内容用双换行符连接起来,以提高可读性。
# Chain
rag_chain = prompt | llm | StrOutputParser()
rag_chain这里,使用 Langchain 组件构建处理链( ),包括提示模板、ChatOllama 实例( llm)和字符串输出解析器。该链有助于根据所提供的上下文生成对用户查询的响应。
### Hallucination Grader
prompt = PromptTemplate(
template=""" system You are a grader assessing whether
an answer is grounded in / supported by a set of facts. Give a binary score 'yes' or 'no' score to indicate
whether the answer is grounded in / supported by a set of facts. Provide the binary score as a JSON with a
single key 'score' and no preamble or explanation. user
Here are the facts:
\n ------- \n
{documents}
\n ------- \n
Here is the answer: {generation} assistant""",
input_variables=["generation", "documents"],
)
hallucination_grader = prompt | llm | JsonOutputParser()
template= """ system 您是一名评分者,评估
答案是否基于一组事实/由一组事实支持。给出二进制分数“是”或“否”分数以表明
是否答案基于/由一组事实支持。以 JSON 形式提供具有
单个键“分数”的二进制分数,并且没有序言或解释 用户
以下是事实:
\n ---------- \n
{文档}
\n ------- \n
答案如下:{生成}助手""" ,
input_variables=[ "生成" , "文档" ],
本节定义了一个提示模板,用于对生成的答案的事实基础进行评分。该模板提示用户评估答案是否得到作为上下文提供的一组事实的支持。生成的答案(generation)和相关文档(documents)通过 Langchain 组件进行评估,并将得到的分数解析为 JSON 格式。
### Answer Grader
prompt = PromptTemplate(
template="""system You are a grader assessing whether an
answer is useful to resolve a question. Give a binary score 'yes' or 'no' to indicate whether the answer is
useful to resolve a question. Provide the binary score as a JSON with a single key 'score' and no preamble or explanation.
user Here is the answer:
\n ------- \n
{generation}
\n ------- \n
Here is the question: {question} assistant""",
input_variables=["generation", "question"],
)
answer_grader = prompt | llm | JsonOutputParser()
template= """system 您是一名评分者,评估
答案是否有助于解决问题。给出二进制分数“是”或“否”以指示答案是否有助于
解决问题问题。以 JSON 形式提供具有单个键“分数”且没有前言或解释的
用户 这是答案:
\n ------- \n
{ Generation}
\n ----- 。 -- \n
这是问题:{问题}助手""" ,
input_variables=[ "生成" , "问题" ],
本节定义了一个提示模板,用于对生成的答案在解决用户问题时的有用性进行评分。该模板提示用户提供一个二进制分数,指示答案是否有效地解决了给定的问题。答案( generation)和问题( question)使用Langchain组件进行处理,并将得到的分数解析为JSON格式进行评估。
### Router
prompt = PromptTemplate(
template="""system
You excel in directing user inquiries either to a vector store or a web search.
For queries related to documents within the vector store, prioritize utilizing the vector store.
There's no need to strictly match keywords in the question to topics within the vector store.
If the question isn't covered by the vector store's content, resort to a web search.
Provide a binary decision, 'web_search' or 'vectorstore', depending on the nature of the question.
Return the a JSON with a single key 'datasource' and
no premable or explaination. Question to route: {question} assistant""",
input_variables=["question"],
)
question_router = prompt | llm | JsonOutputParser()
template= """system
您擅长将用户查询引导至矢量存储或 Web 搜索。
对于与矢量存储中的文档相关的查询,优先使用矢量存储。
没有必要将问题中的关键字与矢量存储中的主题严格匹配。
如果矢量存储的内容未涵盖该问题,请
根据问题的性质提供二元决策“web_search”或“vectorstore” 。
返回带有单个键“数据源”且没有前置或解释的 JSON 。要路由的问题
: {question} Assistant""" ,
input_variables=[ "question" ],
本节定义了一个提示模板,用于根据问题的性质将用户查询路由到矢量存储或网络搜索引擎。该模板指示用户提供一个二元决策,指示用于回答问题的首选数据源(web_search或)。vectorstore使用 Langchain 组件处理问题,并将路由决策解析为 JSON 格式。
### 搜索
os.environ[ "TAVILY_API_KEY" ] = "tvly-XXXX"
web_search_tool = TavilySearchResults(k= 3 )
web_search_tool本节初始化由 Tavily API 提供支持的网络搜索工具 ( )。 Tavily API 密钥设置为环境变量,以启用对 Web 搜索功能的访问。
### State
class GraphState(TypedDict):
"""
Represents the state of our graph.
Attributes:
question: question
generation: LLM generation
web_search: whether to add search
documents: list of documents
"""
question : str
generation : str
web_search : str
documents : List[str]
这里GraphState定义了一个类来表示 Langchain 图的状态。状态包括诸如问题、生成的答案、是否需要网络搜索的指示以及相关文档的列表等属性。
### Nodes
def retrieve(state):
"""
Retrieve documents from vectorstore
Args:
state (dict): The current graph state
Returns:
state (dict): New key added to state, documents, that contains retrieved documents
"""
print("---RETRIEVE---")
question = state["question"]
# Retrieval
documents = retriever.invoke(question)
return {"documents": documents, "question": question}
def generate(state):
"""
Generate answer using RAG on retrieved documents
Args:
state (dict): The current graph state
Returns:
state (dict): New key added to state, generation, that contains LLM generation
"""
print("---GENERATE---")
question = state["question"]
documents = state["documents"]
# RAG generation
generation = rag_chain.invoke({"context": documents, "question": question})
return {"documents": documents, "question": question, "generation": generation}
def grade_documents(state):
"""
Determines whether the retrieved documents are relevant to the question
If any document is not relevant, we will set a flag to run web search
Args:
state (dict): The current graph state
Returns:
state (dict): Filtered out irrelevant documents and updated web_search state
"""
print("---CHECK DOCUMENT RELEVANCE TO QUESTION---")
question = state["question"]
documents = state["documents"]
# Score each doc
filtered_docs = []
web_search = "No"
for d in documents:
score = retrieval_grader.invoke({"question": question, "document": d.page_content})
grade = score['score']
# Document relevant
if grade.lower() == "yes":
print("---GRADE: DOCUMENT RELEVANT---")
filtered_docs.append(d)
# Document not relevant
else:
print("---GRADE: DOCUMENT NOT RELEVANT---")
# We do not include the document in filtered_docs
# We set a flag to indicate that we want to run web search
web_search = "Yes"
continue
return {"documents": filtered_docs, "question": question, "web_search": web_search}
这段代码定义了三个函数, 下面是每个函数的简要说明:
retrieve(state)
这个函数的目的是从向量存储库中检索文档。它接收一个包含当前图状态的字典 state
作为参数,并返回一个新的状态字典,其中添加了一个新键 documents
,包含了检索到的文档。
- 打印出
"---RETRIEVE---"
以标识该函数正在执行。 - 从
state
中获取question
。 - 使用
retriever.invoke(question)
进行文档检索,retriever
是一个检索器对象或函数。 - 返回一个包含检索到的文档和原始问题的更新状态字典。
generate(state)
这个函数使用检索到的文档和问题,通过 RAG(Retrieval-Augmented Generation)生成答案。
- 打印出
"---GENERATE---"
以标识该函数正在执行。 - 从
state
中获取question
和documents
。 - 使用
rag_chain.invoke
调用 RAG 生成器,传入包含文档上下文和问题的字典。 - 返回一个包含文档、问题和生成的答案的更新状态字典。
grade_documents(state)
这个函数评估检索到的文档是否与问题相关,并根据评估结果决定是否需要进行网络搜索。
- 打印出
"---CHECK DOCUMENT RELEVANCE TO QUESTION---"
以标识该函数正在执行。 - 从
state
中获取question
和documents
。 - 对于每个文档,使用
retrieval_grader.invoke
来评分,传入问题和文档内容。 - 如果文档评分为 “yes”,则认为文档相关,将其添加到
filtered_docs
列表中。 - 如果文档评分不是 “yes”,则认为文档不相关,不将其添加到
filtered_docs
列表中,并设置web_search
标志为 “Yes”。 - 返回一个包含过滤后的文档、原始问题和
web_search
状态的更新状态字典。
这些函数代表 Langchain 图中的不同节点,每个节点负责特定的任务。retrieve从向量存储中检索相关文档,generate使用 RAG 模型生成答案,并grade_documents评估检索到的文档与用户问题的相关性,并确定是否需要进行网络搜索。
def web_search(state):
"""
Web search based based on the question
Args:
state (dict): The current graph state
Returns:
state (dict): Appended web results to documents
"""
print("---WEB SEARCH---")
question = state["question"]
documents = state["documents"]
# Web search
docs = web_search_tool.invoke({"query": question})
web_results = "\n".join([d["content"] for d in docs])
web_results = Document(page_content=web_results)
if documents is not None:
documents.append(web_results)
else:
documents = [web_results]
return {"documents": documents, "question": question}
该函数根据用户问题执行网络搜索,并将检索到的网络结果附加到现有文档列表中。 Tavily API 用于执行网络搜索,检索到的内容被格式化并添加到文档列表中。
def route_question(state):
"""
Route question to web search or RAG.
Args:
state (dict): The current graph state
Returns:
str: Next node to call
"""
print("---ROUTE QUESTION---")
question = state["question"]
print(question)
source = question_router.invoke({"question": question})
print(source)
print(source['datasource'])
if source['datasource'] == 'web_search':
print("---ROUTE QUESTION TO WEB SEARCH---")
return "websearch"
elif source['datasource'] == 'vectorstore':
print("---ROUTE QUESTION TO RAG---")
return "vectorstore"
这段代码定义了一个名为 route_question
的函数,其目的是根据问题的内容决定接下来的处理流程,是进行网络搜索还是使用向量存储库(用于检索文档或知识库查询)。以下是该函数的详细说明:
route_question(state)
这个函数用于决定如何处理当前的问题。
-
接收参数:接收一个包含当前图状态的字典
state
。 -
返回值:返回一个字符串,指示下一个应该调用的节点名称。
-
函数体:
- 首先,打印出
"---ROUTE QUESTION---"
以标识该函数正在执行。 - 从
state
中获取question
(问题)。 - 打印出获取到的问题内容。
- 使用
question_router.invoke
调用一个决策函数,传入包含问题的对象,以决定如何处理这个问题。 - 打印出从
question_router.invoke
返回的source
信息,以及source
中的datasource
字段。 - 根据
source['datasource']
的值,决定接下来的操作:- 如果
datasource
的值是'web_search'
,则打印出"---ROUTE QUESTION TO WEB SEARCH---"
,并返回字符串"websearch"
。这表明接下来应该进行网络搜索。 - 如果
datasource
的值是'vectorstore'
,则打印出"---ROUTE QUESTION TO RAG---"
,并返回字符串"vectorstore"
。这表明接下来应该使用向量存储库,可能涉及到使用检索增强生成(Retrieval-Augmented Generation, RAG)模型来生成答案。
- 如果
- 首先,打印出
这个函数是决策流程的一部分,根据问题的内容决定是通过网络搜索获取信息,还是从已有的文档或知识库中检索信息。返回的字符串将被用来确定下一个处理节点,从而驱动整个问答系统的工作流程。
此功能根据查询的性质确定用户问题的路由。它利用 来question_router评估问题是否应该路由到网络搜索或使用 RAG 模型进行处理。该决定基于question_router组件的输出。
def decide_to_generate(state):
"""
Determines whether to generate an answer, or add web search
Args:
state (dict): The current graph state
Returns:
str: Binary decision for next node to call
"""
print("---ASSESS GRADED DOCUMENTS---")
question = state["question"]
web_search = state["web_search"]
filtered_documents = state["documents"]
if web_search == "Yes":
# All documents have been filtered check_relevance
# We will re-generate a new query
print("---DECISION: ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, INCLUDE WEB SEARCH---")
return "websearch"
else:
# We have relevant documents, so generate answer
print("---DECISION: GENERATE---")
return "generate"
这段代码定义了一个名为 decide_to_generate
的函数,其目的是基于当前状态决定是生成答案还是添加网络搜索。以下是该函数的详细说明:
decide_to_generate(state)
这个函数用于决定在处理查询时是直接生成答案还是需要进行网络搜索。
-
接收参数:接收一个包含当前图状态的字典
state
。 -
返回值:返回一个字符串,指示下一个应该调用的节点名称。
-
函数体:
- 首先,打印出
"---ASSESS GRADED DOCUMENTS---"
以标识该函数正在执行。 - 从
state
中获取question
(问题)、web_search
(是否需要网络搜索的标志)和filtered_documents
(过滤后的文档列表)。 - 检查
web_search
的值:- 如果
web_search
的值是"Yes"
,则表示所有检索到的文档都被标记为与问题不相关。在这种情况下,函数打印出"---DECISION: ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, INCLUDE WEB SEARCH---"
,表明需要进行网络搜索,并返回字符串"websearch"
。 - 如果
web_search
的值不是"Yes"
,这意味着至少有一些文档与问题相关。因此,函数打印出"---DECISION: GENERATE---"
,表示可以利用这些相关文档生成答案,并返回字符串"generate"
。
- 如果
- 首先,打印出
这个函数是决策流程的一部分,它根据文档的相关性评分来决定是使用这些文档生成答案还是需要通过网络搜索来寻找更多信息。返回的字符串将被用来确定下一个处理节点,从而驱动整个问答系统的决策过程。
该函数决定是使用 RAG 模型生成答案,还是根据检索到的文档的相关性继续进行网络搜索。如果所有文档均被认为不相关,则该功能会选择启动网络搜索。否则,它将继续生成答案。
def grade_generation_v_documents_and_question(state):
"""
Determines whether the generation is grounded in the document and answers question.
Args:
state (dict): The current graph state
Returns:
str: Decision for next node to call
"""
print("---CHECK HALLUCINATIONS---")
question = state["question"]
documents = state["documents"]
generation = state["generation"]
score = hallucination_grader.invoke({"documents": documents, "generation": generation})
grade = score['score']
# Check hallucination
if grade == "yes":
print("---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---")
# Check question-answering
print("---GRADE GENERATION vs QUESTION---")
score = answer_grader.invoke({"question": question,"generation": generation})
grade = score['score']
if grade == "yes":
print("---DECISION: GENERATION ADDRESSES QUESTION---")
return "useful"
else:
print("---DECISION: GENERATION DOES NOT ADDRESS QUESTION---")
return "not useful"
else:
pprint("---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---")
return "not supported"
这段代码定义了一个名为 grade_generation_v_documents_and_question
的函数,其目的是评估生成的答案是否基于文档内容,并且是否真正回答了提出的问题。以下是该函数的详细说明:
grade_generation_v_documents_and_question(state)
这个函数用于评估生成的答案的质量。
-
接收参数:接收一个包含当前图状态的字典
state
。 -
返回值:返回一个字符串,指示对生成答案的评估结果和下一个处理步骤。
-
函数体:
- 打印出
"---CHECK HALLUCINATIONS---"
以标识该函数正在执行。 - 从
state
中获取question
(问题)、documents
(文档列表)和generation
(生成的答案)。 - 使用
hallucination_grader.invoke
调用一个评估函数,传入文档和生成答案,以判断生成答案是否基于文档内容(即没有产生幻觉,或生成与文档无关的信息)。 - 获取
hallucination_grader
返回的评分score
并检查score['score']
的值:- 如果评分为
"yes"
,则表示生成的答案是基于文档内容的。接下来,函数打印出"---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---"
。 - 然后,使用
answer_grader.invoke
调用另一个评估函数,传入问题和生成答案,以判断生成答案是否真正回答了问题。 - 如果
answer_grader
返回的评分为"yes"
,则表示生成的答案解决了问题。函数打印出"---DECISION: GENERATION ADDRESSES QUESTION---"
并返回"useful"
。 - 如果评分不是
"yes"
,则表示生成的答案没有解决提出的问题。函数打印出"---DECISION: GENERATION DOES NOT ADDRESS QUESTION---"
并返回"not useful"
。
- 如果评分为
- 如果
hallucination_grader
返回的评分不是"yes"
,则表示生成的答案不是基于文档内容的。函数打印出"---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---"
并返回"not supported"
。
- 打印出
这个函数是质量控制流程的一部分,它通过两个不同的评估步骤来确保生成的答案既有关联性又准确回答了问题。返回的字符串将被用来确定生成答案的质量和下一个处理节点,从而驱动整个问答系统的质量保证过程。
该函数评估生成的用户问题答案的事实依据和相关性。它利用 来hallucination_grader评估答案是否基于所提供的文档,并answer_grader确定它是否有效地解决了问题。根据评估,该函数决定答案是否有用。
from langgraph.graph import END, StateGraph
workflow = StateGraph(GraphState)
# Define the nodes
workflow.add_node("websearch", web_search) # web search
workflow.add_node("retrieve", retrieve) # retrieve
workflow.add_node("grade_documents", grade_documents) # grade documents
workflow.add_node("generate", generate) # generatae
# Build graph
workflow.set_conditional_entry_point(
route_question,
{
"websearch": "websearch",
"vectorstore": "retrieve",
},
)
workflow.add_edge("retrieve", "grade_documents")
workflow.add_conditional_edges(
"grade_documents",
decide_to_generate,
{
"websearch": "websearch",
"generate": "generate",
},
)
workflow.add_edge("websearch", "generate")
workflow.add_conditional_edges(
"generate",
grade_generation_v_documents_and_question,
{
"not supported": "generate",
"useful": END,
"not useful": "websearch",
},
)
这段代码使用了 langgraph.graph
模块中的 StateGraph
类来定义一个工作流,该工作流由一系列节点和边组成,用于处理查询并生成答案。代码中涉及的函数之前已经解释过,这里将说明如何将这些函数组合成一个工作流程。
StateGraph
初始化
workflow = StateGraph(GraphState)
初始化了一个状态图,GraphState
是一个用于存储和管理工作流状态的类。
添加节点
- 使用
workflow.add_node
方法向工作流中添加节点,每个节点对应一个处理步骤:"websearch"
: 对应web_search
函数,用于执行网络搜索。"retrieve"
: 对应retrieve
函数,用于从向量存储库检索文档。"grade_documents"
: 对应grade_documents
函数,用于评估检索到的文档与问题的关联性。"generate"
: 对应generate
函数,用于生成答案。
设置条件入口点
workflow.set_conditional_entry_point
方法定义了如何根据条件选择不同的入口点进入工作流。这里使用route_question
函数来决定是执行网络搜索还是从向量存储库检索文档:- 如果
route_question
返回"websearch"
,则进入"websearch"
节点。 - 如果返回
"vectorstore"
,则进入"retrieve"
节点。
- 如果
添加边
- 使用
workflow.add_edge
方法添加边,定义了节点之间的流程顺序:- 从
"retrieve"
节点到"grade_documents"
节点,表示先检索文档,然后评估文档。
- 从
添加条件边
- 使用
workflow.add_conditional_edges
方法添加基于条件的边,定义了基于某些条件从一个节点转移到另一个节点的逻辑:- 从
"grade_documents"
节点出发,根据decide_to_generate
函数的返回值,决定是执行"websearch"
还是"generate"
。 - 从
"websearch"
节点直接到"generate"
节点,表示网络搜索后直接生成答案。 - 从
"generate"
节点出发,根据grade_generation_v_documents_and_question
函数的返回值,决定是重新生成答案、结束工作流还是重新进行网络搜索。
- 从
这段代码构建了一个工作流,用于自动化地处理查询。它首先根据问题的类型选择是进行网络搜索还是文档检索,然后评估检索到的文档的相关性,基于相关文档生成答案,并进一步评估生成的答案的质量。根据答案的质量,工作流可能会结束、重新生成答案或重新进行网络搜索。这样的设计允许系统灵活地处理不同类型的查询,并确保生成的答案既有关联性又准确。
在本节中,workflow构建了一个 Langchain 图 ( ) 来编排操作序列。代表不同任务(例如文档检索、评分、答案生成和网络搜索)的节点被添加到图中。条件边被定义为处理路由决策并根据当前状态指导执行流程
try:
# Compile
app = workflow.compile()
# Test
from pprint import pprint
inputs = {"question": "Who is bedy kharisma?"}
for output in app.stream(inputs):
for key, value in output.items():
pprint(f"Finished running: {key}:")
pprint(value["generation"])
except Exception as e:
# Handle the error
print("An error occurred:", e)
Langchain 图被编译成一个功能应用程序 ( app),然后使用示例输入进行测试。该图通过其定义的节点和边处理输入,执行指定的任务并产生输出。执行过程中遇到的任何错误都会得到妥善处理,确保稳健性和可靠性。
这种全面的分解提供了对 Langchain 框架复杂工作原理的详细了解,展示了其在处理复杂的自然语言处理任务方面的多功能性和强大功能。通过利用 Langchain 的功能,开发人员可以释放新的可能性并彻底改变我们与文本数据交互的方式。
完整的 python 笔记本文件可以在这里下载
# %%
#install modules
!pip install ollama langchain beautifulsoup4 chromadb gradio unstructured langchain-nomic langchain_community tiktoken langchainhub langgraph tavily-python gpt4all -q
!pip install "unstructured[all-docs]" -q
!ollama pull llama3
!ollama pull nomic-embed-text
# %%
# Importing libraries
import os
import bs4
import getpass
import ollama
from typing import List
from typing_extensions import TypedDict
from langchain import hub
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import (
WebBaseLoader,
UnstructuredPDFLoader,
OnlinePDFLoader,
UnstructuredFileLoader,
PyPDFDirectoryLoader,
)
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import OllamaEmbeddings, GPT4AllEmbeddings
from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain.prompts import PromptTemplate, ChatPromptTemplate
from langchain_community.chat_models import ChatOllama
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain_community.tools.tavily_search import TavilySearchResults
# %%
#Options
local_llm = 'llama3'
llm = ChatOllama(model=local_llm, format="json", temperature=0)
#embeddings
#embeddings = OllamaEmbeddings(model="nomic-embed-text")
embeddings = GPT4AllEmbeddings()
# %%
##sources
#url
urls = [
"https://lilianweng.github.io/posts/2023-06-23-agent/",
"https://lilianweng.github.io/posts/2023-03-15-prompt-engineering/",
"https://lilianweng.github.io/posts/2023-10-25-adv-attack-llm/",
]
docs = [WebBaseLoader(url).load() for url in urls]
docs_list = [item for sublist in docs for item in sublist]
#pdf
loader = PyPDFDirectoryLoader("C://Users//ASUS//Downloads//sources//")
data = loader.load()
docs_list.extend(data)
#splitter
text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
chunk_size=1000, chunk_overlap=200
)
doc_splits = text_splitter.split_documents(docs_list)
# Add to vectorDB
vectorstore = Chroma.from_documents(
documents=doc_splits,
collection_name="rag-chroma",
embedding=embeddings,
)
retriever = vectorstore.as_retriever()
# %%
### Retrieval Grader
prompt = PromptTemplate(
template="""<|begin_of_text|><|start_header_id|>system<|end_header_id|> You are a grader assessing relevance
of a retrieved document to a user question. If the document contains keywords related to the user question,
grade it as relevant. It does not need to be a stringent test. The goal is to filter out erroneous retrievals. \n
Give a binary score 'yes' or 'no' score to indicate whether the document is relevant to the question. \n
Provide the binary score as a JSON with a single key 'score' and no premable or explaination.
<|eot_id|><|start_header_id|>user<|end_header_id|>
Here is the retrieved document: \n\n {document} \n\n
Here is the user question: {question} \n <|eot_id|><|start_header_id|>assistant<|end_header_id|>
""",
input_variables=["question", "document"],
)
retrieval_grader = prompt | llm | JsonOutputParser()
# %%
### Generate
prompt = PromptTemplate(
template="""<|begin_of_text|><|start_header_id|>system<|end_header_id|> 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 <|eot_id|><|start_header_id|>user<|end_header_id|>
Question: {question}
Context: {context}
Answer: <|eot_id|><|start_header_id|>assistant<|end_header_id|>""",
input_variables=["question", "document"],
)
# Post-processing
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
# Chain
rag_chain = prompt | llm | StrOutputParser()
# %%
### Hallucination Grader
prompt = PromptTemplate(
template=""" <|begin_of_text|><|start_header_id|>system<|end_header_id|> You are a grader assessing whether
an answer is grounded in / supported by a set of facts. Give a binary score 'yes' or 'no' score to indicate
whether the answer is grounded in / supported by a set of facts. Provide the binary score as a JSON with a
single key 'score' and no preamble or explanation. <|eot_id|><|start_header_id|>user<|end_header_id|>
Here are the facts:
\n ------- \n
{documents}
\n ------- \n
Here is the answer: {generation} <|eot_id|><|start_header_id|>assistant<|end_header_id|>""",
input_variables=["generation", "documents"],
)
hallucination_grader = prompt | llm | JsonOutputParser()
# %%
### Answer Grader
prompt = PromptTemplate(
template="""<|begin_of_text|><|start_header_id|>system<|end_header_id|> You are a grader assessing whether an
answer is useful to resolve a question. Give a binary score 'yes' or 'no' to indicate whether the answer is
useful to resolve a question. Provide the binary score as a JSON with a single key 'score' and no preamble or explanation.
<|eot_id|><|start_header_id|>user<|end_header_id|> Here is the answer:
\n ------- \n
{generation}
\n ------- \n
Here is the question: {question} <|eot_id|><|start_header_id|>assistant<|end_header_id|>""",
input_variables=["generation", "question"],
)
answer_grader = prompt | llm | JsonOutputParser()
# %%
### Router
prompt = PromptTemplate(
template="""<|begin_of_text|><|start_header_id|>system<|end_header_id|>
You excel in directing user inquiries either to a vector store or a web search.
For queries related to documents within the vector store, prioritize utilizing the vector store.
There's no need to strictly match keywords in the question to topics within the vector store.
If the question isn't covered by the vector store's content, resort to a web search.
Provide a binary decision, 'web_search' or 'vectorstore', depending on the nature of the question.
Return the a JSON with a single key 'datasource' and
no premable or explaination. Question to route: {question} <|eot_id|><|start_header_id|>assistant<|end_header_id|>""",
input_variables=["question"],
)
question_router = prompt | llm | JsonOutputParser()
# %%
### Search
os.environ["TAVILY_API_KEY"] = "tvly-xxxx"
web_search_tool = TavilySearchResults(k=3)
# %%
### State
class GraphState(TypedDict):
"""
Represents the state of our graph.
Attributes:
question: question
generation: LLM generation
web_search: whether to add search
documents: list of documents
"""
question : str
generation : str
web_search : str
documents : List[str]
from langchain.schema import Document
### Nodes
def retrieve(state):
"""
Retrieve documents from vectorstore
Args:
state (dict): The current graph state
Returns:
state (dict): New key added to state, documents, that contains retrieved documents
"""
print("---RETRIEVE---")
question = state["question"]
# Retrieval
documents = retriever.invoke(question)
return {"documents": documents, "question": question}
def generate(state):
"""
Generate answer using RAG on retrieved documents
Args:
state (dict): The current graph state
Returns:
state (dict): New key added to state, generation, that contains LLM generation
"""
print("---GENERATE---")
question = state["question"]
documents = state["documents"]
# RAG generation
generation = rag_chain.invoke({"context": documents, "question": question})
return {"documents": documents, "question": question, "generation": generation}
def grade_documents(state):
"""
Determines whether the retrieved documents are relevant to the question
If any document is not relevant, we will set a flag to run web search
Args:
state (dict): The current graph state
Returns:
state (dict): Filtered out irrelevant documents and updated web_search state
"""
print("---CHECK DOCUMENT RELEVANCE TO QUESTION---")
question = state["question"]
documents = state["documents"]
# Score each doc
filtered_docs = []
web_search = "No"
for d in documents:
score = retrieval_grader.invoke({"question": question, "document": d.page_content})
grade = score['score']
# Document relevant
if grade.lower() == "yes":
print("---GRADE: DOCUMENT RELEVANT---")
filtered_docs.append(d)
# Document not relevant
else:
print("---GRADE: DOCUMENT NOT RELEVANT---")
# We do not include the document in filtered_docs
# We set a flag to indicate that we want to run web search
web_search = "Yes"
continue
return {"documents": filtered_docs, "question": question, "web_search": web_search}
def web_search(state):
"""
Web search based based on the question
Args:
state (dict): The current graph state
Returns:
state (dict): Appended web results to documents
"""
print("---WEB SEARCH---")
question = state["question"]
documents = state["documents"]
# Web search
docs = web_search_tool.invoke({"query": question})
web_results = "\n".join([d["content"] for d in docs])
web_results = Document(page_content=web_results)
if documents is not None:
documents.append(web_results)
else:
documents = [web_results]
return {"documents": documents, "question": question}
### Conditional edge
def route_question(state):
"""
Route question to web search or RAG.
Args:
state (dict): The current graph state
Returns:
str: Next node to call
"""
print("---ROUTE QUESTION---")
question = state["question"]
print(question)
source = question_router.invoke({"question": question})
print(source)
print(source['datasource'])
if source['datasource'] == 'web_search':
print("---ROUTE QUESTION TO WEB SEARCH---")
return "websearch"
elif source['datasource'] == 'vectorstore':
print("---ROUTE QUESTION TO RAG---")
return "vectorstore"
def decide_to_generate(state):
"""
Determines whether to generate an answer, or add web search
Args:
state (dict): The current graph state
Returns:
str: Binary decision for next node to call
"""
print("---ASSESS GRADED DOCUMENTS---")
question = state["question"]
web_search = state["web_search"]
filtered_documents = state["documents"]
if web_search == "Yes":
# All documents have been filtered check_relevance
# We will re-generate a new query
print("---DECISION: ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, INCLUDE WEB SEARCH---")
return "websearch"
else:
# We have relevant documents, so generate answer
print("---DECISION: GENERATE---")
return "generate"
### Conditional edge
def grade_generation_v_documents_and_question(state):
"""
Determines whether the generation is grounded in the document and answers question.
Args:
state (dict): The current graph state
Returns:
str: Decision for next node to call
"""
print("---CHECK HALLUCINATIONS---")
question = state["question"]
documents = state["documents"]
generation = state["generation"]
score = hallucination_grader.invoke({"documents": documents, "generation": generation})
grade = score['score']
# Check hallucination
if grade == "yes":
print("---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---")
# Check question-answering
print("---GRADE GENERATION vs QUESTION---")
score = answer_grader.invoke({"question": question,"generation": generation})
grade = score['score']
if grade == "yes":
print("---DECISION: GENERATION ADDRESSES QUESTION---")
return "useful"
else:
print("---DECISION: GENERATION DOES NOT ADDRESS QUESTION---")
return "not useful"
else:
pprint("---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---")
return "not supported"
from langgraph.graph import END, StateGraph
workflow = StateGraph(GraphState)
# Define the nodes
workflow.add_node("websearch", web_search) # web search
workflow.add_node("retrieve", retrieve) # retrieve
workflow.add_node("grade_documents", grade_documents) # grade documents
workflow.add_node("generate", generate) # generatae
# %%
# Build graph
workflow.set_conditional_entry_point(
route_question,
{
"websearch": "websearch",
"vectorstore": "retrieve",
},
)
workflow.add_edge("retrieve", "grade_documents")
workflow.add_conditional_edges(
"grade_documents",
decide_to_generate,
{
"websearch": "websearch",
"generate": "generate",
},
)
workflow.add_edge("websearch", "generate")
workflow.add_conditional_edges(
"generate",
grade_generation_v_documents_and_question,
{
"not supported": "generate",
"useful": END,
"not useful": "websearch",
},
)
# %%
try:
# Compile
app = workflow.compile()
# Test
from pprint import pprint
inputs = {"question": "Who is bedy kharisma?"}
for output in app.stream(inputs):
for key, value in output.items():
pprint(f"Finished running: {key}:")
pprint(value["generation"])
except Exception as e:
# Handle the error
print("An error occurred:", e)
# %%
###END
运行结果为:
pulling manifest â ‹ pulling manifest â ™ pulling manifest â ¹ pulling manifest â ¸ pulling manifest â ¼ pulling manifest â ´ pulling manifest â ¦ pulling manifest â § pulling manifest â ‡ pulling manifest â � pulling manifest â ‹ pulling manifest â ¹ pulling manifest â ¸ pulling manifest â ¸ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ™ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¸ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¼ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¦ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¦ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‡ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‡ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â � pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¸ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¼ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ´ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ´ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¦ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â § pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‡ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â � pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¸ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¼ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¼ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ´ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â § pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â § pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â � pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â � pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ™ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¸ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¼ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ´ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â § pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‡ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â � pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â � pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ™ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¸ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¼ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ´ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¦ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â § pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‡ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â � pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ™ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¸ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¼ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¼ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ´ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¦ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â § pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â � pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â � pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ™ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¼ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ´ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ´ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â § pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‡ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â � pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â � pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ™ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ™ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¸ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¼ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¦ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â § pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‡ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‡ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‹ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ™ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¸ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¸ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ´ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ´ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¦ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ‡ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â � pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â � pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ™ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ™ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest â ¸ pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████� 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████� 12 KB
pulling 8ab4849b038c... 100% ▕████████████████� 254 B
pulling 577073ffcc6c... 100% ▕████████████████� 110 B
pulling ad1518640c43... 100% ▕████████████████� 483 B
verifying sha256 digest
writing manifest
removing any unused layers
success
pulling manifest â ™ pulling manifest â ¹ pulling manifest â ¸ pulling manifest â ¸ pulling manifest â ¼ pulling manifest â ´ pulling manifest â § pulling manifest â § pulling manifest â ‡ pulling manifest â � pulling manifest â ‹ pulling manifest â ™ pulling manifest â ¸ pulling manifest â ¸ pulling manifest â ¼ pulling manifest â ¦ pulling manifest â § pulling manifest â § pulling manifest
pulling 970aa74c0a90... 100% ▕████████████████� 274 MB
pulling c71d239df917... 100% ▕████████████████� 11 KB
pulling ce4a164fc046... 100% ▕████████████████� 17 B
pulling 31df23ea7daa... 100% ▕████████████████� 420 B
verifying sha256 digest â ‹ pulling manifest
pulling 970aa74c0a90... 100% ▕████████████████� 274 MB
pulling c71d239df917... 100% ▕████████████████� 11 KB
pulling ce4a164fc046... 100% ▕████████████████� 17 B
pulling 31df23ea7daa... 100% ▕████████████████� 420 B
verifying sha256 digest â ™ pulling manifest
pulling 970aa74c0a90... 100% ▕████████████████� 274 MB
pulling c71d239df917... 100% ▕████████████████� 11 KB
pulling ce4a164fc046... 100% ▕████████████████� 17 B
pulling 31df23ea7daa... 100% ▕████████████████� 420 B
verifying sha256 digest â ¹ pulling manifest
pulling 970aa74c0a90... 100% ▕████████████████� 274 MB
pulling c71d239df917... 100% ▕████████████████� 11 KB
pulling ce4a164fc046... 100% ▕████████████████� 17 B
pulling 31df23ea7daa... 100% ▕████████████████� 420 B
verifying sha256 digest â ¸ pulling manifest
pulling 970aa74c0a90... 100% ▕████████████████� 274 MB
pulling c71d239df917... 100% ▕████████████████� 11 KB
pulling ce4a164fc046... 100% ▕████████████████� 17 B
pulling 31df23ea7daa... 100% ▕████████████████� 420 B
verifying sha256 digest â ¼ pulling manifest
pulling 970aa74c0a90... 100% ▕████████████████� 274 MB
pulling c71d239df917... 100% ▕████████████████� 11 KB
pulling ce4a164fc046... 100% ▕████████████████� 17 B
pulling 31df23ea7daa... 100% ▕████████████████� 420 B
verifying sha256 digest â ´ pulling manifest
pulling 970aa74c0a90... 100% ▕████████████████� 274 MB
pulling c71d239df917... 100% ▕████████████████� 11 KB
pulling ce4a164fc046... 100% ▕████████████████� 17 B
pulling 31df23ea7daa... 100% ▕████████████████� 420 B
verifying sha256 digest
writing manifest
removing any unused layers
success
---ROUTE QUESTION---
Who is bedy kharisma?
{'datasource': 'vectorstore'}
vectorstore
---ROUTE QUESTION TO RAG---
---RETRIEVE---
'Finished running: retrieve:'
---CHECK DOCUMENT RELEVANCE TO QUESTION---
---GRADE: DOCUMENT NOT RELEVANT---
---GRADE: DOCUMENT NOT RELEVANT---
---GRADE: DOCUMENT NOT RELEVANT---
---GRADE: DOCUMENT NOT RELEVANT---
---ASSESS GRADED DOCUMENTS---
---DECISION: ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, INCLUDE WEB SEARCH---
'Finished running: grade_documents:'
---WEB SEARCH---
'Finished running: websearch:'
---GENERATE---
---CHECK HALLUCINATIONS---
---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---
---GRADE GENERATION vs QUESTION---
---DECISION: GENERATION ADDRESSES QUESTION---
'Finished running: generate:'
('{ "Bedy Kharisma is a young researcher in the Rolling Stock domain and '
'presently working as Manager at PT Industri Kereta Api (Persero), which is '
'the first integrated railway manufacturer in Southeast Asia." : 3 '
'} \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n'
'\n'
'\n'
'\n'
' \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n'
'\n'
'\n'
'\n'
' \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n'
'\n'
'\n'
'\n'
' \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n'
'\n'
'\n'
'\n'
' \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n'
'\n'
'\n'
'\n'
' \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n'
'\n'
'\n'
'\n'
' ')
运行结果显示了一个完整的工作流程,从路由问题到生成答案的过程。以下是每个步骤的说明:
-
路由问题 (
route_question
):- 打印
"---ROUTE QUESTION---"
,表明正在路由问题。 - 用户提出问题:“Who is bedy kharisma?”
- 调用
question_router.invoke
来确定数据源,结果是{'datasource': 'vectorstore'}
,表示应该使用向量存储库。 - 打印
"---ROUTE QUESTION TO RAG---"
,决定使用 RAG(Retrieval-Augmented Generation)模型。
- 打印
-
检索文档 (
retrieve
):- 打印
"---RETRIEVE---"
,开始检索文档。 - 检索器
retriever.invoke
被调用,检索与问题相关的文档。
- 打印
-
检查文档相关性 (
grade_documents
):- 打印
"---CHECK DOCUMENT RELEVANCE TO QUESTION---"
,开始检查文档的相关性。 - 四个
"---GRADE: DOCUMENT NOT RELEVANT---"
打印表明所有检索到的文档都被判断为与问题不相关。 - 由于没有相关文档,打印
"---DECISION: ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, INCLUDE WEB SEARCH---"
,决定进行网络搜索。
- 打印
-
网络搜索 (
websearch
):- 打印
"---WEB SEARCH---"
,开始网络搜索以寻找相关信息。
- 打印
-
生成答案 (
generate
):- 打印
"---GENERATE---"
,使用 RAG 模型基于检索到的信息生成答案。 - 调用
rag_chain.invoke
来生成答案。
- 打印
-
评估生成的答案 (
grade_generation_v_documents_and_question
):- 打印
"---CHECK HALLUCINATIONS---"
,检查生成的答案是否基于文档。 - 打印
"---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---"
,表明生成的答案是基于文档的。 - 打印
"---GRADE GENERATION vs QUESTION---"
,开始评估生成的答案是否回答了问题。 - 打印
"---DECISION: GENERATION ADDRESSES QUESTION---"
,表明生成的答案确实回答了问题。
- 打印
-
生成答案的输出:
- 最后,生成的答案被打印出来,包含了关于 Bedy Kharisma 的信息,他是一名年轻的研究员,在 Rolling Stock 领域工作,目前担任 PT Industri Kereta Api (Persero) 的经理,该公司是东南亚第一家集成铁路制造商。
这个工作流程展示了系统如何自动地处理一个查询,从路由问题、检索文档、评估文档相关性、网络搜索到生成和评估答案。最终,系统成功生成了一个回答用户问题的答案。
把握现在,投资未来 —— 加入大模型课程,一起开启知识与机遇的旅程!
大模型技术分享
《企业级生成式人工智能LLM大模型技术、算法及案例实战》线上高级研修讲座
模块一:Generative AI 原理本质、技术内核及工程实践周期详解
模块二:工业级 Prompting 技术内幕及端到端的基于LLM 的会议助理实战
模块三:三大 Llama 2 模型详解及实战构建安全可靠的智能对话系统
模块四:生产环境下 GenAI/LLMs 的五大核心问题及构建健壮的应用实战
模块五:大模型应用开发技术:Agentic-based 应用技术及案例实战
模块六:LLM 大模型微调及模型 Quantization 技术及案例实战
模块七:大模型高效微调 PEFT 算法、技术、流程及代码实战进阶
模块八:LLM 模型对齐技术、流程及进行文本Toxicity 分析实战
模块九:构建安全的 GenAI/LLMs 核心技术Red Teaming 解密实战
模块十:构建可信赖的企业私有安全大模型Responsible AI 实战
Llama3关键技术深度解析与构建Responsible AI、算法及开发落地实战
1、Llama开源模型家族大模型技术、工具和多模态详解:学员将深入了解Meta Llama 3的创新之处,比如其在语言模型技术上的突破,并学习到如何在Llama 3中构建trust and safety AI。他们将详细了解Llama 3的五大技术分支及工具,以及如何在AWS上实战Llama指令微调的案例。
2、解密Llama 3 Foundation Model模型结构特色技术及代码实现:深入了解Llama 3中的各种技术,比如Tiktokenizer、KV Cache、Grouped Multi-Query Attention等。通过项目二逐行剖析Llama 3的源码,加深对技术的理解。
3、解密Llama 3 Foundation Model模型结构核心技术及代码实现:SwiGLU Activation Function、FeedForward Block、Encoder Block等。通过项目三学习Llama 3的推理及Inferencing代码,加强对技术的实践理解。
4、基于LangGraph on Llama 3构建Responsible AI实战体验:通过项目四在Llama 3上实战基于LangGraph的Responsible AI项目。他们将了解到LangGraph的三大核心组件、运行机制和流程步骤,从而加强对Responsible AI的实践能力。
5、Llama模型家族构建技术构建安全可信赖企业级AI应用内幕详解:深入了解构建安全可靠的企业级AI应用所需的关键技术,比如Code Llama、Llama Guard等。项目五实战构建安全可靠的对话智能项目升级版,加强对安全性的实践理解。
6、Llama模型家族Fine-tuning技术与算法实战:学员将学习Fine-tuning技术与算法,比如Supervised Fine-Tuning(SFT)、Reward Model技术、PPO算法、DPO算法等。项目六动手实现PPO及DPO算法,加强对算法的理解和应用能力。
7、Llama模型家族基于AI反馈的强化学习技术解密:深入学习Llama模型家族基于AI反馈的强化学习技术,比如RLAIF和RLHF。项目七实战基于RLAIF的Constitutional AI。
8、Llama 3中的DPO原理、算法、组件及具体实现及算法进阶:学习Llama 3中结合使用PPO和DPO算法,剖析DPO的原理和工作机制,详细解析DPO中的关键算法组件,并通过综合项目八从零开始动手实现和测试DPO算法,同时课程将解密DPO进阶技术Iterative DPO及IPO算法。
9、Llama模型家族Safety设计与实现:在这个模块中,学员将学习Llama模型家族的Safety设计与实现,比如Safety in Pretraining、Safety Fine-Tuning等。构建安全可靠的GenAI/LLMs项目开发。
10、Llama 3构建可信赖的企业私有安全大模型Responsible AI系统:构建可信赖的企业私有安全大模型Responsible AI系统,掌握Llama 3的Constitutional AI、Red Teaming。
解码Sora架构、技术及应用
一、为何Sora通往AGI道路的里程碑?
1,探索从大规模语言模型(LLM)到大规模视觉模型(LVM)的关键转变,揭示其在实现通用人工智能(AGI)中的作用。
2,展示Visual Data和Text Data结合的成功案例,解析Sora在此过程中扮演的关键角色。
3,详细介绍Sora如何依据文本指令生成具有三维一致性(3D consistency)的视频内容。 4,解析Sora如何根据图像或视频生成高保真内容的技术路径。
5,探讨Sora在不同应用场景中的实践价值及其面临的挑战和局限性。
二、解码Sora架构原理
1,DiT (Diffusion Transformer)架构详解
2,DiT是如何帮助Sora实现Consistent、Realistic、Imaginative视频内容的?
3,探讨为何选用Transformer作为Diffusion的核心网络,而非技术如U-Net。
4,DiT的Patchification原理及流程,揭示其在处理视频和图像数据中的重要性。
5,Conditional Diffusion过程详解,及其在内容生成过程中的作用。
三、解码Sora关键技术解密
1,Sora如何利用Transformer和Diffusion技术理解物体间的互动,及其对模拟复杂互动场景的重要性。
2,为何说Space-time patches是Sora技术的核心,及其对视频生成能力的提升作用。
3,Spacetime latent patches详解,探讨其在视频压缩和生成中的关键角色。
4,Sora Simulator如何利用Space-time patches构建digital和physical世界,及其对模拟真实世界变化的能力。
5,Sora如何实现faithfully按照用户输入文本而生成内容,探讨背后的技术与创新。
6,Sora为何依据abstract concept而不是依据具体的pixels进行内容生成,及其对模型生成质量与多样性的影响。