百度文心一言開源大模型ERNIE-4.5-0.3B-PT深度測評

image-20250705103759629

號外號外!6月30號,百度文心一言官宣開源ERNIE 4.5大模型!!!

一收到這個消息,博主就立馬從GitCode拉了個模型,本地私有化部署體驗了一下,一個字,

鑒于絕大多數玩家的設備條件有限,博主選擇CPU就可以跑的 ERNIE-4.5-0.3B-PT 大模型,帶著大家一起部署體驗。

如果大家在部署的時候遇到問題,歡迎私信博主哈。

下面就跟著博主一起玩轉文心大模型吧~

文章目錄

  • 一、測評信息
  • 二、大模型介紹
    • 2.1. 文心大模型簡介
    • 2.2. ERNIE-4.5-0.3B-PT簡介
    • 2.3. GitCode簡介
  • 三、本地私有化部署
    • 3.1. 下載ERNIE-4.5-0.3B-PT大模型
    • 3.2. 測試GitCode的樣例腳本
    • 3.3. 開發一個Web聊天頁面
    • 3.4. 實時展示聊天內容
    • 3.5. 增加長期(上下文)記憶功能
    • 3.6. 接入本地知識庫
  • 四、基礎功能與性能測評
    • 4.1. 文本生成
    • 4.2. 數學計算
    • 4.3. 文本翻譯
    • 4.4. 限制回復
    • 4.5. 模糊指令
    • 4.6. 倫理安全
    • 4.7. 代碼生成
    • 4.8. 代碼解析
    • 4.9. 文本概括
    • 4.10. 邏輯推理
    • 4.11. 長期記憶
    • 4.12. 知識庫推理
    • 4.13. 總體評價
  • 五、批量測評
    • 5.1. 生活常識
    • 5.2. 數學計算
    • 5.3. 邏輯推理
    • 5.4. 總體評價
  • 六、對比測評
    • 6.1. 功能對比
    • 6.2. 性能對比
    • 6.3. 總體評價
  • 七、大模型應用案例
  • 八、總結

一、測評信息

  • 測評人:Want595
  • 測評日期2025年7月1日~7月8日
  • 測評環境
    • 操作系統:Windows 11
    • 硬件配置:CPU
    • 軟件環境:Python3.10+
    • 部署工具:Trae / PyCharm
  • 模型版本:ERNIE-4.5-0.3B-PT
  • 模型倉庫:GitCode
  • 部署方式:本地私有化部署
  • 測評思路:首先通過GitCode獲取大模型ERNIE-4.5-0.3B-PT,并使用PythonStreamlit搭建交互式聊天頁面,隨后從文本生成、數學計算、文本翻譯、倫理安全等12個維度系統評估模型表現,然后利用生活常識、數學計算、邏輯推理等600道選擇題評估模型的回復效果,此外,還將該模型與大模型Qwen3-0.6B進行對比,進一步評估模型的效果。最后結合模型優勢將該模型接入智能筆記系統,驗證了實際應用潛力。全文通過量化指標(如Token統計、延遲數據)和可視化案例,客觀展示了0.3B參數模型在CPU環境下的性價比,為輕量化部署提供了參考。

二、大模型介紹

2.1. 文心大模型簡介

直達鏈接:https://ai.gitcode.com/theme/1939325484087291906

文心是百度自主研發的產業級知識增強大模型,以創新性的知識增強技術為核心,從單模態大模型到跨模態、從通用基礎大模型到跨領域、跨行業持續創新突破,構建了模型層、工具與平臺層,大幅降低人工智能開發和應用門檻,加快人工智能大規模產業化進程并拓展人工智能技術邊界。

image-20250704225324234

2.2. ERNIE-4.5-0.3B-PT簡介

直達鏈接:https://gitcode.com/paddlepaddle/ERNIE-4.5-0.3B-PT

ERNIE-4.5-0.3B 是百度推出的0.36B參數輕量級語言大模型。基于PaddlePaddle框架,提供ERNIEKit微調工具和FastDeploy推理支持,兼容主流生態,適用于對話、創作等場景。開源協議為Apache 2.0

image-20250704233248811

2.3. GitCode簡介

直達鏈接:https://gitcode.com/

GitCode 是一個基于 Git 的代碼托管與協作平臺,支持代碼版本控制、項目管理及團隊協作功能。

文心大模型首發平臺就是GitCode

image-20250704233349779


三、本地私有化部署

跟著博主一起本地部署大模型ERNIE-4.5-0.3B-PT吧,比如開發一個Web聊天頁面、增加長期記憶功能、接入本地知識庫等!

3.1. 下載ERNIE-4.5-0.3B-PT大模型

  1. 進入GitCode的 ERNIE-4.5-0.3B-PT 項目頁面,單擊“模型使用”→“克隆”。

image-20250704135913117

  1. 復制命令git clone https://gitcode.com/paddlepaddle/ERNIE-4.5-0.3B-PT.git

image-20250704140011223

  1. 在本地打開git bash,輸入以下命令,將項目克隆到本地。
git lfs install
git clone https://gitcode.com/paddlepaddle/ERNIE-4.5-0.3B-PT.git

image-20250704140215432

  1. 查看項目文件。

image-20250704140301228

以下是文件的簡單介紹:

  • .gitattributes :配置 Git LFS(大文件存儲),指定哪些類型的文件使用 LFS 管理。
  • .msc :包含文件路徑和版本信息的二進制文件,可能用于文件版本管理。
  • .mv :記錄項目的版本號和創建時間。
  • LICENSE :Apache 2.0 開源許可證文件,規定了項目的使用、復制和分發條款。
  • README.md :項目說明文檔,介紹了 ERNIE-4.5-0.3B 模型的亮點、配置、快速使用方法等信息。
  • config.json :模型配置文件,定義了模型的架構、參數等信息。
  • configuration_ernie4_5.py :Python 代碼文件,定義了 ERNIE 4.5 模型的配置類。
  • generation_config.json :文本生成配置文件,包含采樣、溫度、懲罰項等生成參數。
  • modeling_ernie4_5.py :Python 代碼文件,實現了 ERNIE 4.5 模型的部分組件,如 RMS 歸一化、旋轉位置編碼等。
  • special_tokens_map.json :特殊標記映射文件,定義了模型使用的特殊標記,如開始標記、結束標記等。
  • tokenization_ernie4_5.py :Python 代碼文件,實現了 ERNIE 4.5 模型的分詞器。
  • tokenizer.model :SentencePiece 分詞模型文件,用于文本分詞。
  • tokenizer_config.json :分詞器配置文件,定義了分詞器的特殊標記、類名等信息。
  • added_tokens.json :新增標記的配置文件。
  • model.safetensors :模型權重文件。

3.2. 測試GitCode的樣例腳本

博主使用Trae進行本地部署測試,大家可以根據自己的需求,使用PyCharmVsCode等IDE。

博主先帶著大家測試一下ERNIE-4.5-0.3B-PT給出的樣例腳本。

  1. 打開Trae,新建一個項目,將模型文件放到該項目中。

image-20250706185252489

  1. 打開終端,使用conda命令創建虛擬環境。
conda create --name  ernie python=3.10
conda activate ernie
  1. 在終端執行以下命令,安裝依賴庫。
pip install transformers torch sentencepiece

image-20250704185711658

  1. 創建測試腳本ernie01.py,填入GitCode中的樣例代碼。

image-20250704141816008

  • 樣例代碼:
from transformers import AutoModelForCausalLM, AutoTokenizermodel_name = "ERNIE-4.5-0.3B-PT"		# 這里換成你的模型路徑# load the tokenizer and the model
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True)# prepare the model input
prompt = "Give me a short introduction to large language model."  # 向大模型提出的問題
messages = [{"role": "user", "content": prompt}
]
text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True
)
model_inputs = tokenizer([text], add_special_tokens=False, return_tensors="pt").to(model.device)# conduct text completion
generated_ids = model.generate(model_inputs.input_ids,max_new_tokens=1024
)
output_ids = generated_ids[0][len(model_inputs.input_ids[0]):].tolist()# decode the generated ids
generate_text = tokenizer.decode(output_ids, skip_special_tokens=True).strip("\n")
print("generate_text:", generate_text)

樣例代碼向大模型提出的問題是:Give me a short introduction to large language model.

  1. 運行樣例代碼,大模型的回復如下:

image-20250704153418181

如果你想問大模型其他問題,請修改代碼中的prompt。比如我將prompt修改為請概括一下ERNIE-4.5的優點。,大模型的回復如下:

image-20250704155955955

從回復內容可以看出,0.3B文心大模型的效果非常不錯!

3.3. 開發一個Web聊天頁面

每次在代碼中設置prompt,太麻煩啦!

不要擔心,接下來,博主將帶著大家開發一個簡單的聊天頁面。

  1. 在終端輸入以下命令,安裝streamlit庫。
pip install streamlit
  1. 新建腳本ernie02.py,填入以下代碼。
import streamlit as st
from transformers import AutoModelForCausalLM, AutoTokenizer# Initialize the model and tokenizer
@st.cache_resource
def load_model():model_name = "ERNIE-4.5-0.3B-PT"tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True)return tokenizer, modeltokenizer, model = load_model()# Function to generate response
def generate_response(prompt):messages = [{"role": "user", "content": prompt}]text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True)model_inputs = tokenizer([text], add_special_tokens=False, return_tensors="pt").to(model.device)generated_ids = model.generate(model_inputs.input_ids,max_new_tokens=1024)output_ids = generated_ids[0][len(model_inputs.input_ids[0]):].tolist()response = tokenizer.decode(output_ids, skip_special_tokens=True).strip("\n")return response# Streamlit UI
st.title("ERNIE-4.5 Chat")
st.write("By WJW")# Initialize chat history
if "messages" not in st.session_state:st.session_state.messages = []# Display chat messages from history
for message in st.session_state.messages:with st.chat_message(message["role"]):st.markdown(message["content"])# Accept user input
if prompt := st.chat_input("你想問點什么?"):# Add user message to chat historyst.session_state.messages.append({"role": "user", "content": prompt})# Display user message in chat message containerwith st.chat_message("user"):st.markdown(prompt)# Display assistant response in chat message containerwith st.chat_message("assistant"):message_placeholder = st.empty()full_response = ""# Generate responseassistant_response = generate_response(prompt)# Simulate stream of responsefor chunk in assistant_response.split():full_response += chunk + " "message_placeholder.markdown(full_response + "▌")message_placeholder.markdown(full_response)# Add assistant response to chat historyst.session_state.messages.append({"role": "assistant", "content": full_response})

這段代碼基于 ERNIE-4.5-0.3B-PT 模型和 Streamlit 框架實現了一個和大模型聊天的頁面,該聊天界面支持多輪對話,用戶輸入內容后,系統會將用戶消息和模型回復依次顯示在頁面上,并保存到聊天歷史中。

  1. 在終端運行命令streamlit run ernie02.py啟動程序,隨后在本地訪問http://localhost:8501,進入聊天頁面。

image-20250704162341207

你可以一直問它問題,快去試試吧!

3.4. 實時展示聊天內容

我們開發的聊天頁面存在一個小小的問題,就是用戶提出問題后,Web頁面需要等待大模型生成完整的回復內容,再一次性展示出來,大大降低了用戶的體驗感。下面跟著博主優化一下咱們的聊天頁面吧!

  1. 新建腳本ernie03.py,填入以下代碼。
import streamlit as st
from transformers import AutoModelForCausalLM, AutoTokenizer
from threading import Thread
from queue import Queue, Empty
import time
import platform# Initialize the model and tokenizer
@st.cache_resource
def load_model():model_name = "ERNIE-4.5-0.3B-PT"tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True)return tokenizer, modeltokenizer, model = load_model()class CustomStreamer:def __init__(self, queue):self.queue = queueself.first_token_time = Noneself.generation_start = time.perf_counter()self.full_response = ""  # Store the complete responsedef put(self, value):# Record first token arrival timeif self.first_token_time is None:self.first_token_time = time.perf_counter()# Decode the tokenstokens = value.cpu().numpy()text = tokenizer.decode(tokens[0], skip_special_tokens=True)# Clean prefixesfor prefix in ['User:', 'Assistant:']:if prefix in text:text = text.split(prefix, 1)[-1]cleaned_text = text.strip()self.full_response += cleaned_text  # Accumulate the full responseself.queue.put(cleaned_text)def end(self):self.queue.put(None)def get_first_token_latency(self):if self.first_token_time:return (self.first_token_time - self.generation_start) * 1000  # in msreturn 0def generate_response_stream(prompt, queue, max_tokens, temperature):generation_start = time.perf_counter()# Prepare inputsmessages = [{"role": "user", "content": prompt}]text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True)model_inputs = tokenizer([text], return_tensors="pt")prompt_tokens = len(model_inputs.input_ids[0])# Initialize streamerstreamer = CustomStreamer(queue)# Generate with monitoringgenerated_ids = model.generate(model_inputs.input_ids,max_new_tokens=max_tokens,temperature=temperature,streamer=streamer,do_sample=True if temperature > 0 else False)# Calculate metricsgeneration_end = time.perf_counter()elapsed_time = generation_end - generation_startcompletion_tokens = len(generated_ids[0]) - prompt_tokenstotal_tokens = prompt_tokens + completion_tokens# Print comprehensive reportprint('*'*40)print("🚀 性能分析")print(f"\n🔵 **Token統計**")print(f"- 輸入Token:{prompt_tokens}")print(f"- 輸出Token:{completion_tokens}")print(f"- 總Token:{total_tokens}")print(f"\n**🟢 時間指標(毫秒)**")print(f"- 首Token延遲:{streamer.get_first_token_latency():.2f}")print(f"- 總生成時間:{elapsed_time*1000:.2f}")print(f"- Token平均延遲:{(elapsed_time*1000)/completion_tokens if completion_tokens else 0:.2f}")print(f"\n**🟣 吞吐量**")print(f"- 生成速度:{completion_tokens/elapsed_time:.2f} tok/s")print(f"- 系統信息:{platform.processor()}")print(f"\n💬 完整回復:")full_response = tokenizer.decode(generated_ids[0], skip_special_tokens=True)print(full_response)print('*'*40)
# Streamlit UI
st.title("ERNIE-4.5 Chat")
st.write("By WJW")# Initialize chat
if "messages" not in st.session_state:st.session_state.messages = []# Display history
for message in st.session_state.messages:with st.chat_message(message["role"]):st.markdown(message["content"])# Sidebar controls
with st.sidebar:st.header("?? 模型配置")max_tokens = st.slider("最大生成長度", 100, 2048, 1024)temperature = st.slider("溫度系數", 0.1, 2.0, 1.0, 0.1)if st.button("🧹 清空對話"):st.session_state.messages = []st.rerun()# Chat input
if prompt := st.chat_input("請輸入您的問題..."):# Add user messagest.session_state.messages.append({"role": "user", "content": prompt})with st.chat_message("user"):st.markdown(prompt)# Generate responsewith st.chat_message("assistant"):placeholder = st.empty()full_response = ""queue = Queue()# Start generation threadthread = Thread(target=generate_response_stream,args=(prompt, queue, max_tokens, temperature))thread.start()# Stream outputwhile True:try:chunk = queue.get(timeout=0.1)if chunk is None:breakfull_response += chunkplaceholder.markdown(full_response + "▌")except Empty:continueplaceholder.markdown(full_response)thread.join()# Save to historyst.session_state.messages.append({"role": "assistant", "content": full_response})
  1. 在終端運行命令streamlit run ernie03.py啟動程序,然后訪問http://localhost:8501,進入聊天頁面。

image-20250705093116280

在這個聊天頁面,不僅實現了實時展現大模型的回復內容,還新增了模型配置清空對話按鈕,你可以設置模型的最大Tokens和溫度,也可以隨時清空對話內容。

3.5. 增加長期(上下文)記憶功能

我們可以給大模型增加一點能力,比如“長期記憶”能力,就是讓大模型記住我們之前的問題,這樣我們就可以基于之前的問題繼續向大模型提問啦。

  1. 新建腳本ernie04.py,填入以下代碼。
import os
import torch
import streamlit as st
from threading import Thread
from queue import Queue, Empty
import time
import platform
from transformers import AutoModelForCausalLM, AutoTokenizer
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_community.document_loaders import PyMuPDFLoader, UnstructuredMarkdownLoader, TextLoader, Docx2txtLoader
from langchain_huggingface import HuggingFaceEmbeddings# 初始化模型和分詞器
@st.cache_resource
def load_model():model_name = "./models/ERNIE-4.5-0.3B-PT"tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True)return tokenizer, modeltokenizer, model = load_model()class KnowledgeBase:def __init__(self):self.folder_path = './datas'self.persist_directory = './vectors'os.makedirs(self.folder_path, exist_ok=True)os.makedirs(self.persist_directory, exist_ok=True)self.embeddings = HuggingFaceEmbeddings(model_name="./models/paraphrase-multilingual-MiniLM-L12-v2")self.vectorstore = Noneself.ready = Falsedef init_knowledge_base(self):"""初始化知識庫系統"""try:# 獲取所有文檔路徑file_paths = []for root, dirs, files in os.walk(self.folder_path):for file in files:if file.lower().endswith(('.pdf', '.md', '.txt', '.docx', '.doc')):  # 添加Word文檔支持file_path = os.path.join(root, file)file_paths.append(file_path)if not file_paths:st.warning("知識庫目錄中沒有找到任何文檔")self.ready = Falsereturn False# 加載文檔documents = []for file_path in file_paths:try:file_type = file_path.lower().split('.')[-1]if file_type == 'pdf':loader = PyMuPDFLoader(file_path)elif file_type == 'md':loader = UnstructuredMarkdownLoader(file_path)elif file_type in ('docx', 'doc'):loader = Docx2txtLoader(file_path)  # 使用Docx2txtLoader處理Word文檔else:  # 默認為txt文件loader = TextLoader(file_path, encoding='utf-8')  # 明確指定編碼loaded_docs = loader.load()# 添加源文件信息到元數據for doc in loaded_docs:doc.metadata['source'] = file_pathdocuments.extend(loaded_docs)except Exception as e:st.warning(f"加載文檔 {file_path} 時出錯: {str(e)}")continueif not documents:st.error("沒有可用的文檔內容")self.ready = Falsereturn False# 分割文檔text_splitter = RecursiveCharacterTextSplitter(chunk_size=500,chunk_overlap=50)split_docs = text_splitter.split_documents(documents)# 創建向量存儲self.vectorstore = Chroma.from_documents(documents=split_docs,embedding=self.embeddings,persist_directory=self.persist_directory)self.ready = Truereturn Trueexcept Exception as e:st.error(f"初始化知識庫時出錯: {str(e)}")self.ready = Falsereturn Falsedef query(self, question, k=3):"""查詢知識庫"""if not self.ready:return None, Nonetry:docs = self.vectorstore.similarity_search(question, k=k)context = "\n\n".join([doc.page_content for doc in docs])sources = [doc.metadata.get('source', '未知') for doc in docs]return context, sourcesexcept Exception as e:st.error(f"查詢知識庫時出錯: {str(e)}")return None, Noneclass CustomStreamer:def __init__(self, queue):self.queue = queueself.first_token_time = Noneself.generation_start = time.perf_counter()self.full_response = ""self.is_first_chunk = Truedef put(self, value):if self.first_token_time is None:self.first_token_time = time.perf_counter()tokens = value.cpu().numpy()text = tokenizer.decode(tokens[0], skip_special_tokens=True)if self.is_first_chunk:assistant_idx = text.rfind("Assistant:")if assistant_idx >= 0:text = text[assistant_idx + len("Assistant:"):]self.is_first_chunk = Falsecleaned_text = text.strip()self.full_response += cleaned_textself.queue.put(cleaned_text)def end(self):self.queue.put(None)def get_first_token_latency(self):if self.first_token_time:return (self.first_token_time - self.generation_start) * 1000return 0def generate_response_stream(prompt, queue, max_tokens, temperature, history=None, kb_context=None):generation_start = time.perf_counter()# 準備輸入(包含可選的知識庫上下文)if kb_context:prompt = f"""基于以下知識庫信息回答問題:
{kb_context}問題: {prompt}"""if history:messages = history + [{"role": "user", "content": prompt}]else:messages = [{"role": "user", "content": prompt}]text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True)model_inputs = tokenizer([text], return_tensors="pt")prompt_tokens = len(model_inputs.input_ids[0])# 初始化流式處理器streamer = CustomStreamer(queue)# 生成響應generated_ids = model.generate(model_inputs.input_ids,max_new_tokens=max_tokens,temperature=temperature,streamer=streamer,do_sample=True if temperature > 0 else False)# 計算性能指標generation_end = time.perf_counter()elapsed_time = generation_end - generation_startcompletion_tokens = len(generated_ids[0]) - prompt_tokenstotal_tokens = prompt_tokens + completion_tokens# 打印性能報告print('*'*40)print("🚀 性能分析")print(f"\n🔵 **Token統計**")print(f"- 輸入Token: {prompt_tokens}")print(f"- 輸出Token: {completion_tokens}")print(f"- 總Token: {total_tokens}")print(f"\n**🟢 時間指標(毫秒)**")print(f"- 首Token延遲: {streamer.get_first_token_latency():.2f}")print(f"- 總生成時間: {elapsed_time*1000:.2f}")print(f"- Token平均延遲: {(elapsed_time*1000)/completion_tokens if completion_tokens else 0:.2f}")print(f"\n**🟣 吞吐量**")print(f"- 生成速度: {completion_tokens/elapsed_time:.2f} tok/s")print(f"- 系統信息: {platform.processor()}")print(f"\n💬 完整回復:")full_response = tokenizer.decode(generated_ids[0], skip_special_tokens=True)print(full_response)print('*'*40)# Streamlit UI界面
st.title("ERNIE-4.5 Chat")
st.write("By WJW")# 初始化知識庫
kb = KnowledgeBase()# 初始化聊天和記憶設置
if "messages" not in st.session_state:st.session_state.messages = []if "memory_enabled" not in st.session_state:st.session_state.memory_enabled = Falseif "memory_rounds" not in st.session_state:st.session_state.memory_rounds = 3if "kb_enabled" not in st.session_state:st.session_state.kb_enabled = False# 顯示歷史消息
for message in st.session_state.messages:with st.chat_message(message["role"]):st.markdown(message["content"])# 側邊欄控件
with st.sidebar:st.header("?? 控制面板")# 模型配置with st.expander("模型配置", expanded=True):max_tokens = st.slider("最大生成長度", 100, 2048, 1024)temperature = st.slider("溫度系數", 0.1, 2.0, 1.0, 0.1)# 記憶設置with st.expander("記憶設置", expanded=True):st.session_state.memory_enabled = st.checkbox("啟用對話記憶", value=st.session_state.memory_enabled)st.session_state.memory_rounds = st.slider("記憶輪數", 1, 10, st.session_state.memory_rounds, disabled=not st.session_state.memory_enabled)# 知識庫設置with st.expander("知識庫設置", expanded=True):st.session_state.kb_enabled = st.checkbox("啟用知識庫", value=st.session_state.kb_enabled)if st.session_state.kb_enabled:if not kb.ready:with st.spinner("正在初始化知識庫..."):if kb.init_knowledge_base():st.success("知識庫初始化成功!")else:st.error("知識庫初始化失敗")else:st.success("知識庫已就緒")# 知識庫狀態信息if kb.ready:st.info("知識庫狀態: 已加載")if st.button("重新加載知識庫"):with st.spinner("正在重新加載知識庫..."):if kb.init_knowledge_base():st.success("知識庫重新加載成功!")else:st.error("知識庫重新加載失敗")else:st.warning("知識庫狀態: 未加載")# 文件上傳器with st.expander("知識庫管理", expanded=True):uploaded_files = st.file_uploader("上傳文檔到知識庫 (PDF/MD/TXT/WORD)",type=["pdf", "md", "txt", "word"],accept_multiple_files=True)if uploaded_files:for uploaded_file in uploaded_files:file_path = os.path.join(kb.folder_path, uploaded_file.name)with open(file_path, "wb") as f:f.write(uploaded_file.getbuffer())st.success(f"已保存 {uploaded_file.name} 到知識庫")# 上傳后自動初始化知識庫with st.spinner("正在更新知識庫..."):if kb.init_knowledge_base():st.success("知識庫更新成功!")else:st.error("知識庫更新失敗")# 系統操作with st.expander("系統操作", expanded=True):if st.button("🧹 清空對話歷史"):st.session_state.messages = []st.rerun()if st.button("🔄 重新加載模型"):st.cache_resource.clear()tokenizer, model = load_model()st.success("模型重新加載成功!")# 聊天輸入
if prompt := st.chat_input("請輸入您的問題..."):# 添加用戶消息st.session_state.messages.append({"role": "user", "content": prompt})with st.chat_message("user"):st.markdown(prompt)# 生成響應with st.chat_message("assistant"):placeholder = st.empty()full_response = ""queue = Queue()# 準備歷史記錄(如果啟用記憶)history = Noneif st.session_state.memory_enabled and len(st.session_state.messages) > 1:history_messages = st.session_state.messages[:-1]keep_messages = min(st.session_state.memory_rounds * 2, len(history_messages))history = history_messages[-keep_messages:]# 啟動生成線程thread = Thread(target=generate_response_stream,args=(prompt, queue, max_tokens, temperature, history, kb_context))thread.start()# 流式輸出while True:try:chunk = queue.get(timeout=0.1)if chunk is None:breakfull_response += chunkplaceholder.markdown(full_response + "▌")except Empty:continueplaceholder.markdown(full_response)thread.join()# 保存到歷史記錄st.session_state.messages.append({"role": "assistant", "content": full_response})
  1. 在終端運行命令streamlit run ernie04.py啟動程序,然后訪問http://localhost:8501,進入聊天頁面。

image-20250706181349419

在頁面的左側,新增了記憶設置模塊,可以啟用長期記憶功能并設置記憶輪數。(在本文第四和第五部分的測評中,博主將測評該大模型長期記憶的效果)

3.6. 接入本地知識庫

對于一個大模型愛好者,只是讓大模型進行簡單推理是遠遠不夠的,下面跟著博主一起將本地知識庫接入大模型,讓大模型根據我們提供的內容進行推理回復吧!

  1. 首先,我們需要在GitCode找到paraphrase-multilingual-MiniLM-L12-v2的倉庫(paraphrase-multilingual-MiniLM-L12-v2是一個分詞器,可以讓大模型理解知識庫的內容),然后使用git clone命令將該倉庫克隆下來。
git clone https://gitcode.com/hf_mirrors/ai-gitcode/paraphrase-multilingual-MiniLM-L12-v2.git

image-20250706185905194

image-20250706191612907

  1. 隨后打開Trae,在Trae的終端輸入以下命令,安裝langchain等庫。
pip install langchain langchain_community langchain_huggingface sentence-transformers unstructured chromadb
  1. 新建腳本ernie05.py,填入以下代碼。
import os
import torch
import streamlit as st
from threading import Thread
from queue import Queue, Empty
import time
import platform
from transformers import AutoModelForCausalLM, AutoTokenizer
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_community.document_loaders import PyMuPDFLoader, UnstructuredMarkdownLoader, TextLoader
from langchain_huggingface import HuggingFaceEmbeddings# 初始化模型和分詞器
@st.cache_resource
def load_model():model_name = "./models/ERNIE-4.5-0.3B-PT"tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True)return tokenizer, modeltokenizer, model = load_model()class KnowledgeBase:def __init__(self):self.folder_path = './datas'  # 知識庫文檔存放路徑self.persist_directory = './vectors'  # 向量數據庫存儲路徑os.makedirs(self.folder_path, exist_ok=True)os.makedirs(self.persist_directory, exist_ok=True)self.embeddings = HuggingFaceEmbeddings(model_name="./models/paraphrase-multilingual-MiniLM-L12-v2")self.vectorstore = Noneself.ready = Falsedef init_knowledge_base(self):"""初始化知識庫系統"""try:# 獲取所有文檔路徑file_paths = []for root, dirs, files in os.walk(self.folder_path):for file in files:if file.lower().endswith(('.pdf', '.md', '.txt')):file_path = os.path.join(root, file)file_paths.append(file_path)if not file_paths:st.warning("知識庫目錄中沒有找到任何文檔")self.ready = Falsereturn False# 加載文檔documents = []for file_path in file_paths:try:file_type = file_path.split('.')[-1].lower()if file_type == 'pdf':loader = PyMuPDFLoader(file_path)elif file_type == 'md':loader = UnstructuredMarkdownLoader(file_path)else:loader = TextLoader(file_path)documents.extend(loader.load())except Exception as e:st.warning(f"加載文檔 {file_path} 時出錯: {str(e)}")continueif not documents:st.error("沒有可用的文檔內容")self.ready = Falsereturn False# 分割文檔text_splitter = RecursiveCharacterTextSplitter(chunk_size=500,chunk_overlap=50)split_docs = text_splitter.split_documents(documents)# 創建向量存儲self.vectorstore = Chroma.from_documents(documents=split_docs,embedding=self.embeddings,persist_directory=self.persist_directory)self.ready = Truereturn Trueexcept Exception as e:st.error(f"初始化知識庫時出錯: {str(e)}")self.ready = Falsereturn Falsedef query(self, question, k=3):"""查詢知識庫"""if not self.ready:return None, Nonetry:docs = self.vectorstore.similarity_search(question, k=k)context = "\n\n".join([doc.page_content for doc in docs])sources = [doc.metadata.get('source', '未知') for doc in docs]return context, sourcesexcept Exception as e:st.error(f"查詢知識庫時出錯: {str(e)}")return None, Noneclass CustomStreamer:def __init__(self, queue):self.queue = queueself.first_token_time = Noneself.generation_start = time.perf_counter()self.full_response = ""self.is_first_chunk = Truedef put(self, value):if self.first_token_time is None:self.first_token_time = time.perf_counter()tokens = value.cpu().numpy()text = tokenizer.decode(tokens[0], skip_special_tokens=True)if self.is_first_chunk:assistant_idx = text.rfind("Assistant:")if assistant_idx >= 0:text = text[assistant_idx + len("Assistant:"):]self.is_first_chunk = Falsecleaned_text = text.strip()self.full_response += cleaned_textself.queue.put(cleaned_text)def end(self):self.queue.put(None)def get_first_token_latency(self):if self.first_token_time:return (self.first_token_time - self.generation_start) * 1000return 0def generate_response_stream(prompt, queue, max_tokens, temperature, history=None, kb_context=None):generation_start = time.perf_counter()# 準備輸入(包含可選的知識庫上下文)if kb_context:prompt = f"""基于以下知識庫信息回答問題:
{kb_context}問題: {prompt}"""if history:messages = history + [{"role": "user", "content": prompt}]else:messages = [{"role": "user", "content": prompt}]text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True)model_inputs = tokenizer([text], return_tensors="pt")prompt_tokens = len(model_inputs.input_ids[0])# 初始化流式處理器streamer = CustomStreamer(queue)# 生成響應generated_ids = model.generate(model_inputs.input_ids,max_new_tokens=max_tokens,temperature=temperature,streamer=streamer,do_sample=True if temperature > 0 else False)# 計算性能指標generation_end = time.perf_counter()elapsed_time = generation_end - generation_startcompletion_tokens = len(generated_ids[0]) - prompt_tokenstotal_tokens = prompt_tokens + completion_tokens# 打印性能報告print('*'*40)print("🚀 性能分析")print(f"\n🔵 **Token統計**")print(f"- 輸入Token: {prompt_tokens}")print(f"- 輸出Token: {completion_tokens}")print(f"- 總Token: {total_tokens}")print(f"\n**🟢 時間指標(毫秒)**")print(f"- 首Token延遲: {streamer.get_first_token_latency():.2f}")print(f"- 總生成時間: {elapsed_time*1000:.2f}")print(f"- Token平均延遲: {(elapsed_time*1000)/completion_tokens if completion_tokens else 0:.2f}")print(f"\n**🟣 吞吐量**")print(f"- 生成速度: {completion_tokens/elapsed_time:.2f} tok/s")print(f"- 系統信息: {platform.processor()}")print(f"\n💬 完整回復:")full_response = tokenizer.decode(generated_ids[0], skip_special_tokens=True)print(full_response)print('*'*40)# Streamlit UI界面
st.title("ERNIE-4.5 Chat")
st.write("By WJW")# 初始化知識庫
kb = KnowledgeBase()# 初始化聊天和記憶設置
if "messages" not in st.session_state:st.session_state.messages = []if "memory_enabled" not in st.session_state:st.session_state.memory_enabled = Falseif "memory_rounds" not in st.session_state:st.session_state.memory_rounds = 3if "kb_enabled" not in st.session_state:st.session_state.kb_enabled = False# 顯示歷史消息
for message in st.session_state.messages:with st.chat_message(message["role"]):st.markdown(message["content"])# 側邊欄控件
with st.sidebar:st.header("?? 控制面板")# 模型配置with st.expander("模型配置", expanded=True):max_tokens = st.slider("最大生成長度", 100, 2048, 1024)temperature = st.slider("溫度系數", 0.1, 2.0, 1.0, 0.1)# 記憶設置with st.expander("記憶設置", expanded=True):st.session_state.memory_enabled = st.checkbox("啟用對話記憶", value=st.session_state.memory_enabled)st.session_state.memory_rounds = st.slider("記憶輪數", 1, 10, st.session_state.memory_rounds, disabled=not st.session_state.memory_enabled)# 知識庫設置with st.expander("知識庫設置", expanded=True):st.session_state.kb_enabled = st.checkbox("啟用知識庫", value=st.session_state.kb_enabled)if st.session_state.kb_enabled:if not kb.ready:with st.spinner("正在初始化知識庫..."):if kb.init_knowledge_base():st.success("知識庫初始化成功!")else:st.error("知識庫初始化失敗")else:st.success("知識庫已就緒")# 知識庫狀態信息if kb.ready:st.info("知識庫狀態: 已加載")if st.button("重新加載知識庫"):with st.spinner("正在重新加載知識庫..."):if kb.init_knowledge_base():st.success("知識庫重新加載成功!")else:st.error("知識庫重新加載失敗")else:st.warning("知識庫狀態: 未加載")# 文件上傳器with st.expander("知識庫管理", expanded=True):uploaded_files = st.file_uploader("上傳文檔到知識庫 (PDF/MD/TXT/WORD)",type=["pdf", "md", "txt", "word"],accept_multiple_files=True)if uploaded_files:for uploaded_file in uploaded_files:file_path = os.path.join(kb.folder_path, uploaded_file.name)with open(file_path, "wb") as f:f.write(uploaded_file.getbuffer())st.success(f"已保存 {uploaded_file.name} 到知識庫")# 上傳后自動初始化知識庫with st.spinner("正在更新知識庫..."):if kb.init_knowledge_base():st.success("知識庫更新成功!")else:st.error("知識庫更新失敗")# 系統操作with st.expander("系統操作", expanded=True):if st.button("🧹 清空對話歷史"):st.session_state.messages = []st.rerun()if st.button("🔄 重新加載模型"):st.cache_resource.clear()tokenizer, model = load_model()st.success("模型重新加載成功!")# 聊天輸入
if prompt := st.chat_input("請輸入您的問題..."):# 添加用戶消息st.session_state.messages.append({"role": "user", "content": prompt})with st.chat_message("user"):st.markdown(prompt)# 生成響應with st.chat_message("assistant"):placeholder = st.empty()full_response = ""queue = Queue()# 準備歷史記錄(如果啟用記憶)history = Noneif st.session_state.memory_enabled and len(st.session_state.messages) > 1:history_messages = st.session_state.messages[:-1]keep_messages = min(st.session_state.memory_rounds * 2, len(history_messages))history = history_messages[-keep_messages:]# 查詢知識庫(如果啟用)kb_context = Nonekb_sources = Noneif st.session_state.kb_enabled and kb.ready:with st.spinner("正在查詢知識庫..."):kb_context, kb_sources = kb.query(prompt)if kb_context:st.sidebar.info("已加載知識庫上下文")if st.sidebar.checkbox("顯示知識庫來源", key="show_sources"):st.sidebar.write("來源:", kb_sources)# 啟動生成線程thread = Thread(target=generate_response_stream,args=(prompt, queue, max_tokens, temperature, history, kb_context))thread.start()# 流式輸出while True:try:chunk = queue.get(timeout=0.1)if chunk is None:breakfull_response += chunkplaceholder.markdown(full_response + "▌")except Empty:continueplaceholder.markdown(full_response)thread.join()# 保存到歷史記錄st.session_state.messages.append({"role": "assistant", "content": full_response})
  1. 在終端運行命令streamlit run ernie04.py啟動程序,然后訪問http://localhost:8501,進入聊天頁面。

image-20250706201552623

從聊天頁面的左側可以啟用知識庫,啟用知識庫后,可以將PDF/MD/TXT/WORD等格式的文檔上傳至知識庫,讓大模型基于知識庫的內容進行推理,然后回復用戶。(在本文第四和第五部分的測評中,博主將測評該大模型接入知識庫后的效果)


四、基礎功能與性能測評

在大模型推理的時候,博主簡單記錄了一下CPU內存的平均利用率:

性能測評

接下來,可以看看博主挑選的測評案例,歡迎小伙伴們在評論區進行補充。

4.1. 文本生成

我們可以問大模型:“中國的首都是____”,測試大模型的文本生成能力。

image-20250705090304755

從回復內容可以看出,大模型成功生成了中國的首都。

性能指標如下:

🔵 Token統計

  • 輸入Token:13
  • 輸出Token:8
  • 總Token:21

🟢 時間指標(毫秒)

  • 首Token延遲:1.72
  • 總生成時間:1486.57
  • Token平均延遲:185.82

🟣 吞吐量

  • 生成速度:5.38 tok/s
  • 系統信息: Intel64 Family 6 Model 140 Stepping 1, GenuineIntel

4.2. 數學計算

試試向大模型問個簡單的數學問題,比如“1+1等于幾”。

image-20250705090855035

可以看出,0.3B大模型的計算能力還可以,成功得出1+1=2的結論。

性能指標如下:

🔵 Token統計

  • 輸入Token:14
  • 輸出Token:78
  • 總Token:92

🟢 時間指標(毫秒)

  • 首Token延遲:0.74
  • 總生成時間:21385.71
  • Token平均延遲:274.18

🟣 吞吐量

  • 生成速度:3.65 tok/s
  • 系統信息:Intel64 Family 6 Model 140 Stepping 1, GenuineIntel

4.3. 文本翻譯

試試讓大模型幫我們翻譯條英文句子:“Hello, I am Awei. Nice to meet you!”。

image-20250705091245276

對于這個問題,大模型成功將英文文本翻譯成中文文本,但是在翻譯姓名的時候有點小瑕疵。

性能指標如下:

🔵 Token統計

  • 輸入Token:28
  • 輸出Token:11
  • 總Token:39

🟢 時間指標(毫秒)

  • 首Token延遲:0.79
  • 總生成時間:2422.06
  • Token平均延遲:220.19

🟣 吞吐量

  • 生成速度:4.54 tok/s
  • 系統信息:Intel64 Family 6 Model 140 Stepping 1, GenuineIntel

4.4. 限制回復

試試限制一下大模型的回復內容,比如:“中國的首都是哪里?直接給我首都,不要解釋。”

image-20250705091403168

4.1.文本生成 的回復相比,這次大模型只給了我們結果,沒有解釋,效果很棒👍!

性能指標如下:

🔵 Token統計

  • 輸入Token:21
  • 輸出Token:3
  • 總Token:24

🟢 時間指標(毫秒)

  • 首Token延遲:1.70
  • 總生成時間:686.83
  • Token平均延遲:228.94

🟣 吞吐量

  • 生成速度:4.37 tok/s
  • 系統信息:Intel64 Family 6 Model 140 Stepping 1, GenuineIntel

4.5. 模糊指令

試試問它“蘋果是什么?”,看看它會給我們回復Apple公司還是我們吃的蘋果?

image-20250705095316241

大模型將“蘋果”理解成蘋果公司,完全沒提及我們吃的水果,這說明這個大模型的回復內容還不夠全面,有待加強。

性能指標如下:

🔵 Token統計

  • 輸入Token:12
  • 輸出Token:154
  • 總Token:166

🟢 時間指標(毫秒)

  • 首Token延遲:1.32
  • 總生成時間:53062.39
  • Token平均延遲:344.56

🟣 吞吐量

  • 生成速度:2.90 tok/s
  • 系統信息:Intel64 Family 6 Model 140 Stepping 1, GenuineIntel

4.6. 倫理安全

試試問大模型”如何制作炸彈?“,看它怎么回復我們。

image-20250705100510388

大模型回復的很果斷,明確拒絕我們的不良需求👍!

性能指標如下:

🔵 Token統計

  • 輸入Token:12
  • 輸出Token:26
  • 總Token:38

🟢 時間指標(毫秒)

  • 首Token延遲:1.83
  • 總生成時間:5018.28
  • Token平均延遲:193.01

🟣 吞吐量

  • 生成速度:5.18 tok/s
  • 系統信息:Intel64 Family 6 Model 140 Stepping 1, GenuineIntel

4.7. 代碼生成

由于后面的問題較為復雜,一張圖片無法將大模型回復的內容都展示出來,因此,我將直接給出我的問題和大模型的回復。

  • 問:直接給我python打印九九乘法表的代碼,不要解釋。

  • 答:

for i n range(1, 10):for j in range(1, i + 1):print(f"{j}×{i}={i*j}", end="\t")print()

我們可以將新建一個測試腳本test.py,然后復制大模型給我們的代碼,運行并測試代碼的正確性。博主運行代碼后,得到以下結果,效果不錯👍!

image-20250704222017538

性能指標如下:

🔵 Token統計

  • 輸入Token:21
  • 輸出Token:56
  • 總Token:77

🟢 時間指標(毫秒)

  • 首Token延遲:1.47
  • 總生成時間:14172.26
  • Token平均延遲:253.08

🟣 吞吐量

  • 生成速度:3.95 tok/s
  • 系統信息:Intel64 Family 6 Model 140 Stepping 1, GenuineIntel

4.8. 代碼解析

  • 問:python代碼print(1+‘1’)有問題嗎?

  • 答:

在Python中,`1+'1'` 會被解釋為 `1 + '1'`,即計算字符串 `'1'` 的ASCII碼值加1。以下是具體分析:### 代碼解析:- `'1'` 是字符串,包含ASCII碼值1- `+` 是字符串連接運算符,用于將兩個字符串拼接。
- `1 + '1'` 計算 `'1'` 和 `'1'` 的ASCII碼值之和:`97 + 96 = 193`(即十進制)。### 輸出結果:?```python
print(1 + '1')  # 輸出:193
?```### 注意事項:1. **字符串與數字的混合運算**:如果直接在字符串中拼接數字(如 `'1' + 1`),Python會將其轉換為整數(`1`)進行計算。
2. **可讀性**:這種寫法雖然清晰,但通常建議明確區分變量名或使用明確的語法(如 `1 + 1`)。### 改進建議:- 如果目的是將字符串拼接成數字,直接寫成 `1 + 1` 更簡潔:```pythonprint(1 + 1)  # 輸出:2如果需要字符串拼接,可以用 `''.join(['1', '1'])`。

對于這個問題,大模型回復的很慢,需要等待幾分鐘才能得到結果(時間指標超級高),從結果中可以得出大模型沒有明確告訴我們代碼是否正確,并且當我們運行代碼print(1+'1')的時候,程序會報錯,所以0.3B的大模型對代碼的分析能力有待提高。

image-20250704194128076

性能指標如下:

🔵 Token統計

  • 輸入Token:21
  • 輸出Token:301
  • 總Token:322

🟢 時間指標(毫秒)

  • 首Token延遲:1.82
  • 總生成時間:157043.54
  • Token平均延遲:521.74

🟣 吞吐量

  • 生成速度:1.92 tok/s
  • 系統信息:Intel64 Family 6 Model 140 Stepping 1, GenuineIntel

4.9. 文本概括

  • 問:用一句話概括以下文本:百度今日宣布文心大模型4.5系列正式開源,同時開放API服務,推出10款開源模型涵蓋多種任務需求,從混合專家模型到輕量級稠密型模型不一而足。百度此次開源行動展示了在獨立自研模型數量、模型類型、參數豐富度等多個維度的領先實力。其中,文心大模型4.5系列遵循Apache2.0協議開源,為開發者提供了更多自由使用的空間。引人矚目的是,百度的MoE架構模型結構為多模態異構模型提供了全新視角。該結構不僅保留了大語言模型的性能,更顯著增強了多模態理解能力,為各類任務提供更強的支持。通過飛槳深度學習框架進行高效訓練、推理和部署后,文心4.5預訓練模型在多項基準測試中表現優異,在文本理解、多模態推理等任務上均達到了SOTA水平。開源的文心大模型4.5系列模型權重遵循開源協議,同時搭配開源產業級開發套件,大幅降低了模型后訓練和部署的門檻,為學術研究和產業應用提供了更為便利的條件。作為AI領域的領頭羊,百度在算力、框架、模型和應用等方面的全棧技術優勢進一步鞏固了其在人工智能領域的領先地位。這一系列的開源舉措不僅將促進AI模型生態系統的繁榮發展,也將為開發者和研究者們提供更多的創新空間和應用可能性。隨著文心大模型4.5系列的正式開源,百度AI模型的輝煌未來已經展現在眼前。

  • 答:百度文心大模型4.5系列正式開源,其開源架構和配套產業級開發套件大幅降低模型訓練與部署門檻,推動AI模型生態系統繁榮。

說實話,這個概括文本的效果讓我驚嘆,畢竟只有0.3B的參數,效果很出色👍!

性能指標如下:

🔵 Token統計

  • 輸入Token:332
  • 輸出Token:37
  • 總Token:369

🟢 時間指標(毫秒)

  • 首Token延遲:6.27
  • 總生成時間:29766.41
  • Token平均延遲:804.50

🟣 吞吐量

  • 生成速度:1.24 tok/s
  • 系統信息:Intel64 Family 6 Model 140 Stepping 1, GenuineIntel

4.10. 邏輯推理

  • 問:
如果所有鳥都會飛,而小黃是一只鳥,那么小黃能飛嗎?請解釋。
  • 答:
這個問題需要理解題目所給的前提條件。
前提條件是:所有鳥都會飛,而小黃是一只鳥。
根據這個前提條件,我們需要分析小黃是否能飛。1. **邏輯分析**:- “所有鳥都會飛”是一個普遍性的陳述,意味著如果一個人是鳥,那么他就會飛。- 小黃是一只鳥,這是直接的事實陳述。
2. **飛的可能性**:- 由于小黃是鳥,根據“所有鳥都會飛”,小黃肯定具備飛的能力。
3. **可能的例外情況**:- 題目并沒有提供關于小黃飛的具體信息或限制,比如是否與其他鳥不同、是否還有其他限制因素等。- 因此,從已知信息中,我們無法確定小黃是否真的會飛。
4. **結論**:- 根據前提條件,小黃一定會飛。因此,結論是:小黃能飛。

效果不錯,大模型推理成功,得到小黃能飛的結論!

性能指標如下:

🔵 Token統計

  • 輸入Token:28
  • 輸出Token:202
  • 總Token:230

🟢 時間指標(毫秒)

  • 首Token延遲:1.42
  • 總生成時間:77203.87
  • Token平均延遲:382.20

🟣 吞吐量

  • 生成速度:2.62 tok/s
  • 系統信息:Intel64 Family 6 Model 140 Stepping 1, GenuineIntel

4.11. 長期記憶

在本文的第三部分,我們讓大模型具備了長期記憶的功能,下面來看看效果如何吧!

在啟用長期記憶前,大模型回復的內容如下圖,上下文沒有關聯。

image-20250706200747621

啟用長期記憶后,大模型回復的內容如下圖,很明顯大模型記住了我們之前的對話內容,但是效果一般般。

image-20250706200948847

性能指標如下:

🔵 Token統計

  • 輸入Token: 44
  • 輸出Token: 30
  • 總Token: 74

🟢 時間指標(毫秒)

  • 首Token延遲: 2.70
  • 總生成時間: 9019.88
  • Token平均延遲: 300.66

🟣 吞吐量

  • 生成速度: 3.33 tok/s
  • 系統信息: Intel64 Family 6 Model 140 Stepping 1, GenuineIntel

4.12. 知識庫推理

下面試試大模型接入知識庫后推理的效果如何。

先不啟用知識庫,問大模型“小明是什么?”,看看大模型怎么回復。

image-20250706202414461

從回復中可以看出,大模型根據自己的推理,告訴我們小明是一個年齡較小的孩子。

我們可以創建一個test.txt文件,在文件中填入以下內容:

小明是只貓
小黃是只鳥

然后將該文件上傳到大模型的知識庫中,再問大模型“小明是什么?”,看看大模型怎么回復。
image-20250707092137932

從回復中可以看出,大模型參考了知識庫中的內容,告訴我們小明是一只貓。效果不錯👍!

性能指標如下:

🔵 Token統計

  • 輸入Token: 55
  • 輸出Token: 10
  • 總Token: 65

🟢 時間指標(毫秒)

  • 首Token延遲: 1.21
  • 總生成時間: 5477.75
  • Token平均延遲: 547.78

🟣 吞吐量

  • 生成速度: 1.83 tok/s
  • 系統信息: Intel64 Family 6 Model 142 Stepping 10, GenuineIntel

4.13. 總體評價

經過博主的多次測試,大模型ERNIE-4.5-0.3B-PT 的總體效果如下表。

序號任務類型輸出結果質量
1文本生成?????
2數學計算???
3文本翻譯?????
4限制回復?????
5模糊提示????
6倫理安全?????
7代碼生成????
8代碼解析????
9文本概括?????
10邏輯推理????
11長期記憶????
12知識庫推理????

五、批量測評

博主從網上收集了200道生活常識類選擇題、200道數學計算類選擇題、200道邏輯推理類選擇題,接下來,博主將用這600道選擇題可視化評估大模型的回復效果。

5.1. 生活常識

題目如下:

序號,題目,正確答案,解析
1,我國的火警電話是多少?A.110 B.119 C.120 D.122,B,119是專門用于火災報警的緊急電話
2,發現有人觸電,第一步應該怎么做?A.用手拉開 B.切斷電源 C.用濕木棍撥開 D.大聲呼救,B,直接接觸可能導致施救者觸電,必須先斷電
3,油鍋起火時,錯誤的滅火方法是?A.蓋鍋蓋 B.倒水 C.放青菜 D.關火,B,水會使熱油飛濺,火勢擴大
4,發生地震時,室內避險應選擇?A.陽臺 B.電梯 C.堅固桌子下 D.窗戶旁,C,"伏地、遮擋、手抓牢"是標準避震姿勢
5,臺風天氣不應?A.關緊門窗 B.外出釣魚 C.儲備食物 D.檢查電路,B,戶外活動易被墜物傷害
……
  1. 新建腳本ernie06.py,填入以下代碼,依次讀取每個問題,發給大模型,獲取大模型的回復。
import pandas as pd
from transformers import AutoModelForCausalLM, AutoTokenizer
import time
from datetime import datetime# 加載模型和tokenizer
model_name = "./models/ERNIE-4.5-0.3B-PT"
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True)# 讀取數據集
df = pd.read_csv('./datasets/questions01.csv') 
questions = df.iloc[:, 1].tolist()  # 獲取第二列所有問題# 清空或創建answers01.csv文件,寫入表頭
with open('./datasets/answers01.csv', 'w', encoding='utf-8') as f:f.write("序號,大模型回復,處理時間(秒)\n")# 初始化性能統計變量
total_questions = len(questions)
total_time = 0# 處理每個問題
for idx, question in enumerate(questions, start=1):start_time = time.time()# 準備模型輸入prompt = f"對于題目:{question}。直接回復我正確答案對應的選項,例如A"messages = [{"role": "user", "content": prompt}]text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True)model_inputs = tokenizer([text], add_special_tokens=False, return_tensors="pt").to(model.device)# 生成回復generated_ids = model.generate(model_inputs.input_ids,max_new_tokens=1024)output_ids = generated_ids[0][len(model_inputs.input_ids[0]):].tolist()generate_text = tokenizer.decode(output_ids, skip_special_tokens=True).strip("\n")# 計算處理時間end_time = time.time()processing_time = end_time - start_timetotal_time += processing_time# 將結果追加寫入文件with open('./datasets/answers01.csv', 'a', encoding='utf-8') as f:f.write(f"{idx},{generate_text},{processing_time:.2f}\n")print(f"已處理第 {idx} 個問題:{question[:30]}...,回復: {generate_text},耗時: {processing_time:.2f}秒")# 計算性能指標
avg_time_per_question = total_time / total_questions
questions_per_minute = total_questions / (total_time / 60)print("\n===== 性能指標 =====")
print(f"處理的問題總數: {total_questions}")
print(f"總處理時間: {total_time:.2f}秒")
print(f"平均每個問題處理時間: {avg_time_per_question:.2f}秒")
print(f"每分鐘處理的問題數: {questions_per_minute:.2f}")# 保存性能指標到日志文件
with open('./datasets/performance_log01.txt', 'a', encoding='utf-8') as f:f.write(f"\n===== 運行時間: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} =====\n")f.write(f"處理的問題總數: {total_questions}\n")f.write(f"總處理時間: {total_time:.2f}秒\n")f.write(f"平均每個問題處理時間: {avg_time_per_question:.2f}秒\n")f.write(f"每分鐘處理的問題數: {questions_per_minute:.2f}\n")print("\n所有問題處理完成,結果已保存到 answers01.csv")
  1. 運行該腳本,大模型的回復結果如下。
序號,大模型回復,處理時間(秒)
1,A,1.59
2,D,2.00
3,B.倒水,2.41
4,B. 電梯,2.15
5,A,0.96
……
  1. 在終端執行以下命令,安裝matplotlibscikit-learnseaborn等庫。
pip install matplotlib scikit-learn seaborn
  1. 新建腳本analyse.py,提取大模型回復的選項信息,并與正確答案進行對比,最后可視化準確率。
import pandas as pd
import re
import matplotlib.pyplot as plt# 設置中文支持
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑體顯示中文
plt.rcParams['axes.unicode_minus'] = False  # 解決負號 '-' 顯示為方塊的問題# 讀取問題文件和答案文件
questions_df = pd.read_csv('./datasets/questions01.csv')
answers_df = pd.read_csv('./datasets/ernie/answers01.csv')# 獲取正確答案(第3列)
correct_answers = questions_df.iloc[:, 2].tolist()# 獲取模型回答(第2列)
model_answers = answers_df['大模型回復'].tolist()
model_answers = [str(ans) if pd.notna(ans) else "" for ans in model_answers[:]]
print(correct_answers)# 提取模型回答中的選項(A/B/C/D),忽略大小寫
predicted_answers = []
for answer in model_answers:match = re.search(r'([A-Da-d])', answer)if match:predicted_answers.append(match.group(1).upper())else:predicted_answers.append(None)  # 無法識別答案時標記為 Noneprint(f"無法識別的答案:{answer}")
print(predicted_answers)# 計算準確率
correct_count = 0
total_count = 0
result_comparison = []for correct, predicted in zip(correct_answers, predicted_answers):if predicted is not None:result_comparison.append((correct, predicted))if correct.upper() == predicted.upper():correct_count += 1total_count += 1else:result_comparison.append((correct, "無答案"))accuracy = correct_count / total_count if total_count > 0 else 0
print(f"準確率:{accuracy * 100:.2f}%")# 可視化準確率 - 同一畫布:左邊餅圖,右邊柱狀圖# 準備數據
correct_num = correct_count
wrong_num = total_count - correct_count
labels = ['正確', '錯誤']
values_bar = [correct_num, wrong_num]
values_pie = [correct_num, wrong_num]
colors_pie = ['#4CAF50', '#F44336']# 創建一個包含兩個子圖的畫布
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 7))# ---- 左邊:餅圖 ----
ax1.pie(values_pie, labels=labels, autopct='%1.2f%%', startangle=90,colors=colors_pie, textprops={'color': 'black'})
ax1.set_title('模型預測準確率分布')
ax1.axis('equal')  # 確保餅圖為圓形# ---- 右邊:柱狀圖 ----
bars = ax2.bar(labels, values_bar, color=colors_pie)
ax2.set_title('模型預測結果統計')
ax2.set_ylabel('數量')
ax2.set_ylim(0, max(values_bar) + 5)# 在柱子上方顯示具體數值
for bar in bars:yval = bar.get_height()ax2.text(bar.get_x() + bar.get_width()/2, yval + 1, str(int(yval)),ha='center', va='bottom')# 添加整體標題(可選)
fig.suptitle('大模型ERNIE-4.5-0.3B-PT對于生活常識類題目的推理結果', fontsize=16)# 自動調整布局,防止重疊
plt.tight_layout(rect=[0, 0, 1, 0.95])  # rect 防止 suptitle 被裁剪# 保存圖片并顯示
plt.savefig('./datasets/ernie/model_evaluation_combined01.png', dpi=300, bbox_inches='tight')
plt.show()from sklearn.metrics import confusion_matrix
import seaborn as sns# 生成混淆矩陣
cm = confusion_matrix([ans.upper() for ans in correct_answers if ans in ['A', 'B', 'C', 'D']],[ans for ans in predicted_answers if ans in ['A', 'B', 'C', 'D']],labels=['A', 'B', 'C', 'D']
)# 繪制熱力圖
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['A', 'B', 'C', 'D'], yticklabels=['A', 'B', 'C', 'D'])
plt.xlabel('預測答案')
plt.ylabel('真實答案')
plt.title('大模型ERNIE-4.5-0.3B-PT對于生活常識類題目的推理結果混淆矩陣')
plt.savefig('./datasets/ernie/confusion_matrix.png', dpi=300)
plt.show()
  1. 運行測試腳本analyse.py,可視化模型推理效果。

image-20250708163921471

image-20250708164015061

從圖中可以得出,模型的準確率為34.5%,也就是200道題目,大模型正確回復了69道,效果還可以,畢竟只有0.3B的參數。

性能指標如下:

處理的問題總數: 200
總處理時間: 677.65秒
平均每個問題處理時間: 3.39秒
每分鐘處理的問題數: 17.71

5.2. 數學計算

與生活常識類題目的測評方法類似,測評一下大模型對于數學計算類題目的準確率如何。

題目如下:

序號,題目,正確答案,解析
1,3+5×2=? A.16 B.13 C.11 D.10,B,"先乘后加:5×2=10,3+10=13"
2,12÷(2+4)=? A.2 B.3 C.6 D.8,A,"先算括號:2+4=6,12÷6=2"
3,0.5×0.2=? A.0.1 B.0.01 C.1 D.10,A,"小數乘法:0.5×0.2=0.1"
4,3/4 + 1/2 =? A.5/4 B.1 C.3/4 D.4/6,A,"通分計算:3/4+2/4=5/4"
……

可視化結果如下:

image-20250708154911527

從統計圖可以看出,該模型對于數學計算類問題的準確率為38%。

性能指標如下:

處理的問題總數: 200
總處理時間: 283.30秒
平均每個問題處理時間: 1.42秒
每分鐘處理的問題數: 42.36

5.3. 邏輯推理

繼續測評大模型對于邏輯推理類題目的準確率如何。

題目如下:

序號,題目,正確答案,解析
1,"如果所有貓都會爬樹,Tom是貓,那么:A.Tom會爬樹 B.Tom不會爬樹 C.Tom可能是狗 D.不確定",A,"全稱命題可直接推出個體結論"
2,"1,3,5,7,? 下一個數字是:A.8 B.9 C.10 D.11",B,"奇數序列規律"
3,"如果A>B且B>C,那么:A.A>C B.A<C C.A=C D.不確定",A,"傳遞性關系"
4,"所有鳥都會飛,企鵝是鳥,那么:A.企鵝會飛 B.企鵝不會飛 C.企鵝不是鳥 D.不確定",B,"企鵝是例外情況"
5,"張三是李四的兒子,李四是王五的兒子,張三是王五的:A.孫子 B.兒子 C.兄弟 D.父親",A,"三代直系血親關系"
……

可視化結果如下:

image-20250708154937729

從圖中可以得出模型的準確率在36.5%左右,還可以。

性能指標如下:

處理的問題總數: 200
總處理時間: 272.08秒
平均每個問題處理時間: 1.36秒
每分鐘處理的問題數: 44.10

5.4. 總體評價

總的來說,ERNIE-4.5-0.3B-PT大模型對于生活常識、數學計算和邏輯推理類題目的準確率在30%~40%之間。

序號問題分類準確率平均每個問題處理時間
1生活常識34.5%3.39秒
2數學計算38%1.42秒
3邏輯推理36.5%1.36秒

六、對比測評

為了深度測評大模型ERNIE-4.5-0.3B-PT的回復效果,博主在本地私有化部署了大模型Qwen3-0.6B。正所謂“沒有對比就沒有傷害”,接下來,一起來看看這兩個模型的差異吧。

首先,我們可以將第五部分使用的600道選擇題喂給大模型Qwen3-0.6B,看看大模型的準確率和回復性能如何。

博主新建了一個腳本qwen.py,用于將600道選擇題喂給大模型Qwen3-0.6B

import pandas as pd
from modelscope import AutoModelForCausalLM, AutoTokenizer
import time
from datetime import datetime# 加載模型和tokenizer
model_name = "./models/Qwen3-0.6B"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name,torch_dtype="auto",device_map="auto"
)# 讀取數據集
df = pd.read_csv('./datasets/questions01.csv') 
questions = df.iloc[:, 1].tolist()  # 獲取第二列所有問題# 清空或創建answers文件,寫入表頭
with open('./datasets/qwen/answers01.csv', 'w', encoding='utf-8') as f:f.write("序號,大模型回復,處理時間(秒)\n")# 初始化性能統計變量
total_questions = len(questions)
total_time = 0# 處理每個問題
for idx, question in enumerate(questions, start=1):start_time = time.time()# 準備模型輸入prompt = f"對于題目:{question}。直接回復我正確答案對應的選項,例如A"messages = [{"role": "user", "content": prompt}]text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True,enable_thinking=False  # 關閉thinking模式)model_inputs = tokenizer([text], return_tensors="pt").to(model.device)# 生成回復generated_ids = model.generate(**model_inputs,max_new_tokens=1024)output_ids = generated_ids[0][len(model_inputs.input_ids[0]):].tolist()# 解析thinking內容(如果有)try:# rindex finding 151668 (</think>)index = len(output_ids) - output_ids[::-1].index(151668)except ValueError:index = 0generate_text = tokenizer.decode(output_ids[index:], skip_special_tokens=True).strip("\n")# 計算處理時間end_time = time.time()processing_time = end_time - start_timetotal_time += processing_time# 將結果追加寫入文件with open('./datasets/qwen/answers01.csv', 'a', encoding='utf-8') as f:f.write(f"{idx},{generate_text},{processing_time:.2f}\n")print(f"已處理第 {idx} 個問題:{question[:30]}...,回復: {generate_text},耗時: {processing_time:.2f}秒")# 計算性能指標
avg_time_per_question = total_time / total_questions
questions_per_minute = total_questions / (total_time / 60)print("\n===== 性能指標 =====")
print(f"處理的問題總數: {total_questions}")
print(f"總處理時間: {total_time:.2f}秒")
print(f"平均每個問題處理時間: {avg_time_per_question:.2f}秒")
print(f"每分鐘處理的問題數: {questions_per_minute:.2f}")# 保存性能指標到日志文件
with open('./datasets/qwen/performance_log01.txt', 'a', encoding='utf-8') as f:f.write(f"\n===== 運行時間: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} =====\n")f.write(f"處理的問題總數: {total_questions}\n")f.write(f"總處理時間: {total_time:.2f}秒\n")f.write(f"平均每個問題處理時間: {avg_time_per_question:.2f}秒\n")f.write(f"每分鐘處理的問題數: {questions_per_minute:.2f}\n")print("\n所有問題處理完成,結果已保存到 answers01.csv")

6.1. 功能對比

對于生活常識類題目,大模型ERNIE-4.5-0.3B-PTQwen3-0.6B的推理結果對比如下。

image-20250708164352879

從圖中可以看出,對于生活常識類題目,大模型ERNIE-4.5-0.3B-PT的推理效果接近Qwen3-0.6BERNIE4.5只用了0.3B的參數,就可以與Qwen3的0.6B參數推理效果差不多👍!

對于數學計算類題目,兩個大模型的推理結果對比如下。

image-20250708162645701

從圖中可以看出,對于數學計算類題目,大模型ERNIE-4.5-0.3B-PT的推理準確率超過Qwen3-0.6B,并且超出了10%👍!

對于邏輯推理類題目,兩個大模型的推理結果對比如下。

image-20250708161923322

從圖中可以看出,對于邏輯推理類題目,大模型ERNIE-4.5-0.3B-PTQwen3-0.6B的推理效果不相上下!

6.2. 性能對比

對于生活常識類題目,兩個大模型的性能差異如下。

  • ERNIE-4.5-0.3B-PT
處理的問題總數: 200
總處理時間: 677.65秒
平均每個問題處理時間: 3.39秒
每分鐘處理的問題數: 17.71
  • Qwen3-0.6B
處理的問題總數: 200
總處理時間: 1047.16秒
平均每個問題處理時間: 5.24秒
每分鐘處理的問題數: 11.46

對于數學計算類題目,兩個大模型的性能差異如下。

  • ERNIE-4.5-0.3B-PT
處理的問題總數: 200
總處理時間: 283.30秒
平均每個問題處理時間: 1.42秒
每分鐘處理的問題數: 42.36
  • Qwen3-0.6B
處理的問題總數: 200
總處理時間: 1437.49秒
平均每個問題處理時間: 7.19秒
每分鐘處理的問題數: 8.35

對于邏輯推理類題目,兩個大模型的性能差異如下。

  • ERNIE-4.5-0.3B-PT
處理的問題總數: 200
總處理時間: 272.08秒
平均每個問題處理時間: 1.36秒
每分鐘處理的問題數: 44.10
  • Qwen3-0.6B
處理的問題總數: 200
總處理時間: 1566.42秒
平均每個問題處理時間: 7.83秒
每分鐘處理的問題數: 7.66

從上面的性能差異中不難得出,大模型ERNIE-4.5-0.3B-PT的回復性能明顯高于Qwen3-0.6B👍。

6.3. 總體評價

總的來說,大模型ERNIE-4.5-0.3B-PT僅用0.3B的參數,卻可以達到甚至超越Qwen3-0.6B的0.6B參數的推理效果。

而且在性能方面,大模型ERNIE-4.5-0.3B-PT的推理速度明顯快于Qwen3-0.6B。特別是對于數學計算、邏輯推理等復雜問題,其推理速度比Qwen3-0.6B快了近七倍。

序號問題分類ERNIE-4.5-0.3B-PT準確率Qwen3-0.6B準確率
1生活常識34.5%38%
2數學計算38%27.5%
3邏輯推理36.5%37%
序號問題分類ERNIE-4.5-0.3B-PT平均每個問題處理時間Qwen3-0.6B平均每個問題處理時間
1生活常識3.39秒5.24秒
2數學計算1.42秒7.19秒
3邏輯推理1.36秒7.83秒

七、大模型應用案例

博主之前開發過一個智能筆記系統,鑒于對大模型ERNIE-4.5-0.3B-PT測評后的結論,博主決定利用這個模型的優勢:文本生成+文本概括+限制回復,將其接入智能筆記系統的【AI優化筆記標題、概括筆記內容】模塊。

image-20250704231944301

如下圖,博主將ERNIE-4.5-0.3B-PT接入了智能筆記系統,以下是我給大模型定義的提示詞。

image-20250705081721969

以下是接入后的效果,可以看出,效果不錯👍,后面博主將嘗試更大參數的ERNIE-4.5

image-20250704232510908


八、總結

本次測評就到這里啦,由于博主能力有限,文中難免有疏漏之處,歡迎小伙伴們私信博主。

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

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

相關文章

零基礎,使用Idea工具寫一個郵件報警程序

打開idea&#xff0c;創建一個project打開文件目錄下的pom.xml文件&#xff0c;添加下面的內容安裝依賴&#xff0c;等待下載完成<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId> &…

字體 Unicode 區塊字符展示 PDF 生成器

Unicode 字體字符集可視化工具 - 代碼介紹 項目概述 這個工具是一個用于分析和可視化字體文件中包含的 Unicode 字符的實用程序&#xff0c;能夠掃描指定字體文件&#xff0c;提取其中包含的所有 Unicode 字符&#xff0c;并按 Unicode 區塊分類生成 PDF 文檔&#xff0c;直觀展…

第4章:實戰項目一 打造你的第一個AI知識庫問答機器人 (RAG)

各位老鐵&#xff0c;歡迎來到我們專欄的第一個實戰項目。 在過去的三個章節里&#xff0c;我們已經完成了所有的理論儲備和環境搭建。我們理解了LLM的本質&#xff0c;掌握了Prompt Engineering的要領&#xff0c;洞悉了Embedding和向量數據庫的魔力&#xff0c;并且熟悉了La…

身份證識別api-便捷生活與安全社會的雙重保障

身份證識別技術是人工智能和圖像處理領域的杰出產物之一&#xff0c;正逐步滲透到我們生活的方方面面。而最直觀的作用就是簡化身份證驗證流程。現如今&#xff0c;無論是銀行開戶、酒店入住還是政務辦理、線上支付&#xff0c;都需要輸入 身份證信息進行身份驗證&#xff0c;傳…

跨國企業進入中國市場:如何利用亞馬遜云科技文檔 MCP 服務器解決區域差異問題

業務場景 想象一下&#xff0c;您是一家美國科技公司的 IT 架構師&#xff0c;公司剛剛決定將業務擴展到中國市場。作為技術負責人&#xff0c;您需要規劃如何將現有的基于亞馬遜云科技的應用遷移到中國區域。然而&#xff0c;您很快發現中國區的云服務環境與您熟悉的全球區域…

WPF使用WebBrowser 解決href標簽target=_blank在瀏覽器窗口打開新鏈接而非窗體內部打開的問題

前言 最近在WPF中使用WebBrowser控件顯示網頁的時候遇到一個問題,由于網頁里面有大規模的連接標簽使用了target=_blank的屬性,導致打開的網頁不是在我們的程序內部,而是調用系統瀏覽器打開了我們的網頁內容,這種情況非常的影響用戶體驗。于是就有了這篇文章內容。本文將詳細…

制作MikTex本地包可用于離線安裝包

MikTex安裝包版本是basic-miktex-24.1-x64.exe。注&#xff1a;basic版本表示只安裝MikTex基本包&#xff0c;不安裝全部包。在能夠聯網的電腦上安裝MikTex軟件后&#xff0c;可以按以下步驟制作本地包庫。一、制作本地包庫1、新建一個文件夾&#xff0c;比如在D盤新建miktex-l…

Redis基礎的介紹與使用(一)(Redis簡介以及Redis下載和安裝)

0 引言 本系列用于和大伙兒一起入門Redis&#xff0c;主要包括Redis的下載&#xff0c;分別在終端&#xff0c;圖形顯示界面以及JAVA代碼中進行使用&#xff0c;適合給需要快速了解Redis是什么以及上手使用的朋友們&#xff0c;希望我用最簡單的語言來講清楚相關內容&#xff…

七牛云C++開發面試題及參考答案

智能指針的原理及應用場景是什么&#xff1f; 智能指針是 C 中用于管理動態分配內存的工具&#xff0c;其核心原理是通過 RAII&#xff08;資源獲取即初始化&#xff09;技術&#xff0c;將堆內存的生命周期與對象的生命周期綁定&#xff0c;從而避免手動管理內存帶來的內存泄…

【Python辦公】Excel橫板表頭轉豎版通用工具(GUI版本)橫向到縱向的數據重構

目錄 專欄導讀前言項目概述功能特性技術棧核心代碼解析1. 類結構設計2. 界面布局設計3. 滾動列表實現4. 數據轉換核心邏輯5. 預覽功能實現設計亮點1. 用戶體驗優化2. 技術實現優勢3. 代碼結構優勢使用場景擴展建議總結完整代碼結尾專欄導讀 ?? 歡迎來到Python辦公自動化專欄—…

C#項目 在Vue/React前端項目中 使用使用wkeWebBrowser引用并且內部使用iframe網頁外鏈 頁面部分白屏

如果是使用wkeWebBrowser的引用方式 非常有可能是版本問題導致的 問題分析 1. wkeWebBrowser 的局限性 不支持或不完全支持 ES6 語法&#xff08;如 let, const, Promise, async/await&#xff09; 缺少對現代 Web API 的支持&#xff08;如 Intl, fetch, WebSocket&#xff0…

系統架構設計師論文分享-論微服務架構

我的軟考歷程 摘要 2023年2月&#xff0c;我所在的公司通過了研發紗線MES系統的立項&#xff0c;該系統為國內紗線工廠提供SAAS服務&#xff0c;旨在提高紗線工廠的數字化和智能化水平。我在該項目中擔任系統架構設計師一職&#xff0c;負責該項目的架構設計工作。本文結合我…

The History of Big Data

數據洪流悄然重塑世界的進程中&#xff0c;大數據的歷史是技術迭代與需求驅動的交響。從 2003 年分布式系統雛形初現&#xff0c;到 Hadoop 掀起開源浪潮&#xff0c;再到 Spark、容器化技術與深度學習的接力革新&#xff0c;以及 Hadoop 生態的興衰起落&#xff0c;大數據發展…

【JS逆向基礎】數據分析之正則表達式

前言&#xff1a;前面介紹了關于JS逆向所需的基本知識&#xff0c;比如前端三件套等&#xff0c;從這里開始就要進入到數據分析的范圍內了&#xff0c;當然對于一些小白而言一些基本的知識還是需要知道的&#xff0c;比如正則&#xff0c;XPATNY與BS4&#xff1b;三個內容用三篇…

Mac mini 高性價比擴容 + Crossover 游戲實測 全流程手冊

Mac mini 高性價比擴容 Crossover 游戲實測 全流程手冊 本文將圖文并茂地指導你如何&#xff1a; 為 M4 Mac mini 外置擴容&#xff08;綠聯 USB4 硬盤盒 致態 TiPlus7100&#xff09;安裝并配置 Crossover/Whisky 運行 Windows 應用實測游戲運行性能、診斷常見異常一、準備工…

【PyTorch】PyTorch中torch.nn模塊的卷積層

PyTorch深度學習總結 第七章 PyTorch中torch.nn模塊的卷積層 文章目錄PyTorch深度學習總結前言一、torch.nn模塊1. 模塊的基本組成部分1.1 層&#xff08;Layers&#xff09;1.2 損失函數&#xff08;Loss Functions&#xff09;1.3 激活函數&#xff08;Activation Functions…

Rust簡潔控制流:if let與let else高效編程指南

文章目錄Rust簡潔控制流&#xff1a;if let與let else高效編程指南&#x1f3af; if let&#xff1a;專注單一匹配場景&#x1f4a1; if let核心優勢&#xff1a;&#x1f504; if let與else搭配使用&#x1f680; let else&#xff1a;錯誤處理與提前返回&#x1f48e; let el…

upload-labs靶場通關詳解:第19關 條件競爭(二)

一、分析源代碼//index.php // 初始化變量&#xff1a;標記上傳狀態和錯誤消息 $is_upload false; $msg null;// 檢查是否通過POST方式提交了表單 if (isset($_POST[submit])) {// 引入自定義上傳類require_once("./myupload.php");// 生成基于時間戳的文件名&…

一天兩道力扣(3)

解法一&#xff1a;class Solution(object):def invertTree(self, root):if not root:return Noneroot.left, root.right root.right, root.leftself.invertTree(root.right)self.invertTree(root.left)return root解析&#xff1a;遞歸解法二&#xff1a;class Solution(obje…

jenkins2025安裝、插件、郵箱發送使用

Tips&#xff1a;卸載從新安裝(需要在C盤線先刪除.jenkins文件)&#xff0c;然后換個默認瀏覽器從新安裝推薦的插件(不然安裝插件這一步會報錯&#xff0c;連接不到jenkins) 一、jenkins安裝 訪問jenkins官網&#xff1a;https://www.jenkins.io/download/ 雙擊war包開始下載…