开源模型应用落地-工具使用篇-Ollama(六)

一、前言

在AI大模型百花齐放的时代,很多人都对新兴技术充满了热情,都想尝试一下。但是,实际上要入门AI技术的门槛非常高。除了需要高端设备,还需要面临复杂的部署和安装过程,这让很多人望而却步。不过,随着开源技术的不断进步,使得入门AI变得越来越容易。通过使用Ollama,您可以快速体验大语言模型的乐趣,不再需要担心繁琐的设置和安装过程。


二、术语

2.1、Ollama

是一个强大的框架,用于在 Docker 容器中部署 LLM(大型语言模型)。它的主要功能是在 Docker 容器内部署和管理 LLM 的促进者,使该过程变得简单。它可以帮助用户快速在本地运行大模型,通过简单的安装指令,用户可以执行一条命令就在本地运行开源大型语言模型。

Ollama 支持 GPU/CPU 混合模式运行,允许用户根据自己的硬件条件(如 GPU、显存、CPU 和内存)选择不同量化版本的大模型。它提供了一种方式,使得即使在没有高性能 GPU 的设备上,也能够运行大型模型。

2.2、Qwen1.5

Qwen1.5 is the beta version of Qwen2, a transformer-based decoder-only language model pretrained on a large amount of data. In comparison with the previous released Qwen, the improvements include:

  • 6 model sizes, including 0.5B, 1.8B, 4B, 7B, 14B, and 72B;
  • Significant performance improvement in human preference for chat models;
  • Multilingual support of both base and chat models;
  • Stable support of 32K context length for models of all sizes
  • No need of trust_remote_code.

三、前置条件

3.1、Ollama安装

下载地址:Download Ollama on macOS

支持macOS、Linux以及windows,此处以windows操作系统为例:

点击OllmaSetup.exe进行安装,当前安装版本为0.1.27

安装完成后,在C:\Users\用户名\AppData\Local\Ollama目录下,有Ollama的配置及日志文件

也可以在右下角快速点开

查看版本


四、使用方式

4.1、运行Qwen1.5-1.8B-Chat模型

ollama run qwen:1.8b

五、测试

5.1、命令行方式测试

5.2、代码方式测试

默认Ollama api会监听11434端口,可以使用命令进行查看

netstat -ano | findstr 11434

安装requests库

python 复制代码
pip install requests -i https://pypi.douban.com/simple
python 复制代码
# -*-  coding = utf-8 -*-
import json
import sys
import traceback
import logging

#######################日志配置#######################
import requests
from requests.adapters import HTTPAdapter

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s]: %(message)s',  # 指定日志输出格式
    datefmt='%Y-%m-%d %H:%M:%S'  # 指定日期时间格式
)

# 创建一个日志记录器
formatter = logging.Formatter('%(asctime)s [%(levelname)s]: %(message)s')  # 指定日志输出格式
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

if sys.platform == "linux":
    # 创建一个文件处理器,将日志写入到文件中
    file_handler = logging.FileHandler('/data/logs/app.log')
else:
    # 创建一个文件处理器,将日志写入到文件中
    file_handler = logging.FileHandler('E:\\logs\\app.log')

file_handler.setFormatter(formatter)
# 创建一个控制台处理器,将日志输出到控制台
# console_handler = logging.StreamHandler()
# console_handler.setFormatter(formatter)

# 将处理器添加到日志记录器中
logger.addHandler(file_handler)
# logger.addHandler(console_handler)

DEFAULT_MODEL = "qwen:1.8b-chat"
DEFAULT_IP='127.0.0.1'
DEFAULT_PORT=11434
DEFAULT_MAX_TOKENS = 32768
DEFAULT_CONNECT_TIMEOUT=3
DEFAULT_REQUEST_TIMEOUT=60
DEFAULT_MAX_RETRIES=0
DEFAULT_POOLSIZE=100

class Model:
    def __init__(self):
        self.headers = {"User-Agent": "Test Client"}
        self.s = requests.Session()
        self.s.mount('http://', HTTPAdapter(pool_connections=DEFAULT_POOLSIZE, pool_maxsize=DEFAULT_POOLSIZE, max_retries=DEFAULT_MAX_RETRIES))
        self.s.mount('https://', HTTPAdapter(pool_connections=DEFAULT_POOLSIZE, pool_maxsize=DEFAULT_POOLSIZE, max_retries=DEFAULT_MAX_RETRIES))

    def chat(self, message, history=None, system=None, config=None, stream=True):
        if config is None:
            config = {'temperature': 0.45, 'top_p': 0.9, 'repetition_penalty': 1.2, 'max_tokens': DEFAULT_MAX_TOKENS,'n':1}
        logger.info(f'config: {config}')

        messages = []
        if system is not None:
            messages.append({"role": "system", "content": system})

        if history is not None:
            if len(history) > 0 and len(history) % 2 == 0:
                for his in history:
                    user,assistant = his

                    user_obj = {"role": "user", "content": user}
                    assistant_obj = {"role": "assistant", "content": assistant}

                    messages.append(user_obj)
                    messages.append(assistant_obj)

        if message is None:
            raise RuntimeError("prompt不能为空!")
        else:
            messages.append({"role": "user", "content": message})
        logger.info(messages)
        try:
            merge_pload = {"model": DEFAULT_MODEL, "messages": messages, **config}
            logger.info(merge_pload)

            response = self.s.post(f"http://{DEFAULT_IP}:{DEFAULT_PORT}/api/chat", headers=self.headers,
                                   json=merge_pload, stream=stream, timeout=(DEFAULT_CONNECT_TIMEOUT, DEFAULT_REQUEST_TIMEOUT))
            str = ''
            for msg in response:
                # logger.info(msg)
                if msg and len(msg) > 0:
                    decode_msg = msg.decode('UTF-8')
                    if '\n' in decode_msg :
                        if len(str) == 0:
                            obj = json.loads(decode_msg)
                            if 'message' in obj:
                                content = obj['message']['content']
                                if content is not None:
                                    yield content
                        else:
                            str = str + decode_msg
                            obj = json.loads(str)
                            if 'message' in obj:
                                content = obj['message']['content']
                                if content is not None:
                                    str=''
                                    yield content
                    else:
                        str = str + decode_msg
        except Exception as e:
            traceback.print_exc()


if __name__ == '__main__':
    model = Model()
    message = '我家有什么特产?'
    system = 'You are a helpful assistant.'
    history = [('hi,你好','你好!有什么我可以帮助你的吗?'),('我家在广州,很好玩哦','广州是一个美丽的城市,有很多有趣的地方可以去。'),]
    config = {'temperature': 0.45, 'top_p': 0.9, 'repetition_penalty': 1.2, 'max_tokens': 8192}
    gen = model.chat(message=message, history=history, system=system, config=config, stream=True)
    results = []
    for value in gen:
        results.append(value)
    str = ''.join(results)
    logger.info(str)

模型参数:

Ollama Api返回的数据格式以**\n结尾,但由于流式返回,可能存在多行输出再返回\n**的情况:

测试结果:


六、附带说明

6.1、各操作系统下的安装步骤

https://github.com/ollama/ollama

6.2、Ollama支持的模型库

https://ollama.com/library

6.3、运行各规格qwen模型的命令

https://registry.ollama.ai/library/qwen/tags

6.4、问题

重试几次或者换另外规格的模型

6.5、代码中传递给Ollama Api的模型参数,要和运行的模型一致,即

6.6、Ollama常用命令

# list

# show

# delete

等等,可以查阅: https://github.com/ollama/ollama/blob/main/cmd/cmd.go

相关推荐
学术头条2 小时前
清华、智谱团队:探索 RLHF 的 scaling laws
人工智能·深度学习·算法·机器学习·语言模型·计算语言学
18号房客2 小时前
一个简单的机器学习实战例程,使用Scikit-Learn库来完成一个常见的分类任务——**鸢尾花数据集(Iris Dataset)**的分类
人工智能·深度学习·神经网络·机器学习·语言模型·自然语言处理·sklearn
Ven%2 小时前
如何在防火墙上指定ip访问服务器上任何端口呢
linux·服务器·网络·深度学习·tcp/ip
IT猿手2 小时前
最新高性能多目标优化算法:多目标麋鹿优化算法(MOEHO)求解TP1-TP10及工程应用---盘式制动器设计,提供完整MATLAB代码
开发语言·深度学习·算法·机器学习·matlab·多目标算法
强哥之神3 小时前
Nexa AI发布OmniAudio-2.6B:一款快速的音频语言模型,专为边缘部署设计
人工智能·深度学习·机器学习·语言模型·自然语言处理·音视频·openai
18号房客3 小时前
一个简单的深度学习模型例程,使用Keras(基于TensorFlow)构建一个卷积神经网络(CNN)来分类MNIST手写数字数据集。
人工智能·深度学习·机器学习·生成对抗网络·语言模型·自然语言处理·tensorflow
神秘的土鸡3 小时前
神经网络图像隐写术:用AI隐藏信息的艺术
人工智能·深度学习·神经网络
数据分析能量站3 小时前
神经网络-LeNet
人工智能·深度学习·神经网络·机器学习
Jaly_W3 小时前
用于航空发动机故障诊断的深度分层排序网络
人工智能·深度学习·故障诊断·航空发动机
FL16238631294 小时前
钢材缺陷识别分割数据集labelme格式693张4类别
深度学习