# 基于DCU开源代码适配Ollama

#### 现有问题:

1. export HIP_VISIBLE_DEVICES=2,3,4,5 等多卡后, ollama依然会优先加载所有模型到2号卡。随机会加载模型到其他卡;
2. v0.1.43不支持gemma2;
3. 自测NV上ollama-v0.3.4的模型调度逻辑: 在多卡环境下, 并非多卡去推理一个模型。而是一张卡推一个模型。一个模型只可能会在1张卡上。假如说同时 run 了8个模型，那均衡分配8个模型到8张卡上面。超出8个模型之后, 同一张卡上会有多个模型。

本工程的v0.3.5的多卡环境下模型调度策略已经和NV一致.

v0.3.5: https://developer.hpccube.com/codes/wangkx1/ollama_dcu/-/tree/v0.3.5 


#### 拓展: ollama + open-webui: 

教程见: [./tutorial_ollama/01-ollama_open-webui.md](./tutorial_ollama/01-ollama_open-webui.md)


## 适配步骤

工程地址：http://developer.hpccube.com/codes/wangkx1/ollama_dcu.git

### **1. 拉取工程, 根据readme解压构建ollama的压缩文件;**

```bash
git clone http://developer.hpccube.com/codes/wangkx1/ollama_dcu.git

cd ollama_dcu

cp -r /opt/hyhal ./
tar -zxvf cmake-3.29.3.tgz

```

### **2. 根据注释, 修改Dockerfile，构建ollama镜像修改后的Dockerfile 内容如下:**


```bash
FROM image.sourcefind.cn:5000/dcu/admin/base/pytorch:2.1.0-ubuntu20.04-dtk24.04.1-py3.10

# Set the working directory in the container
WORKDIR /app

COPY hyhal /opt/hyhal

COPY . /app/

RUN ls -h

# 如果拉取失败，更换python源
RUN pip install --no-cache-dir -r /app/ollama/llm/llama.cpp/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

# 当前设备型号（如：gfx906，gfx928等）
ENV AMDGPU_TARGETS=gfx928
# HSA_OVERRIDE_GFX_VERSION=设备型号（如: gfx906对应9.0.6；gfx928对应9.2.8）
ENV HSA_OVERRIDE_GFX_VERSION=9.2.8
ENV HIP_PATH=/opt/dtk/hip
ENV ROCM_PATH=/opt/dtk
ENV CMAKE_PREFIX_PATH=/opt/dtk/lib/cmake/amd_comgr:$CMAKE_PREFIX_PATH
ENV LIBRARY_PATH=/opt/dtk/llvm/lib/clang/15.0.0/lib/linux/:$LIBRARY_PATH
ENV HIP_VISIBLE_DEVICES=0,1,2,3,4,5,6,7

RUN tar -C /usr/local -xzf go1.22.3.linux-amd64.tar.gz
ENV PATH=/app/ollama:/usr/local/go/bin:$PATH

RUN go env -w GO111MODULE=on
RUN go env -w GOPROXY=https://goproxy.cn,direct

ENV PATH=/app/cmake-3.29.3-linux-x86_64/bin:$PATH

RUN cmake --version

WORKDIR /app/ollama/llm/generate
RUN bash gen_linux.sh

WORKDIR /app/ollama
RUN go build

WORKDIR /app
```

### **3. Dockerfile 修改完毕后, 执行如下命令, 开始构建镜像;**

```bash
# sudo docker build -t <镜像名字> .  # ollama_k100ai 可以更改为自己想要的镜像名字
# 构建涉及到大规模的代码编译, 时间预计花费15分钟左右
sudo docker build -t ollama_k100ai .
```

### **4. 构建成功，查看镜像**

```bash
(base) sugon@ailab:~$ sudo docker images
[sudo] password for sugon: 
REPOSITORY                                        TAG                                   IMAGE ID       CREATED              SIZE
ollama_k100ai                                     latest                                b60143c747ea   About a minute ago   19.7GB
image.sourcefind.cn:5000/dcu/admin/base/pytorch   2.1.0-ubuntu20.04-dtk24.04.1-py3.8    a474220de118   5 weeks ago          17.2GB
image.sourcefind.cn:5000/dcu/admin/base/pytorch   2.1.0-ubuntu20.04-dtk24.04.1-py3.10   a4dd5be0ca23   6 weeks ago          17.1GB
```


### **5. 进入容器**

进入指定文件夹： `cd tutorial_ollama`


<font color=red>**注意点:**</font>
- `launch_` 前缀的脚本之中的 `export MY_CONTAINER="sg_t0"`, `sg_t0` 是容器的名字，需要自己修改，使得名字需要唯一，才能启动属于自己的容器。如果名字重复很可能会进入别人的容器;


<font color=red>**进入容器的方法:**</font>

- 终端执行:  `sudo bash launch_ollama.sh 1` 
- 验证是否已经进入容器, 容器内部没有安装docker, 在终端执行docker, 如果执行失败, 则进入成功; 如果打印docker的参数介绍，则进入失败，需要重新执行`sudo bash launch_ollama.sh 1`
- 大家感兴趣的可以用大模型去了解下 `launch_ollama.sh` 的脚本内容
### **6. 启动 ollama**


<font color=red>**注意:**</font>

- 为了避免启动ollama服务时出现端口已经被占用的情况, 可以选择 1024-65535之间的任意端口重新设置; 
- 使用 `export HIP_VISIBLE_DEVICES=` 指定使用哪张卡
- 将`ollama`加入环境变量: `export PATH=/app/ollama:$PATH`
- 如果有迁移的本地模型仓库, 需要增加环境变量: `export OLLAMA_MODELS=/local—model-path`


<font color=red>**设置关键环境变量步骤，只需要设置一次即可:**</font>

```bash

# 前提，确保已经进入容器

vim ~/.bashrc, 键盘输入 i


export HIP_VISIBLE_DEVICES=0
export OLLAMA_HOST="0.0.0.0:28120(将28120替换为自己选择的端口号)"
export PATH=/app/ollama:$PATH

切换至英文输入法, 键盘输入: Esc 后, 输入 wq + enter , 保存退出;
激活环境变量:  source ~/.bashrc
```




<font color=red>**建议启动ollama容器的方法:**</font>

在终端执行:

`ollama serve &`


说明:

- 命令末尾使用`空格 + &`结尾, 直接将启动的ollama设置到后台执行, 如果需要停止 ollama 服务, 进入容器后, 执行 `pkill ollama`
### **7. ollama 拉取模型**

ollama 模型仓: https://ollama.com/library

<font color=red>**建议ollama拉取模型的方法:**</font>

- 前提: 
    1. 确保当前处于容器之中, 可以参考`1 进入容器`确认自己进入容器
    2. 确保 ollama serve 命令已经执行;

- 运行命令:  `ollama pull llava`

- 说明: `ollama pull <model-name:tag>`
   - `<model-name:tag>` 可以从 https://ollama.com/library 参考;


### **8. 运行模型**
 


前提: 
   1. 确保当前处于容器之中, 可以参考`1 进入容器`确认自己进入容器
   2. 确保 ollama serve 命令已经执行;

ollama 执行`run`命令, 会自动拉取模型

#### 8.1 ollama 运行对话大模型 llama3


运行命令:  `ollama run llama3`


#### 8.2 ollama 运行多模态大模型 llava

运行命令:  `ollama run llava`

对话过程中可以输入`本地图像的绝对路径`，多模态大模型会对图片内容自动进行一个描述

### **9. 自定义模型**

我们可以利用下载到本地的GGUF模型文件，创建一个Modelfile模型描述文件给ollama使用。 

文件名称: llama3-zh.mf

文件内容:

---

FROM ./xxx.gguf

---

FROM 后面的内容是 GGUF模型文件 的路径，创建好模型描述文件后，我们使用ollama命令行工具即可将模型注册到本地:

ollama create llama3-zh -f ./xxx.mf


此时我们就可以使用`ollama list`和`ollama run`等命令操作这个模型了



### **10. ollama + open-webui**


见: [./tutorial_ollama/01-ollama_open-webui.md](./tutorial_ollama/01-ollama_open-webui.md)
