人工智能, 生活

使用ModelScope本地运行大语言模型

这是之前调用模型的博文,主要是使用 Ollama 形式、HuggingFace 形式、第三方 API 等:

本篇通过 ModelScope 平台下载模型并运行模型,网络会更稳定;同时,本地运行模型会比 Ollama 更灵活些,支持全精度模型。

这里以 Qwen3-0.6B 为例,官方链接为(全精度和 GGUF 量化版本):

需要安装 ModelScope:

pip install modelscope

如果仅使用 CPU 运行,那么需要的内存大小估算为:

模型参数量全精度 (FP32)INT8 量化INT4 量化
qwen3:0.6b6亿~2.4 GB~0.6 GB~0.3 GB
qwen3:1.7b17亿~6.8 GB~1.7 GB~0.85 GB
qwen3:4b40亿~16 GB~4 GB~2 GB
qwen3:8b80亿~32 GB~8 GB~4 GB
qwen3:14b140亿~56 GB~14 GB~7 GB
qwen3:30b300亿~120 GB~30 GB~15 GB
qwen3:32b320亿~128 GB~32 GB~16 GB
qwen3:235b2350亿~940 GB~235 GB~117.5 GB

一、全精度模型

下载全精度模型:

# 模型下载
from modelscope import snapshot_download
model_dir = snapshot_download('Qwen/Qwen3-0.6B', local_dir='D:/models/Qwen/Qwen3-0.6B')

多轮对话代码例子:

"""
This code is supported by the website: https://www.guanjihuan.com
The newest version of this code is on the web page: https://www.guanjihuan.com/archives/48066
"""

from modelscope import AutoModelForCausalLM, AutoTokenizer
import time

class QwenChatbot:
    def __init__(self, model_name="D:/models/Qwen/Qwen3-0.6B"):
        """
        初始化 Qwen 聊天机器人
        :param model_name: 模型路径
        """
        self.tokenizer = AutoTokenizer.from_pretrained(model_name)  # 加载分词器
        self.model = AutoModelForCausalLM.from_pretrained(model_name)  # 加载模型
        self.history = []  # 存储对话历史

    def generate_response(self, user_input):
        """
        生成模型回复
        :param user_input: 用户输入
        :return: 模型回复
        """
        # 将历史对话和当前用户输入组合成消息列表
        messages = self.history + [{"role": "user", "content": user_input}]

        # 使用聊天模板格式化输入文本
        text = self.tokenizer.apply_chat_template(
            messages,
            tokenize=False,  # 不进行分词,返回字符串
            add_generation_prompt=True  # 添加生成提示
        )

        # 对文本进行分词,并返回PyTorch张量
        inputs = self.tokenizer(text, return_tensors="pt")
        
        # 生成回复,最多生成32768个新token
        response_ids = self.model.generate(**inputs, max_new_tokens=32768)[0][len(inputs.input_ids[0]):].tolist()
        
        # 解码生成的token,跳过特殊token
        response = self.tokenizer.decode(response_ids, skip_special_tokens=True)

        # 更新对话历史
        self.history.append({"role": "user", "content": user_input})
        self.history.append({"role": "assistant", "content": response})

        return response

# 示例使用
if __name__ == "__main__":
    chatbot = QwenChatbot()  # 创建聊天机器人实例

    # 第一次输入(不带/think或/no_think标签,默认启用思考模式)
    start_time = time.time()
    user_input_1 = "计算:1+1"
    print(f"用户: {user_input_1}")
    response_1 = chatbot.generate_response(user_input_1)
    print(f"机器人: {response_1}")
    end_time = time.time()
    print(f"\n--- 分割线(耗时:{end_time-start_time:.2f} 秒) ---\n")

    # 第二次输入带/no_think标签
    start_time = time.time()
    user_input_2 = "确定吗?/no_think"
    print(f"用户: {user_input_2}")
    response_2 = chatbot.generate_response(user_input_2)
    print(f"机器人: {response_2}") 
    end_time = time.time()
    print(f"\n--- 分割线(耗时:{end_time-start_time:.2f} 秒) ---\n")

    # 第三次输入带/think标签
    start_time = time.time()
    user_input_3 = "确定吗?/think"
    print(f"用户: {user_input_3}")
    response_3 = chatbot.generate_response(user_input_3)
    print(f"机器人: {response_3}")
    end_time = time.time()
    print(f"\n--- 分割线(耗时:{end_time-start_time:.2f} 秒) ---\n")

运行结果:

用户: 计算:1+1
机器人: <think>
嗯,我现在要计算的是1加1,对吧?不过先别急着下结论,让我仔细想想。首先,这个题目看起来很简单,但可能有什么陷 阱或者需要注意的地方吗?

首先,1加1,是不是等于2呢?我记得加法的基本原理是,两个相同的数相加,结果就是它们的和。所以1加1,应该是1加1,等于2。不过,可能有没有什么特殊情况需要考虑吗?比如说,是否在不同的数学体系中会有不同的结果?不过一般来说,在标准的加法运算中,1加1的结果是2,对吗?

不过,为了确保万无一失,我应该再检查一下有没有可能哪里弄错了。比如说,有没有可能题目中的数字有误,或者有没有 其他的隐藏含义?比如,是否有可能是1加1的结果不是2,而是其他数值?不过题目里明确写的是1+1,所以应该没错。     

或者,有没有可能这个题目是想让我应用某种特殊的数学规则,比如进位或者某种运算,但这里显然没有这样的情况。比如 ,在十进制中,1加1是2,没问题。在其他进制的话,比如二进制的话,1+1是0,但题目里应该用的是十进制,所以应该没问题。

再想想,有没有可能这个题目是中文的,比如在中文数学题中,有时候会有不同的解释?比如,是否有可能中文里的加法有 不同的符号或解释?不过一般来说,中文的加法符号是加号,即+,所以1+1就是1+1,结果是2。

或者,有没有可能题目是要求用某种方式计算,比如分解成更小的步骤?比如,1+1可以看成是1+1,或者分解成1+1,但不管怎么分解,结果都是2。所以这个结果应该没错。

不过,为了彻底确认,我可以再用不同的方法验证一下。比如说,用数学公式,1+1等于多少?根据数学的基本运算规则,1 加1等于2,没错。或者,可以用代数的方法,比如设x=1,那么x+x=2,所以结果正确。

或者,可以用实际的实物来演示。比如说,如果有1个苹果和1个苹果,那么总共有2个苹果。这时候结果就是2。所以这个思 路是对的。

有没有可能题目中的数字不是1,而是其他数?比如,如果是12+12,那结果就是24,但题目里是1+1,所以应该没错。所以综合以上各种可能性,我应该可以确定1+1的结果是2。

不过,可能有人会误以为1加1的结果是其他数值,比如2或者别的,但显然根据基本的加法原则,答案应该是2。因此,我认 为这个题目的答案应该是2。
</think>

1 + 1 的结果是 2。

**步骤解析:**
1. 加法的基本原理:两个相同的数相加,结果为它们的和。
2. 1 + 1 = 2。

**答案:2**

--- 分割线(耗时:134.47 秒) ---

用户: 确定吗?/no_think
机器人: <think>

</think>

是的,1 + 1 的结果是 **2**。

--- 分割线(耗时:4.72 秒) ---

用户: 确定吗?/think
机器人: <think>
好的,用户之前问过1+1的结果,我给出了答案2。现在用户又问了“确定吗?”,看起来他们可能是在确认这个答案是否正确 ,或者想进一步验证。我需要检查之前的回答是否正确,并确保用户得到明确的结果。

首先,用户可能是在测试我的回答是否正确,或者他们可能希望得到更详细的解释。我需要确认步骤解析是否正确,比如加 法的基本原理是否适用,以及结果是否正确。此外,用户可能是在学习加法,所以需要更清晰的步骤说明。

另外,用户可能没有意识到“确定吗?”的正确用法,可能想确认答案是否正确。这时候我应该直接给出答案,并解释步骤, 确保用户理解。同时,保持回答简洁,避免冗长,让用户容易理解。

总结来说,我需要确认答案的正确性,解释步骤,确保用户明白为什么是2,并且确认他们的问题是否得到了解决。        
</think>

是的,1 + 1 的结果是 **2**。

--- 分割线(耗时:59.95 秒) ---

二、GGUF 量化模型

下载 GGUF 量化格式的模型:

# 模型下载
from modelscope import snapshot_download
model_dir = snapshot_download('Qwen/Qwen3-0.6B-GGUF', local_dir='D:/models/Qwen/Qwen3-0.6B-GGUF')

安装 llama-cpp-python:

pip install llama-cpp-python

多轮对话代码例子:

"""
This code is supported by the website: https://www.guanjihuan.com
The newest version of this code is on the web page: https://www.guanjihuan.com/archives/48066
"""

from llama_cpp import Llama
import time

class QwenChatbotGGUF:
    def __init__(self, model_path="D:/models/Qwen/Qwen3-0.6B-GGUF/Qwen3-0.6B-Q8_0.gguf", n_ctx=32768):
        """
        初始化基于 GGUF 的 Qwen3 聊天机器人
        :param model_path: GGUF 模型文件路径(必须是 Qwen3 的 GGUF 文件)
        :param n_ctx: 上下文长度(Qwen3 支持长上下文,最大可设 32768)
        """
        self.llm = Llama(
            model_path=model_path,
            n_ctx=n_ctx,
            verbose=False,
            chat_format="chatml",  # Qwen 使用 ChatML 格式
            logits_all=False
        )
        self.history = []

    def generate_response(self, user_input):
        """
        生成模型回复
        :param user_input: 用户输入文本
        :return: 模型回复文本
        """
        # 将当前输入加入历史(role=user)
        self.history.append({"role": "user", "content": user_input})

        # 使用 llama.cpp 内置的 chat completion(自动处理模板)
        response = self.llm.create_chat_completion(
            messages=self.history,
            max_tokens=2048,
            temperature=0.6,
            top_p=0.95,
            repeat_penalty=1.5,
        )

        # 提取助手回复内容
        assistant_message = response["choices"][0]["message"]["content"].strip()

        # 将助手回复加入历史
        self.history.append({"role": "assistant", "content": assistant_message})

        return assistant_message

# 示例使用
if __name__ == "__main__":
    chatbot = QwenChatbotGGUF()  # 创建聊天机器人实例

    # 第一次输入
    start_time = time.time()
    user_input_1 = "计算:1+1"
    print(f"用户: {user_input_1}")
    response_1 = chatbot.generate_response(user_input_1)
    print(f"机器人: {response_1}")
    end_time = time.time()
    print(f"\n--- 分割线(耗时:{end_time - start_time:.2f} 秒) ---\n")

    # 第二次输入(带 /no_think)
    start_time = time.time()
    user_input_2 = "确定吗?/no_think"
    print(f"用户: {user_input_2}")
    response_2 = chatbot.generate_response(user_input_2)
    print(f"机器人: {response_2}")
    end_time = time.time()
    print(f"\n--- 分割线(耗时:{end_time - start_time:.2f} 秒) ---\n")

    # 第三次输入(带 /think)
    start_time = time.time()
    user_input_3 = "确定吗?/think"
    print(f"用户: {user_input_3}")
    response_3 = chatbot.generate_response(user_input_3)
    print(f"机器人: {response_3}")
    end_time = time.time()
    print(f"\n--- 分割线(耗时:{end_time - start_time:.2f} 秒) ---\n")

运行结果:

用户: 计算:1+1
机器人: <think>
嗯,我现在要计算的是1加起来的结果。首先我应该回忆一下基本的数学运算规则吧?对了,在算术中通常就是相加之和。

不过让我仔细想想有没有什么需要注意的地方或者可能出错的情况呢?比如是不是有时候会有不同的解释方式导致结果不同?

比如说在某些情况下可能会有不同的理解,但一般来说1加起来的结果应该是简单的。例如数字之间的基本操作应该不会有问题吧!

再考虑一下运算符的优先级问题吗?」通常来说,在数学表达式中先算乘除法、括号里的内容之后才是添加减去之类的顺序对不对?不过在这个例子里没有遇到任何需要处 理的地方,所以直接相加应该是可以接受的方式。

有没有可能用户在这里有其他的意思或者意图呢?”比如是不是在某个特定的上下文中进行的操作不同?

比如说如果是数字之间的一些转换操作或者其他类型的运算吗?」但根据问题描述中的符号“+”和结果1的话应该就是普通的整数添加了,没有疑问或额外条件需要考虑进去 。

再检查一遍数值是否正确。原题是计算:1 + 1的结果是多少?显然正确的答案应该是2!

有没有可能我哪里弄错了呢?”比如是不是把加号看成了其他符号或者数字的某种组合?

例如如果是写成“+”而不是其他的运算符,还是有误吗?」不过这里的表达式看起来已经很明确地用了中文中的算术操作。所以应该没问题。

总结一下:1 + 1 = 2。
</think>

计算结果是:

$$
1 + 1 = \boxed{2}
$$

--- 分割线(耗时:11.80 秒) ---

用户: 确定吗?/no_think
机器人: <think>

</think>
是的,1加起来的结果确实是2。

--- 分割线(耗时:2.98 秒) ---

用户: 确定吗?/think
机器人: <think>
好的,用户问“确定吗?”我需要确认之前回答是否正确。之前的计算是1+1=2,并且已经用中文表达清楚了。

现在我要检查是否有其他可能的解释或需要注意的地方。比如是否存在不同的运算顺序、符号使用问题或者其他潜在的问题?

没有发现任何矛盾之处的情况下,在数学中,加法和减法的操作遵循优先级规则:先进行乘除后是加上去的话不需要考虑括号或其他因素即可直接相加以得到结果。

因此结论仍然是正确的,并且用户可能需要确认答案的准确性或进一步解释。如果他们有其他问题或者想验证计算过程,请随时提问!

--- 分割线(耗时:4.56 秒) ---
10 次浏览

【说明:本站主要是个人的一些笔记和代码分享,内容可能会不定期修改。为了使全网显示的始终是最新版本,这里的文章未经同意请勿转载。引用请注明出处:https://www.guanjihuan.com

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

Captcha Code