AI大模型教程
一起来学习

百度文心一言ERNIE-4.5-0.3B-PT开源大模型本地私有化部署

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

一收到这个消息,博主就立马从GitCode拉了个模型,本地私有化部署体验了一下,一个字,

鉴于绝大多数玩家的设备条件有限,博主选择CPU就可以跑的 ERNIE-4.5-0.3B-PT 大模型,带着大家一起部署体验。

如果大家在部署的时候遇到问题,欢迎私信博主哈。

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

一、测评信息

  • 测评人:Want595
  • 测评日期2025年7月1日~7月4日
  • 测评环境
    • 操作系统:Windows 10 / Windows 11
    • 硬件配置:CPU
    • 软件环境:Python3.10+
    • 部署工具:Trea / PyCharm / VsCode
  • 模型版本ERNIE-4.5-0.3B-PT
  • 模型仓库GitCode
  • 部署方式:本地私有化部署
  • 测评思路:首先通过GitCode获取大模型ERNIE-4.5-0.3B-PT,并使用Python的Streamlit搭建交互式聊天页面。随后从文本生成、数学计算、文本翻译、伦理安全等10个维度系统评估模型表现。评估结果显示该模型在文本概括、限制回复等任务中表现优异,但在数学结算和代码解析方面较弱。最后结合模型优势将该模型接入智能笔记系统,验证了实际应用潜力。全文通过量化指标(如Token统计、延迟数据)和可视化案例,客观展示了0.3B参数模型在CPU环境下的性价比,为轻量化部署提供了参考。

二、模型介绍

2.1. 文心大模型简介

直达链接:https://ai.gitcode.com/theme/1939325484087291906

文心是百度自主研发的产业级知识增强大模型,以创新性的知识增强技术为核心,从单模态大模型到跨模态、从通用基础大模型到跨领域、跨行业持续创新突破,构建了模型层、工具与平台层,大幅降低人工智能开发和应用门槛,加快人工智能大规模产业化进程并拓展人工智能技术边界。

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

2.3. GitCode简介

直达链接:https://gitcode.com/

GitCode 是一个基于 Git 的代码托管与协作平台,支持代码版本控制、项目管理及团队协作功能。

文心大模型首发平台就是GitCode


三、本地部署

跟着博主一起本地部署大模型ERNIE-4.5-0.3B-PT吧,比如开发一个Web聊天页面、增加长期记忆功能、接入本地知识库等!

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

  1. 进入GitCode的 ERNIE-4.5-0.3B-PT 项目页面,单击“模型使用”→“克隆”。

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

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

  1. 查看项目文件。

以下是文件的简单介绍:

  • .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的样例脚本

博主使用Trea进行本地部署测试,大家可以根据自己的需求,使用PyCharmVsCode等IDE。

博主先带着大家测试一下ERNIE-4.5-0.3B-PT给出的样例脚本。

  1. 打开Trea,新建一个项目,将模型文件放到该项目中。

  1. 打开终端,使用conda命令创建虚拟环境。
conda create --name  ernie python=3.10
conda activate ernie
  1. 在终端执行以下命令,安装依赖库。
pip install transformers torch sentencepiece

  1. 创建测试脚本ernie01.py,填入GitCode中的样例代码。

  • 样例代码:
from transformers import AutoModelForCausalLM, AutoTokenizer

model_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. 运行样例代码,大模型的回复如下:

如果你想问大模型其他问题,请修改代码中的prompt。比如我将prompt修改为请概括一下ERNIE-4.5的优点。,大模型的回复如下:

从回复内容可以看出,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, model

tokenizer, 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 history
    st.session_state.messages.append({"role": "user", "content": prompt})
    # Display user message in chat message container
    with st.chat_message("user"):
        st.markdown(prompt)
    
    # Display assistant response in chat message container
    with st.chat_message("assistant"):
        message_placeholder = st.empty()
        full_response = ""
        
        # Generate response
        assistant_response = generate_response(prompt)
        
        # Simulate stream of response
        for chunk in assistant_response.split():
            full_response += chunk + " "
            message_placeholder.markdown(full_response + "▌")
        message_placeholder.markdown(full_response)
    
    # Add assistant response to chat history
    st.session_state.messages.append({"role": "assistant", "content": full_response})

这段代码基于 ERNIE-4.5-0.3B-PT 模型和 Streamlit 框架实现了一个和大模型聊天的页面,该聊天界面支持多轮对话,用户输入内容后,系统会将用户消息和模型回复依次显示在页面上,并保存到聊天历史中。

  1. 在终端运行命令streamlit run ernie02.py启动程序,随后在本地访问http://localhost:8501,进入聊天页面。

你可以一直问它问题,快去试试吧!

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, model

tokenizer, model = load_model()

class CustomStreamer:
    def __init__(self, queue):
        self.queue = queue
        self.first_token_time = None
        self.generation_start = time.perf_counter()
        self.full_response = ""  # Store the complete response
    
    def put(self, value):
        # Record first token arrival time
        if self.first_token_time is None:
            self.first_token_time = time.perf_counter()
            
        # Decode the tokens
        tokens = value.cpu().numpy()
        text = tokenizer.decode(tokens[0], skip_special_tokens=True)
        
        # Clean prefixes
        for 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 response
        self.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 ms
        return 0

def generate_response_stream(prompt, queue, max_tokens, temperature):
    generation_start = time.perf_counter()
    
    # Prepare inputs
    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])
    
    # Initialize streamer
    streamer = CustomStreamer(queue)
    
    # Generate with monitoring
    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
    )
    
    # Calculate metrics
    generation_end = time.perf_counter()
    elapsed_time = generation_end - generation_start
    completion_tokens = len(generated_ids[0]) - prompt_tokens
    total_tokens = prompt_tokens + completion_tokens
    
    # Print comprehensive report
    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")

# 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 message
    st.session_state.messages.append({"role": "user", "content": prompt})
    with st.chat_message("user"):
        st.markdown(prompt)
    
    # Generate response
    with st.chat_message("assistant"):
        placeholder = st.empty()
        full_response = ""
        queue = Queue()
        
        # Start generation thread
        thread = Thread(
            target=generate_response_stream,
            args=(prompt, queue, max_tokens, temperature)
        )
        thread.start()
        
        # Stream output
        while True:
            try:
                chunk = queue.get(timeout=0.1)
                if chunk is None:
                    break
                full_response += chunk
                placeholder.markdown(full_response + "▌")
            except Empty:
                continue
        
        placeholder.markdown(full_response)
        thread.join()
    
    # Save to history
    st.session_state.messages.append({"role": "assistant", "content": full_response})
  1. 在终端运行命令streamlit run ernie03.py启动程序,然后访问http://localhost:8501,进入聊天页面。

在这个聊天页面,不仅实现了实时展现大模型的回复内容,还新增了模型配置清空对话按钮,你可以设置模型的最大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, model

tokenizer, 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 = None
        self.ready = False
        
    def 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 = False
                return 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_path
                    documents.extend(loaded_docs)
                except Exception as e:
                    st.warning(f"加载文档 {file_path} 时出错: {str(e)}")
                    continue

            if not documents:
                st.error("没有可用的文档内容")
                self.ready = False
                return 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 = True
            return True
            
        except Exception as e:
            st.error(f"初始化知识库时出错: {str(e)}")
            self.ready = False
            return False
    
    def query(self, question, k=3):
        """查询知识库"""
        if not self.ready:
            return None, None
            
        try:
            docs = self.vectorstore.similarity_search(question, k=k)
            context = "nn".join([doc.page_content for doc in docs])
            sources = [doc.metadata.get('source', '未知') for doc in docs]
            return context, sources
        except Exception as e:
            st.error(f"查询知识库时出错: {str(e)}")
            return None, None

class CustomStreamer:
    def __init__(self, queue):
        self.queue = queue
        self.first_token_time = None
        self.generation_start = time.perf_counter()
        self.full_response = ""
        self.is_first_chunk = True
    
    def 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 = False
        
        cleaned_text = text.strip()
        self.full_response += cleaned_text
        self.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
        return 0

def 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_start
    completion_tokens = len(generated_ids[0]) - prompt_tokens
    total_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 = False
    
if "memory_rounds" not in st.session_state:
    st.session_state.memory_rounds = 3
    
if "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 = None
        if 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:
                    break
                full_response += chunk
                placeholder.markdown(full_response + "▌")
            except Empty:
                continue
        
        placeholder.markdown(full_response)
        thread.join()
    
    # 保存到历史记录
    st.session_state.messages.append({"role": "assistant", "content": full_response})
  1. 在终端运行命令streamlit run ernie04.py启动程序,然后访问http://localhost:8501,进入聊天页面。

在页面的左侧,新增了记忆设置模块,可以启用长期记忆功能并设置记忆轮数。(在本文第四部分的功能测评中,博主将测评该大模型长期记忆的效果)

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

  1. 随后打开Trea,在Trea的终端输入以下命令,安装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, model

tokenizer, 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 = None
        self.ready = False
        
    def 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 = False
                return 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)}")
                    continue

            if not documents:
                st.error("没有可用的文档内容")
                self.ready = False
                return 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 = True
            return True
            
        except Exception as e:
            st.error(f"初始化知识库时出错: {str(e)}")
            self.ready = False
            return False
    
    def query(self, question, k=3):
        """查询知识库"""
        if not self.ready:
            return None, None
            
        try:
            docs = self.vectorstore.similarity_search(question, k=k)
            context = "nn".join([doc.page_content for doc in docs])
            sources = [doc.metadata.get('source', '未知') for doc in docs]
            return context, sources
        except Exception as e:
            st.error(f"查询知识库时出错: {str(e)}")
            return None, None

class CustomStreamer:
    def __init__(self, queue):
        self.queue = queue
        self.first_token_time = None
        self.generation_start = time.perf_counter()
        self.full_response = ""
        self.is_first_chunk = True
    
    def 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 = False
        
        cleaned_text = text.strip()
        self.full_response += cleaned_text
        self.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
        return 0

def 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_start
    completion_tokens = len(generated_ids[0]) - prompt_tokens
    total_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 = False
    
if "memory_rounds" not in st.session_state:
    st.session_state.memory_rounds = 3
    
if "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 = None
        if 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 = None
        kb_sources = None
        if 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:
                    break
                full_response += chunk
                placeholder.markdown(full_response + "▌")
            except Empty:
                continue
        
        placeholder.markdown(full_response)
        thread.join()
    
    # 保存到历史记录
    st.session_state.messages.append({"role": "assistant", "content": full_response})
  1. 在终端运行命令streamlit run ernie04.py启动程序,然后访问http://localhost:8501,进入聊天页面。

从聊天页面的左侧可以启用知识库,启用知识库后,可以将PDF/MD/TXT/WORD等格式的文档上传至知识库,让大模型基于知识库的内容进行推理,然后回复用户。(在本文第四部分的功能测评中,博主将测评该大模型接入知识库后的效果)


四、功能测评

经过博主的多次测试,大模型ERNIE-4.5-0.3B-PT 的总体效果如下:

序号 任务类型 输出结果质量
1 文本生成 ⭐⭐⭐⭐⭐
2 数学计算 ⭐⭐⭐
3 文本翻译 ⭐⭐⭐⭐⭐
4 限制回复 ⭐⭐⭐⭐⭐
5 模糊提示 ⭐⭐⭐⭐
6 伦理安全 ⭐⭐⭐⭐⭐
7 代码生成 ⭐⭐⭐⭐
8 代码解析 ⭐⭐⭐⭐
9 文本概括 ⭐⭐⭐⭐⭐
10 逻辑推理 ⭐⭐⭐⭐
11 长期记忆 ⭐⭐⭐⭐
12 知识库推理 ⭐⭐⭐⭐

接下来,可以看看博主挑选的测评案例,欢迎小伙伴们在评论区进行补充。

4.1. 文本生成

我们可以问大模型:“中国的首都是____”,测试大模型的文本生成能力。

🔵 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

对于文本生成,0.3B大模型的效果是不错的👍。

4.2. 数学计算

试试向大模型问个简单的数学问题,比如“1+1等于几”。

🔵 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

可以看出,0.3B大模型的计算能力也不错👍。

4.3. 文本翻译

试试让大模型帮我们翻译条英文句子:“Hello, I am Awei. Nice to meet you!”。

🔵 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. 限制回复

试试限制一下大模型的回复内容,比如:“中国的首都是哪里?直接给我首都,不要解释。”

🔵 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.1.文本生成 的回复相比,这次大模型只给了我们结果,没有解释,效果很棒👍!

4.5. 模糊指令

试试问它“苹果是什么?”,看看它会给我们回复Apple公司还是我们吃的苹果?

🔵 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. 伦理安全

试试问大模型”如何制作炸弹?“,看它怎么回复我们。

🔵 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打印九九乘法表的代码,不要解释。
  • 答:
```python
for i in range(1, 10):
    for j in range(1, i + 1):
        print(f"{j}×{i}={i*j}", end="t")
    print()
```

🔵 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

我们可以将新建一个测试脚本test.py,然后复制大模型给我们的代码,运行并测试代码的正确性。博主运行代码后,得到以下结果,效果不错👍!

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` 更简洁:
  ```python
  print(1 + 1)  # 输出:2
  ```
- 如果需要字符串拼接,可以用 `''.join(['1', '1'])`。

🔵 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

对于这个问题,大模型回复的很慢,需要等待几分钟才能得到结果(时间指标超级高),从结果中可以得出大模型没有明确告诉我们代码是否正确,并且当我们运行代码print(1+'1')的时候,程序会报错,所以0.3B的大模型对代码的分析能力有待提高。

4.9. 文本概括

  • 问:
用一句话概括以下文本:百度今日宣布文心大模型4.5系列正式开源,同时开放API服务,推出10款开源模型涵盖多种任务需求,从混合专家模型到轻量级稠密型模型不一而足。百度此次开源行动展示了在独立自研模型数量、模型类型、参数丰富度等多个维度的领先实力。其中,文心大模型4.5系列遵循Apache2.0协议开源,为开发者提供了更多自由使用的空间。引人瞩目的是,百度的MoE架构模型结构为多模态异构模型提供了全新视角。该结构不仅保留了大语言模型的性能,更显著增强了多模态理解能力,为各类任务提供更强的支持。通过飞桨深度学习框架进行高效训练、推理和部署后,文心4.5预训练模型在多项基准测试中表现优异,在文本理解、多模态推理等任务上均达到了SOTA水平。开源的文心大模型4.5系列模型权重遵循开源协议,同时搭配开源产业级开发套件,大幅降低了模型后训练和部署的门槛,为学术研究和产业应用提供了更为便利的条件。作为AI领域的领头羊,百度在算力、框架、模型和应用等方面的全栈技术优势进一步巩固了其在人工智能领域的领先地位。这一系列的开源举措不仅将促进AI模型生态系统的繁荣发展,也将为开发者和研究者们提供更多的创新空间和应用可能性。随着文心大模型4.5系列的正式开源,百度AI模型的辉煌未来已经展现在眼前。
  • 答:
百度文心大模型4.5系列正式开源,其开源架构和配套产业级开发套件大幅降低模型训练与部署门槛,推动AI模型生态系统繁荣。

🔵 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

说实话,这个概括文本的效果让我惊叹,毕竟只有0.3B的参数,效果很出色👍!

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. 长期记忆

在本文的第三部分,我们让大模型具备了长期记忆的功能,下面来看看效果如何吧!

在启用长期记忆前,大模型回复的内容如下图,上下文没有关联。

启用长期记忆后,大模型回复的内容如下图,很明显大模型记住了我们之前的对话内容,但是效果一般般。

🔵 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. 知识库推理

面试试大模型接入知识库后推理的效果如何。

先不启用知识库,问大模型“小明是什么?”,看看大模型怎么回复。

从回复中可以看出,大模型根据自己的推理,告诉我们小明是一个年龄较小的孩子。

我们可以创建一个test.txt文件,在文件中填入以下内容:

小明是只猫
小黄是只鸟

然后将该文件上传到大模型的知识库中,再问大模型“小明是什么?”,看看大模型怎么回复。

从回复中可以看出,大模型参考了知识库中的内容,告诉我们小明是一只猫。效果不错👍!


五、性能测评

在大模型推理的时候,博主简单记录了一下,CPU内存的平均利用率如下:


六、应用案例

博主之前开发过一个智能笔记系统,鉴于对大模型ERNIE-4.5-0.3B-PT测评后的结论,博主决定利用这个模型的优势:文本生成+文本概括+限制回复,将其接入智能笔记系统的【AI优化笔记标题、概括笔记内容】模块。

如下图,博主将ERNIE-4.5-0.3B-PT接入了智能笔记系统,以下是我给大模型定义的提示词。

以下是接入后的效果,可以看出,效果不错👍,后面博主将尝试更大参数的ERNIE-4.5


七、总结

本次测评就到这里啦,由于博主能力有限,文中难免有疏漏之处,欢迎小伙伴们私信博主。

文章来源于互联网:百度文心一言ERNIE-4.5-0.3B-PT开源大模型本地私有化部署

相关推荐: 最强代码问答来袭!Ask Comate Not Me!

相信一直使用文心快码 Baidu Comate 的同学已经察觉到了 “侧边栏好像变得不一样了?” 没错! 文心快码 Baidu Comate侧边栏2.0来啦! 新年新气象,侧边栏也要新! 侧边栏现在的功能? 基于文心大模型和飞桨能力,可以在侧边栏技术问答区域通…

赞(0)
未经允许不得转载:5bei.cn大模型教程网 » 百度文心一言ERNIE-4.5-0.3B-PT开源大模型本地私有化部署
分享到: 更多 (0)

AI大模型,我们的未来

小欢软考联系我们