使用langgraph 構建RAG 智能問答代理

RAG 智能問答代理:

? 支持用戶持續提問

? 根據模型判斷是否需要查資料

? 自動調用 PDF 檢索工具查找內容

? 自動引用內容回答

? 可以輸入 exit / quit 退出

下載需要的library

pip install langchain-google-genai
pip install langgraph
pip install langchain-community
pip install langchain-chroma
pip install pypdf
from typing import TypedDict, Annotated, Sequence
from langchain_core.messages import BaseMessage, ToolMessage, SystemMessage, HumanMessage, AIMessage
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_google_genai import GoogleGenerativeAIEmbeddings
from langchain_core.tools import tool
from operator import add as add_messages
from langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_chroma import Chroma
import os

🔹 from typing import TypedDict, Annotated, Sequence
這些是 Python 的標準類型提示工具(來自 typing 模塊):

TypedDict:允許你定義帶類型的字典。例如,用于聲明狀態數據結構。

Annotated:用于在類型提示中附加額外的元信息。常用于 Pydantic 或運行時類型校驗。

Sequence:表示有序的元素集合(比如 list 或 tuple),用于函數簽名中明確參數是一個有序結構。

🔹 from langchain_core.messages import BaseMessage, ToolMessage, SystemMessage, HumanMessage, AIMessage
這些是 LangChain Core 中的消息類型,用于構建對話流。常見于聊天模型的輸入/輸出:

BaseMessage:所有消息的基類。

HumanMessage:用戶輸入的信息(人類說的話)。

AIMessage:AI 生成的回復。

SystemMessage:系統預設信息,例如系統提示或指令。

ToolMessage:來自外部工具的消息(比如函數調用返回的結果)。

這些類型可幫助聊天模型更準確地理解不同來源的消息。

🔹 from langchain_google_genai import ChatGoogleGenerativeAI
這是用于接入 Google Gemini 模型(以前稱 PaLM)的 LangChain 接口:

ChatGoogleGenerativeAI:允許你使用 Google 的生成式 AI(例如 Gemini)進行聊天任務,支持多輪對話、函數調用、上下文管理等。

🔹 from langchain_google_genai import GoogleGenerativeAIEmbeddings
此類用于生成文本嵌入向量(Embeddings):

GoogleGenerativeAIEmbeddings:調用 Google Gemini 的嵌入接口,把文字轉為向量(常用于檢索、語義搜索、向量數據庫等)。

🔹 from langchain_core.tools import tool
tool 是一個 裝飾器,用于將一個普通函數轉換為可供語言模型調用的工具(tool)。

常用于實現帶函數調用能力的聊天模型(Function Calling 或 Tool Use)。

🔹 from operator import add as add_messages
Python 標準庫的 operator.add 函數用于執行 a + b 操作。

這里使用了 as add_messages 給它起了別名,暗示這個函數可能會被用于合并兩個消息列表

🔹 from langgraph.graph import StateGraph, START, END
這是 LangGraph 的核心模塊,用于構建有狀態的對話圖(Stateful Computation Graph):

StateGraph:LangGraph 的狀態圖結構,用于構建可追蹤的多步驟對話流程。

START, END:圖中的特殊節點,表示開始和結束點。通常用于定義流程的入口和出口。

LangGraph 是 LangChain 的實驗性擴展,可構建類似狀態機的復雜應用,例如代理、多工具工作流。

🔹 from langgraph.prebuilt import ToolNode
ToolNode 是一個預構建的節點類,表示圖中執行工具調用的節點。

它可自動處理工具輸入/輸出,在 LangGraph 中連接工具和對話狀態。

🔹 from langchain_community.document_loaders import PyPDFLoader
PyPDFLoader 是一個文檔加載器,用于從 PDF 文件中提取文本內容。

常用于文檔問答(RAG)場景,比如加載報告、合同、書籍等。

🔹 from langchain.text_splitter import RecursiveCharacterTextSplitter
RecursiveCharacterTextSplitter 是一種文本切分器,用于將文檔按段落或句子切成小塊(chunks),便于索引和嵌入。

支持遞歸回退策略,根據標點符號逐級切分,保持語義連貫。

🔹 from langchain_chroma import Chroma
Chroma 是向量數據庫的接口,支持將嵌入存入本地或遠程數據庫,并進行語義搜索。

它用于構建帶記憶或文檔檢索能力的聊天系統。

llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash", google_api_key=GOOGLE_API_KEY, temperature=0)

創建一個 低溫度設定的 Gemini 2.5 Flash 模型客戶端,用于多輪對話、函數調用(Tool Use)、文檔問答等任務。
temperature 控制模型生成的 隨機性/創造性。
模型在生成時將非常穩定、可預測、偏向選擇概率最高的輸出。非常適合用于確定性應用,如問答系統、數據處理、文檔提取等。

embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001",google_api_key=GOOGLE_API_KEY
)

創建一個 embeddings 實例,它使用 Google 的 Gemini 嵌入模型(embedding-001)將文本轉化為高維向量,用于語義檢索、向量數據庫存儲或文本相似度比較等下游任務。

pdf_path = "Stock_Market_Performance_2024.pdf"if not os.path.exists(pdf_path):raise FileNotFoundError(f"PDF file not found: {pdf_path}")

os.path.exists(pdf_path) 會檢查這個路徑下是否存在對應的文件或文件夾。
raise FileNotFoundError(…) 是 Python 的一種錯誤拋出機制。
當找不到文件時,主動拋出 FileNotFoundError 異常。

pdf_loader = PyPDFLoader(pdf_path)  # This loads the PDF# Checks if the PDF is there
try:pages = pdf_loader.load()print(f"PDF has been loaded and has {len(pages)} pages")
except Exception as e:print(f"Error loading PDF: {e}")raise

PyPDFLoader(pdf_path) 是 LangChain 提供的一個 PDF 文檔加載器類。
它會讀取 PDF 文件,為后續的問答系統或嵌入向量處理做準備。
但注意:這行代碼只是初始化了一個加載器對象,并沒有真正加載內容。真正加載發生在 .load() 方法中。

.load() 方法才是真正執行 讀取 PDF 文件內容 的操作。
它會返回一個按頁拆分的文本內容列表(List[Document]),每一頁是一個 LangChain Document 對象,包含內容和元信息(如頁碼)。

raise:再次拋出這個異常,終止程序運行(防止之后的代碼繼續運行在錯誤狀態下)。

創建一個「遞歸字符級文本切分器」,把文檔切成一段段長度不超過 1000 字符的 小塊文本(chunk),且相鄰的文本塊之間有 200 字符的重疊(overlap)。

# Chunking Process
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000,chunk_overlap=200
)

相鄰兩個 chunk 之間會有 200 個字符的重疊內容。
目的是:保持語義連續性,避免重要信息被截斷在邊界上。

把 PDF 文檔內容切分成小段(chunks),轉化為向量,然后存入本地的 Chroma 向量數據庫,用于后續的語義搜索或問答(RAG)應用。

pages_split = text_splitter.split_documents(pages)  # We now apply this to our pagespersist_directory = r"vec_db"
collection_name = "stock_market"# If our collection does not exist in the directory, we create using the os command
if not os.path.exists(persist_directory):os.makedirs(persist_directory)try:# Here, we actually create the chroma database using our embeddigns modelvectorstore = Chroma.from_documents(documents=pages_split,embedding=embeddings,persist_directory=persist_directory,collection_name=collection_name)print(f"Created ChromaDB vector store!")except Exception as e:print(f"Error setting up ChromaDB: {str(e)}")raise

pages 是前面通過 PyPDFLoader().load() 得到的文檔頁(每頁是一個 Document 對象)。

text_splitter.split_documents(pages) 會對每頁文本進行切分(chunking),生成多個小段文本,每段仍然是一個 Document 對象。

切分規則由 text_splitter 定義(如:1000 字,重疊 200 字)。

檢查本地磁盤上是否已經存在名為 “vec_db” 的文件夾。

如果不存在,則使用 os.makedirs() 創建它,防止寫入數據庫時報錯。

documents=pages_split:要寫入向量數據庫的 Document 列表(每個含文本和元數據)。

embedding=embeddings:使用哪個嵌入模型把文本轉成向量。你前面定義的是 Google Gemini 的嵌入模型。

persist_directory=persist_directory:Chroma 向量數據庫在磁盤上保存的文件夾路徑。

collection_name=collection_name:給這組向量一個邏輯名稱(一個“集合”)。

從 Chroma 向量數據庫中創建一個 Retriever(檢索器),用于后續問答(RAG)或聊天任務中從文檔中“找出最相關的內容”。

# Now we create our retriever
retriever = vectorstore.as_retriever(search_type="similarity",search_kwargs={"k": 5}  # K is the amount of chunks to return
)

創建一個“文檔檢索器(Retriever)”,每次輸入一個查詢問題時,它會返回與問題最相關的 5 個文檔塊(chunk),基于語義相似度。
vectorstore 是你剛剛用 Chroma 建好的本地向量數據庫,包含了你 PDF 文檔的所有嵌入向量。
.as_retriever() 是 LangChain 的方法,它會將向量數據庫對象封裝為一個可檢索的接口對象。
指定檢索方式為 “similarity”,即使用向量相似度搜索。
k=5 表示每次檢索返回 最相關的前 5 個文檔塊(chunk)。

將你之前創建的 retriever 封裝成一個可以被 LLM 代理(如 Gemini 或 LangChain Agent)調用的工具。工具的作用是:從 PDF 文檔中查找問題相關的段落內容,并返回結果給語言模型。

@tool
def retriever_tool(query: str) -> str:"""This tool searches and returns the information from the Stock Market Performance 2024 document."""docs = retriever.invoke(query)if not docs:return "I found no relevant information in the Stock Market Performance 2024 document."results = []for i, doc in enumerate(docs):results.append(f"Document {i+1}:\n{doc.page_content}")return "\n\n".join(results)

創建了一個名為 retriever_tool 的函數工具,用于在向量數據庫中檢索有關用戶查詢的問題的文檔段落(chunks),然后格式化成文本返回。

定義一個名為 retriever_tool 的函數

它接收一個字符串 query,表示用戶的查詢問題

返回一個字符串(即結果文本)

函數的文檔注釋(docstring)
這段文字會作為 工具的說明文檔,提供給代理模型了解工具用途

retriever.invoke(query) 會返回與你的問題語義最相近的文檔段落列表(通常是 5 個)

如果找不到相關段落(即檢索結果為空),直接返回一段提示信息。
這樣可以避免模型誤解為“有內容但沒展示”。

將所有結果用兩個換行符拼接成一個字符串

返回給 LLM,作為檢索器的最終輸出

將你定義的外部工具(retriever_tool)綁定到語言模型(llm)上,讓它具有調用工具的能力。

tools = [retriever_tool]llm = llm.bind_tools(tools)

創建一個名為 tools 的列表,里面包含一個你自定義的工具函數 retriever_tool。

retriever_tool 是你前面定義過并用 @tool 裝飾過的檢索工具,它可以從 PDF 文檔中找出與用戶問題相關的段落。

把你定義的工具 tools 綁定到語言模型對象 llm 上,使得它在生成回答時可以調用這些工具。

這使得模型可以在需要外部知識時 自動調用 retriever_tool 來輔助回答。

llm 是你使用的 ChatGoogleGenerativeAI(…)(Gemini 模型)對象。

.bind_tools(tools) 返回的是一個新模型對象,這個對象的能力比原始 llm 更強:

它能識別工具說明(docstring)

它知道哪些工具可以使用、怎么使用(參數是什么)

它會在遇到問題無法回答時自動決定是否調用工具

你可以把這個看作是“增強模型”:它除了聊天之外,還能主動調用外部函數。

構建一個LangGraph 智能代理(Agent)系統中的狀態管理與控制邏輯,這是 LangChain 中創建多步驟對話流程(如工具調用、LLM響應、條件跳轉等)時的關鍵組成部分。

class AgentState(TypedDict):messages: Annotated[Sequence[BaseMessage], add_messages]def should_continue(state: AgentState):"""Check if the last message contains tool calls."""result = state['messages'][-1]return hasattr(result, 'tool_calls') and len(result.tool_calls) > 0

AgentState 是什么?
這是一個使用 TypedDict 定義的 自定義狀態類型,用來在 LangGraph 工作流中傳遞和記錄會話狀態。

messages 是 AgentState 中的唯一字段,表示當前會話的消息歷史。

它是一個 消息對象的列表(Sequence[BaseMessage]),每個對象可以是:

HumanMessage:用戶輸入

AIMessage:模型響應

ToolMessage:工具返回結果

SystemMessage:系統指令

LangChain 中統一繼承自 BaseMessage。

這部分是 LangGraph 的特有寫法,表示:

這個 messages 字段在每一步節點運行時應該追加消息(而不是替換),由 add_messages 函數控制。

🧠 作用:
LangGraph 會根據 add_messages 邏輯自動將新的消息(如 LLM 的回答、工具調用結果)加入到 messages 這個狀態列表中,實現完整會話追蹤。

should_continue() 是做什么的?
它是一個用于流程控制(Conditional Edge)的函數,告訴 LangGraph:

“根據當前的 AgentState,我該不該繼續調用工具(tool)?”

獲取當前狀態中最后一條消息(即剛生成的 LLM 響應)

判斷:

最后一條消息是否有 tool_calls 屬性(即模型有沒有提出要調用某個工具)

并且這些工具調用的列表不為空

如果滿足這兩個條件,就返回 True,表示應該“繼續”,即跳轉到下一步工具調用節點。

否則就返回 False,表示無需再調用工具,可以終止或輸出結果。

什么是 system prompt?

在大多數對話式 AI 系統中(包括 GPT、Gemini、Claude 等),system prompt 是用來定義模型角色與行為規則的提示語。

它在每次對話開始時就被送入模型,作為“隱藏的第一句話”,影響模型后續所有行為。

在 LangChain 或 LangGraph 中,常通過 SystemMessage(content=system_prompt) 明確注入。

system_prompt = """
You are an intelligent AI assistant who answers questions about Stock Market Performance in 2024 based on the PDF document loaded into your knowledge base.
Use the retriever tool available to answer questions about the stock market performance data. You can make multiple calls if needed.
If you need to look up some information before asking a follow up question, you are allowed to do that!
Please always cite the specific parts of the documents you use in your answers.
"""

“你現在是一個股市問答專家,但不能靠記憶胡說八道。你只能通過一個叫 retriever_tool 的工具從我們給你的 PDF 文檔中查資料,才能回答問題。你可以多次查資料,而且請在回答時引用文檔的內容。”

構建一個具備“工具調用能力”的語言模型代理(LLM Agent)的關鍵組件,用于在 LangGraph 中調用語言模型并處理對話狀態。

tools_dict = {our_tool.name: our_tool for our_tool in tools}  # Creating a dictionary of our tools# LLM Agent
def call_llm(state: AgentState) -> AgentState:"""Function to call the LLM with the current state."""messages = list(state['messages'])messages = [SystemMessage(content=system_prompt)] + messagesmessage = llm.invoke(messages)return {'messages': [message]}

創建一個以工具名稱為 key、工具本身為 value 的字典,用于在后續流程中快速根據名稱定位工具。

定義了一個 LangGraph 中的 節點函數(node),在流程圖運行時,它會根據當前 state 調用語言模型并返回新結果。

從當前的對話狀態 AgentState 中提取消息列表

state[‘messages’] 是之前記錄的用戶提問 / 工具回復 / 模型回答等內容

把你之前定義的 system_prompt 加到消息列表的最前面

這一步至關重要:它確保每次模型調用都記住“我是誰、我該怎么答、要用 retriever_tool 查資料”

把你之前定義的 system_prompt 加到消息列表的最前面

這一步至關重要:它確保每次模型調用都記住“我是誰、我該怎么答、要用 retriever_tool 查資料”

把剛才模型生成的新 AIMessage 包裝成一個新的 AgentState 字典

LangGraph 中,所有節點函數都要返回類似這種結構(新狀態),以便下一步繼續推進

🧠 配合你之前的 add_messages 注釋,這個新消息會自動合并進原有消息列表中。

LangGraph 智能代理流程中的一個核心步驟:執行工具調用的動作節點。

# Retriever Agent
def take_action(state: AgentState) -> AgentState:"""Execute tool calls from the LLM's response."""tool_calls = state['messages'][-1].tool_calls# 取出對話歷史中的最后一條消息(即模型剛剛生成的 AIMessage)
.	# tool_calls 是該消息中模型請求調用的工具清單results = []for t in tool_calls:# 可能有多個工具請求(例如一個問句查兩段內容),所以逐一處理# t 表示一個單獨的工具調用print(f"Calling Tool: {t['name']} with query: {t['args'].get('query', 'No query provided')}")# 實時打印工具名稱和參數(便于調試)if not t['name'] in tools_dict:  # Checks if a valid tool is presentprint(f"\nTool: {t['name']} does not exist.")result = "Incorrect Tool Name, Please Retry and Select tool from List of Available tools."# 如果模型給出的工具名不合法(拼錯或沒注冊),返回錯誤提示# 避免運行未知或惡意工具名else:result = tools_dict[t['name']].invoke(t['args'].get('query', ''))print(f"Result length: {len(str(result))}")# 從 tools_dict 里取出對應的工具函數(如 retriever_tool)# 調用 .invoke() 方法執行工具(工具的實際邏輯如從 PDF 中查找內容)# 獲取結果(通常是字符串),打印結果長度# Appends the Tool Messageresults.append(ToolMessage(tool_call_id=t['id'], name=t['name'], content=str(result)))# LangChain 使用 ToolMessage 來表示“工具的返回結果”# 它需要:# tool_call_id: 和模型請求時的 ID 對應(用于追蹤)# name: 工具名# content: 工具運行的結果(必須是字符串)print("Tools Execution Complete. Back to the model!")return {'messages': results}

這個函數叫 take_action,它的作用是:

從上一步模型生成的響應中提取所有工具調用(tool_calls),逐個執行對應工具函數,并把結果封裝成 ToolMessage 發送回模型。

用戶提問 → LLM 判斷是否需要工具 → 如果需要 → 調用工具 → 再回到 LLM → 最終回答。

graph = StateGraph(AgentState)
graph.add_node("llm", call_llm)
graph.add_node("retriever_agent", take_action)graph.add_conditional_edges("llm",should_continue,{True: "retriever_agent", False: END}
)
graph.add_edge("retriever_agent", "llm")
graph.set_entry_point("llm")
rag_agent = graph.compile()

創建一個新的 LangGraph 對話流程圖,名為 graph
注冊兩個節點函數(處理流程的步驟):

“llm”:使用語言模型(如 Gemini 2.5)生成回復或提出工具調用請求 → 對應函數 call_llm

“retriever_agent”:真正執行工具調用 → 對應函數 take_action

執行完 “llm” 節點后

使用 should_continue() 判斷模型返回是否包含工具調用(tool_calls)

如果是:

跳轉到 “retriever_agent” 節點 → 實際調用工具

如果否:

直接終止(END)→ 模型回答完畢

一旦工具調用完畢,工具節點 retriever_agent 會輸出 ToolMessage 到狀態中

然后再次執行 “llm” 節點,讓模型根據工具返回結果繼續回答或再發起下一輪調用

告訴 LangGraph:流程從 “llm” 節點開始(即用戶提問后,先調用語言模型)

     ┌────────────┐│   llm      │ ?─────────────┐└────┬───────┘               ││                       │should_continue()              ││         │                 │Yes       No                 │↓         ↓                ▲
┌────────────┐  └───────? END   │
│retriever_agent│               │
└──────┬───────┘                ││                        │└────────?───────────────┘

RAG 智能問答代理的主程序入口,以命令行(終端)方式運行,實現一個可以連續提問、基于 PDF 自動查資料、調用工具回答的智能問答助手。

print("\n=== RAG AGENT===")while True:user_input = input("\nWhat is your question: ")if user_input.lower() in ['exit', 'quit']:breakmessages = [HumanMessage(content=user_input)]  # converts back to a HumanMessage typeresult = rag_agent.invoke({"messages": messages})print("\n=== ANSWER ===")print(result['messages'][-1].content)

進入一個無限循環,等待用戶在命令行輸入問題

input() 是 Python 的標準輸入函數

每次輸入的內容都會被作為提問交給智能代理

如果用戶輸入了 exit 或 quit(不區分大小寫),就退出循環,結束程序

是一種常見的 CLI 退出機制

將用戶輸入內容包裝成 HumanMessage 對象

這是 LangChain 中對話格式的標準寫法,便于與模型/工具交互

messages 是一個 list,因為智能代理是多輪對話系統(可以支持多條消息歷史)

你在前面已經構建并 compile() 出了一個圖形化代理:rag_agent

.invoke() 方法會觸發整個 LangGraph 流程,包括:

調用語言模型(llm 節點)

判斷是否需要工具(should_continue)

如果需要,調用工具(retriever_agent 節點)

工具返回結果后,再次讓模型生成最終回答

輸出 LangGraph 最終執行結果中的最后一條消息(通常是 AI 的回答)

result[‘messages’] 是整個狀態流中的歷史消息列表

[-1] 表示最后一條,通常是模型的回答 AIMessage

User input (What happened in Q2 2024?)[HumanMessage(content=user_input)]↓
rag_agent.invoke(...)  → 調用 LangGraph 圖↓
[llm](需要工具?)[retriever_agent][llm]↓
模型綜合結果回答↓
輸出 ANSWER
=== RAG AGENT===What is your question: how was the SMP500 performing in 2024?
Calling Tool: retriever_tool with query: S&P 500 performance in 2024
Result length: 4385
Tools Execution Complete. Back to the model!=== ANSWER ===
The S&P 500 index had a remarkably strong performance in 2024, delivering roughly a 25% total return (around +23% in price terms). This marked the second consecutive year of over 20% returns for the S&P 500, a feat not seen since the late 1990s. The gains were disproportionately driven by mega-cap technology stocks, particularly the "Magnificent 7" companies, which accounted for over half (about 54%) of the S&P 500's total return for the year.(Source: Document 1, Document 4, Document 5)What is your question: How did OpenAI perform in 2024?
Calling Tool: retriever_tool with query: OpenAI performance 2024
Result length: 4078
Tools Execution Complete. Back to the model!=== ANSWER ===
I am sorry, but I cannot provide information on OpenAI's performance in 2024. The provided documents discuss the overall U.S. stock market performance, highlighting the strong performance of mega-cap technology stocks and companies benefiting from AI adoption, such as Nvidia, Netflix, and Alphabet (Google). However, OpenAI is not mentioned in the provided text.What is your question: exit

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/88653.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/88653.shtml
英文地址,請注明出處:http://en.pswp.cn/web/88653.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

零基礎搭建監控系統:Grafana+InfluxDB 保姆級教程,5分鐘可視化服務器性能!?

??你是否遇到過這些問題???服務器突然卡頓,卻找不到性能瓶頸需要手動查看日志,無法實時監控數據運維報表全靠截圖拼接,領導直呼“太原始”?今天教你用GrafanaInfluxDB構建企業級監控系統,從此告別“盲人摸象”式運…

Java中的wait和notify、Condition接口的使用

Java中的wait和notify機制基礎概念在Java中,wait()和notify()是Object類的原生方法,用于實現線程間的協作:wait()使當前線程釋放對象鎖并進入等待狀態必須在synchronized代碼塊內調用語法:obj.wait() 或 obj.wait(long timeout)線…

【Modern C++ Part9】Prefer-alias-declarations-to-typedefs

條款9&#xff1a;優先使用聲明別名而不是typedef 我有信心說&#xff0c;大家都同意使用STL容器是個好的想法&#xff0c;并且我希望&#xff0c;條款18可以說服你使用std::unique_ptr也是個好想法&#xff0c;但是我想絕對我們中間沒有人喜歡寫像這樣std::unique_ptr<std:…

STM32第二十一天定時器TIM

1 定時器基礎知識a:上來說就是用來定時的機器&#xff0c;是存在于STM32單片機中的一個外設。STM32總共有8個定時器&#xff0c;分別是2個高級定時器(TIM1、TIM8)&#xff0c;4個通用定時器 (TIM2、TIM3、TIM4、TIM5) 和2個基本定時器 (TIM6、TIM7)&#xff0c;如下圖所示&…

鼎捷T100程序開發:校驗程序詳解

校驗程序概述 T100系統校驗程序需要確保系統數據的準確性、完整性和一致性&#xff0c;相當于企業信息系統的"健康體檢醫生"。它通過預設規則掃描系統數據&#xff0c;識別異常和錯誤&#xff0c;確保業務運行可靠。通過持續完善的校驗機制&#xff0c;企業能夠構建數…

BaseDao 通用查詢方法設計與實現

BaseDao 通用查詢方法設計與實現 一、通用查詢方法設計思路 1. 核心查詢功能矩陣查詢類型方法名功能說明復雜度主鍵查詢findById()根據主鍵獲取單個實體?全量查詢findAll()獲取全部實體?條件查詢findByCondition()動態條件查詢???分頁查詢findPage()分頁結果集????排序…

llama.cpp gguf主要量化方法

量化是一種通過降低模型參數的表示精度來減少模型的大小和計算存儲需求的方法&#xff0c;如把單精度fp32轉化為int8來減少存儲和計算成本。 常見的是線性量化&#xff0c;公式 r S(q-Z)&#xff0c;將實數值r映射為量化的整數值q&#xff0c;其中縮放因子S和零點Z根據參數分…

汽車級MCU選型新方向:eVTOL垂槳控制監控芯片的替代選型技術分析

摘要&#xff1a;隨著eVTOL&#xff08;電動垂直起降航空器&#xff09;領域的蓬勃發展&#xff0c;對于高性能、高可靠性的垂槳控制監控芯片的需求日益迫切。本文旨在深入探討汽車級MCU&#xff08;微控制單元&#xff09;在這一新興領域的應用潛力&#xff0c;以國科安芯推出…

Deepoc具身智能大模型:送餐機器人如何學會“讀心術”

Deepoc具身智能大模型&#xff1a;送餐機器人如何學會“讀心術”深夜十點的商場火鍋店&#xff0c;一臺銀色機器人正穿越喧鬧的人群。當它感知到奔跑的兒童突然變向&#xff0c;驅動輪立即反向微調0.3度&#xff1b;托盤上的牛油鍋底因顧客推椅產生晃動&#xff0c;平衡系統瞬間…

學習設計模式《十七》——狀態模式

一、基礎概念 狀態模式的本質是【根據狀態來分離和選擇行為】。 狀態模式的定義&#xff1a;允許一個對象在其內部狀態改變時改變它的行為&#xff1b;對象看起來似乎修改了它的類。 認識狀態模式序號認識狀態模式說明1狀態和行為通常指的是對象實例的屬性的值&#xff1b;而行…

python的婚紗影樓管理系統

前端開發框架:vue.js 數據庫 mysql 版本不限 后端語言框架支持&#xff1a; 1 java(SSM/springboot)-idea/eclipse 2.NodejsVue.js -vscode 3.python(flask/django)–pycharm/vscode 4.php(thinkphp/laravel)-hbuilderx 數據庫工具&#xff1a;Navicat/SQLyog等都可以 隨著婚紗…

濾波電路Multisim電路仿真實驗匯總——硬件工程師筆記

目錄 1 濾波電路基礎知識 1.1 濾波電路的分類 1.1.1 按頻率選擇性分類 1.1.2 按實現方式分類 1.2 濾波電路的設計 1.2.1 確定濾波器類型 1.2.2 計算截止頻率 1.2.3 選擇濾波階數 1.2.4 考慮元件參數 1.2.5 仿真驗證 1.3 濾波電路的應用 1.3.1 電源濾波 1.3.2 音頻…

C++隨機打亂函數:簡化源碼與原理深度剖析

文章目錄一、Fisher-Yates洗牌算法核心原理二、std::random_shuffle簡化實現與缺陷分析簡化源碼&#xff08;核心邏輯&#xff09;原理層面的致命缺陷三、std::shuffle的現代改進與實現簡化源碼&#xff08;核心邏輯&#xff09;原理層面的關鍵改進四、隨機數生成器工作原理URB…

DBeaver連接MySQL8.0報錯Public Key Retrieval is not allowed

DBeaver 鏈接本地mysql8.0服務報錯Public Key Retrieval is not allowed為什么會出現這個錯誤&#xff1f;MySQL 8.0 默認使用新的認證插件&#xff1a;caching_sha2_password某些客戶端&#xff08;比如老版本的 JDBC 驅動或配置不當的 DBeaver&#xff09;在連接時&#xff0…

SpringBoot系列—統一功能處理(攔截器)

上篇文章&#xff1a; SpringBoot系列—MyBatis-plushttps://blog.csdn.net/sniper_fandc/article/details/148979284?fromshareblogdetail&sharetypeblogdetail&sharerId148979284&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link 目錄 1 攔…

《匯編語言:基于X86處理器》第7章 整數運算(3)

本章將介紹匯編語言最大的優勢之一:基本的二進制移位和循環移位技術。實際上&#xff0c;位操作是計算機圖形學、數據加密和硬件控制的固有部分。實現位操作的指令是功能強大的工具&#xff0c;但是高級語言只能實現其中的一部分&#xff0c;并且由于高級語言要求與平臺無關&am…

應用筆記|數字化儀在醫學SS-OCT中的應用

引言近些年來&#xff0c;OCT&#xff08;光學相干斷層掃描&#xff0c;Optical Coherence Tomography&#xff09;作為一種非破壞性3D光學成像技術逐漸在醫學眼科設備中流行起來。OCT可提供實時一維深度或二維截面或三維立體的圖像&#xff0c;分辨率可達微米&#xff08;μm&…

Ubuntu 22.04與24.04 LTS版本對比分析及2025年使用建議

Ubuntu 22.04與24.04 LTS版本對比分析及2025年使用建議 在2025年的技術環境下&#xff0c;Ubuntu 22.04和24.04 LTS各有優勢&#xff0c;選擇哪一個取決于具體應用場景和用戶需求。經過對系統內核、桌面環境、軟件生態、生命周期支持等多方面因素的綜合分析&#xff0c;本報告將…

Linux進程的生命周期:狀態定義、轉換與特殊場景

前言 在Linux系統中&#xff0c;進程是資源分配和調度的基本單位&#xff0c;而進程狀態則是理解進程行為的關鍵。從運行中的任務&#xff08;TASK_RUNNING&#xff09;到僵尸進程&#xff08;EXIT_ZOMBIE&#xff09;&#xff0c;每個狀態都反映了進程在內核調度、資源等待或父…

神經網絡簡介

大腦的基本計算單位是神經元&#xff08;neuron&#xff09;。人類的神經系統中大約有860億個神經元&#xff0c;它們被大約10^14-10^15個突觸&#xff08;synapses&#xff09;連接起來。下面圖表的左邊展示了一個生物學的神經元&#xff0c;右邊展示了一個常用的數學模型。每…