一文玩转ollama

​1.介绍​
🚀什么是ollama?

Ollama 是一个开源工具,专为在本地计算机上​​快速部署和运行大型语言模型(LLM)​​而设计。通过简化的命令行操作,用户无需复杂配置即可调用诸如 DeepSeek、Qwen 等主流开源模型,适合:

  • 开发者快速测试模型
  • 研究者进行原型开发
  • 企业实现私有化部署
🔍 ​核心优势​

  1. 一键部署主流开源模型
  2. 完全本地运行保障隐私
  3. 兼容OpenAI API生态
⚖️ ​竞品对比​

lm studio官网
image.png

lm-studio提供了一个gui界面,使用起来相对友好。

工具开源GUI支持模型扩展性
​Ollama​
​LM Studio​
​2. 安装与配置​
💻 ​​安装步骤​

ollama支持windowsLinuxmacos平台,选择自己平台进行下载。
image.png
安装完成之后,输入ollama --version,输出下面这些信息即代表安装成功。

PS C:\> ollama --help
Large language model runner

Usage:
  ollama [flags]
  ollama [command]

Available Commands:
  serve       Start ollama
  create      Create a model from a Modelfile
  show        Show information for a model
  run         Run a model
  stop        Stop a running model
  pull        Pull a model from a registry
  push        Push a model to a registry
  list        List models
  ps          List running models
  cp          Copy a model
  rm          Remove a model
  help        Help about any command

Flags:
  -h, --help      help for ollama
  -v, --version   Show version information

Use "ollama [command] --help" for more information about a command.
⚙️ ​​关键配置​

此时,先不要着急下载模型,我们先来设置环境变量。

  • OLLAMA_HOST 如果需要外部可以访问,设置为0.0.0.0
  • OLLAMA_MODELS 指定模型下载到指定文件夹。windows平台用户建议设置,否则会下载到系统盘用户目录下,占用系统盘空间。

更多很多环境变量请参考帮助文档,例如ollma serve --help
image.png

[!warning] 注意防止服务暴露
对于有公网ip的用户,轻易不要设置OLLAMA_HOST,以防止ollama服务暴露,可以在外面套一层nginx服务,进行鉴权校验。

💡 ​​硬件建议​
  • 7B模型:至少8GB内存
  • 14B模型:推荐16GB内存+GPU加速
  • 量化模型(如Q4):可降低50%显存占用
​​3. 基础使用教程​
​📥 ​模型下载​

ollama官方提供了模型仓库,里面包含热门的开源模型。

image.png
可以根据EmbeddingVsionTools等进行筛选
qwen3为例
image.png
点进模型详情页面,该模型会详尽列出该模型所有版本,根据自身电脑配置选择合适大小的模型进行下载运行。

qwen3:14b为例
下载该模型

	ollama pull qwen3:14b

也可以直接输入ollama run qwen3:14b,ollama发现本地没有该模型,会自动进行下载。

该市场除了官方模型,也有很多用户上传的修改版模型。例如搜索qwen3
image.png
有很多特殊定制的版本,例如去除大模型限制的qwen3-abliterated、去除思考的Qw3

🔧 ​常用命令速查​
  • 模型管理
    • 下载模型:ollama pull <model-name>
    • 查看本地模型列表:ollama list
    • 查看模型信息:ollama show <model-name>
    • 删除模型:ollama rm <model-name>
  • 运行与交互
    • 启动模型:ollama run <model-name>
    • 运行中对话: ollama ps
    • 关闭模型:ollama stop <model-name>
    • 退出交互模式 ctrl+d/bye
  • 常用命令速查表
    image.png
📜 命令使用示例​
  1. 下载模型
C:\> ollama pull qwen3:4b
verifying sha256 digest
...
writing manifest
success
  1. 查看本地模型列表
    image.png

  2. 查看模型

PS C:\> ollama show qwen3:14b
  Model
    architecture        qwen3
    parameters          14.8B
    context length      40960
    embedding length    5120
    quantization        Q4_K_M

  Capabilities
    completion
    tools

  Parameters
    temperature       0.6
    top_k             20
    top_p             0.95
    repeat_penalty    1
    stop              "<|im_start|>"
    stop              "<|im_end|>"

  License
    Apache License
    Version 2.0, January 2004
  1. 删除模型
PS C:\> ollama rm qwen:0.5b
deleted 'qwen:0.5b'
  1. 运行模型
    image.png

–verbose可以让ollama打印出token信息

  1. 查看运行中对话
PS C:\> ollama ps
NAME         ID              SIZE     PROCESSOR    UNTIL
qwen3:14b    7d7da67570e2    12 GB    100% GPU     2 minutes from now
  1. 关闭模型
PS C:\> ollama stop qwen3:14b
​​4. 高级功能与技巧​
  • 自定义模型配置
    • 修改模型参数(温度、top-k 等)
    • 加载本地微调模型(Modelfile 使用)
  • API 集成
    • 通过 REST API 调用 Ollama
    • Python 示例代码(requests 库)
​🔌 API集成示例​
🐍使用ollama库
import ollama
from rich import print  
from rich.progress import track
from rich.console import Console
from rich.logging import RichHandler
import logging
import os

# 设置Ollama服务器地址环境变量
# 可以通过环境变量传入或直接在此设置
os.environ["OLLAMA_HOST"] = "127.0.0.1:11434"

# 初始化Rich控制台和日志系统
console = Console()
logging.basicConfig(
    level="NOTSET",  # 设置日志级别为最低,记录所有日志
    format="%(message)s",  # 日志格式
    datefmt="[%X]",  # 时间格式
    handlers=[RichHandler(console=console)]  # 使用Rich处理日志输出
)
log = logging.getLogger("rich")

def complete_output():
    """
    完整输出模式 - 一次性获取完整响应
    """
    console.print("[bold yellow]完整输出模式启动...[/bold yellow]")
    
    # 构造对话消息
    messages = [
        {
            "role": "system",
            "content": "你是一个python开发专家,针对问题直接返回代码,如果办不到直接回复暂时无法解决"
        },
        {
            "role": "user",
            "content": "请使用pygame编写一个弹球游戏"
        }
    ]
    
    # 发送请求并获取完整响应
    try:
        response = ollama.chat(
            model="qwen:7b",
            messages=messages,
            stream=False  # 关闭流式输出
        )
        
        # 输出完整响应
        console.print("\n[bold green]完整响应:[/bold green]")
        console.print(response['message']['content'])
        
    except Exception as e:
        log.error(f"请求失败: {str(e)}")

def stream_output():
    """
    流式输出模式 - 实时显示响应内容
    """
    console.print("[bold yellow]流式输出模式启动...[/bold yellow]")
    
    # 构造对话消息
    messages = [
        {
            "role": "system",
            "content": "你是一个python开发专家,针对问题直接返回代码,如果办不到直接回复暂时无法解决"
        },
        {
            "role": "user",
            "content": "请使用pygame编写一个弹球游戏"
        }
    ]
    
    console.print("生成中...")
    console.print("AI响应:\n")
    
    try:
        # 发送流式请求
        stream = ollama.chat(
            model="qwen:7b",
            messages=messages,
            stream=True  # 启用流式输出
        )
        
        # 实时输出响应内容
        for chunk in stream:
            print(chunk['message']['content'], end="", flush=True)
            
        console.print("\n[bold green]生成完成[/bold green]")
        
    except Exception as e:
        log.error(f"请求失败: {str(e)}")

if __name__ == '__main__':
    # 用户可以选择输出模式
    console.print("请选择输出模式:")
    console.print("1. 完整输出模式")
    console.print("2. 流式输出模式")
    
    choice = input("请输入选择(1/2): ")
    
    if choice == "1":
        complete_output()
    elif choice == "2":
        stream_output()
    else:
        console.print("[bold red]无效选择![/bold red]")
🌐使用http进行调用

对于完整http api接口,参考文档

使用requests进行实现

import requests
from rich import print
from rich.console import Console
from rich.logging import RichHandler
import logging
import os
import json

# 设置Ollama服务器地址
OLLAMA_HOST = "http://127.0.0.1:11434"

# 初始化Rich控制台和日志系统
console = Console()
logging.basicConfig(
    level="NOTSET",  # 设置日志级别为最低,记录所有日志
    format="%(message)s",  # 日志格式
    datefmt="[%X]",  # 时间格式
    handlers=[RichHandler(console=console)]  # 使用Rich处理日志输出
)
log = logging.getLogger("rich")

def complete_output():
    """
    完整输出模式 - 使用requests库一次性获取完整响应
    """
    console.print("[bold yellow]完整输出模式启动...[/bold yellow]")
    
    # 构造请求URL和消息体
    url = f"{OLLAMA_HOST}/api/chat"
    messages = [
        {
            "role": "system",
            "content": "你是一个python开发专家,针对问题直接返回代码,如果办不到直接回复暂时无法解决"
        },
        {
            "role": "user",
            "content": "请使用pygame编写一个弹球游戏"
        }
    ]
    
    # 构造请求数据
    data = {
        "model": "qwen3:8b",
        "messages": messages,
        "stream": False  # 关闭流式输出
    }
    
    try:
        # 发送POST请求
        response = requests.post(
            url,
            json=data,
            headers={"Content-Type": "application/json"}
        )
        response.raise_for_status()  # 检查HTTP错误
        
        # 解析并输出响应
        result = response.json()
        console.print("\n[bold green]完整响应:[/bold green]")
        console.print(result['message']['content'])
        
    except requests.exceptions.RequestException as e:
        log.error(f"HTTP请求失败: {str(e)}")

def stream_output():
    """
    流式输出模式 - 使用requests库实时显示响应内容
    """
    console.print("[bold yellow]流式输出模式启动...[/bold yellow]")
    
    # 构造请求URL和消息体
    url = f"{OLLAMA_HOST}/api/chat"
    messages = [
        {
            "role": "system",
            "content": "你是一个python开发专家,针对问题直接返回代码,如果办不到直接回复暂时无法解决"
        },
        {
            "role": "user",
            "content": "请使用pygame编写一个弹球游戏"
        }
    ]
    
    # 构造请求数据
    data = {
        "model": "qwen3:8b",
        "messages": messages,
        "stream": True  # 启用流式输出
    }
    
    console.print("生成中...")
    console.print("AI响应:\n")
    
    try:
        # 发送流式请求
        with requests.post(
            url,
            json=data,
            headers={"Content-Type": "application/json"},
            stream=True
        ) as response:
            response.raise_for_status()  # 检查HTTP错误
            
            # 逐行读取流式响应
            for line in response.iter_lines():
                if line:
                    chunk = json.loads(line.decode('utf-8'))
                    print(chunk['message']['content'], end="", flush=True)
                    
        console.print("\n[bold green]生成完成[/bold green]")
        
    except requests.exceptions.RequestException as e:
        log.error(f"HTTP请求失败: {str(e)}")

if __name__ == '__main__':
    # 用户可以选择输出模式
    console.print("请选择输出模式:")
    console.print("1. 完整输出模式")
    console.print("2. 流式输出模式")
    
    choice = input("请输入选择(1/2): ")
    
    if choice == "1":
        complete_output()
    elif choice == "2":
        stream_output()
    else:
        console.print("[bold red]无效选择![/bold red]")
🛠️ ​​自定义模型​

以基础模型qwen3:14b为例,我们想实现默认关闭思考。

1️⃣ 创建ModelFile

FROM qwen3:14b
SYSTEM """/no_think 你是助手贾维斯,根据用户问题给出专业简短的回复"""

​2️⃣ 注册该模型

image.png
由于基础模型已经存在,创建该模型并不会占用大量额外空间。

**3️⃣测试效果
image.png

📂加载本地GGUF模型

1️⃣ 准备工作​

Qwen3-14B-GGUF为例
image.png
通过ollama pull qwen3:13b拉取的模型是Q4_K_M量化版本。这里我们以Qwen3-14B-Q8.gguf Q6_K量化为例,创建一个新的模型。

2️⃣ 准备ModelFile

FROM ./Qwen3-14B-Q8_0.gguf

具体ModelFile编写。视具体需求进行调整。最好拷贝官方的ModelFile内容进行修改。

3️⃣ 注册该模型

ollama create Qwen3-14B-Q8 -f ModelFile

image.png

4️⃣ 查询是否注册成功
image.png

5️⃣ 运行该模型
image.png

​5.案例实战
📃 文档rag问答助手
from langchain_community.llms import Ollama
import gradio as gr
import os
from typing import List, Tuple
from langchain_community.document_loaders import (
    DirectoryLoader,
    PyPDFLoader,
    Docx2txtLoader,
    TextLoader,
    UnstructuredExcelLoader,
    UnstructuredPowerPointLoader
)
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings import OllamaEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.chains import RetrievalQA
import warnings
warnings.warn(
    "启用危险反序列化,请确保只加载自己创建的向量数据库文件",
    UserWarning
)

# 配置参数
DOCS_DIR = "../docs"
VECTOR_DB_DIR = "../db/vector_db"
MODEL_NAME = "qwen3:14b"  # 可替换为 mistral 或其他模型
EMBEDDING_MODEL = "mxbai-embed-large:335m"  # 可替换为其他嵌入模型
SUPPORTED_EXTENSIONS = {
    '.pdf': PyPDFLoader,
    '.docx': Docx2txtLoader,
    '.xlsx': UnstructuredExcelLoader,
    '.pptx': UnstructuredPowerPointLoader,
    '.txt': TextLoader
}

# 1. 多格式文档加载器
def load_documents() -> Tuple[List, str]:
    if not os.path.exists(DOCS_DIR):
        os.makedirs(DOCS_DIR)
        return [], "请先在项目目录下创建docs文件夹并放入您的文档"

    documents = []
    loaded_files = set()
    
    for ext, loader_class in SUPPORTED_EXTENSIONS.items():
        try:
            loader = DirectoryLoader(DOCS_DIR, glob=f"**/*{ext}", loader_cls=loader_class)
            loaded_docs = loader.load()
            documents.extend(loaded_docs)
            loaded_files.update(doc.metadata['source'] for doc in loaded_docs)
        except Exception as e:
            print(f"加载 {ext} 文件时出错: {str(e)}")

    if not documents:
        return [], "未找到支持的文档格式,请检查docs目录"

    # 文档分割
    text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=1000,
        chunk_overlap=200
    )
    split_docs = text_splitter.split_documents(documents)
    
    file_count = len(loaded_files)
    chunk_count = len(split_docs)
    return split_docs, f"已加载 {file_count} 个文件 ({', '.join(SUPPORTED_EXTENSIONS.keys())}),分割为 {chunk_count} 个文本块"

# 2. 向量数据库管理
class VectorDBManager:
    def __init__(self):
        self.embeddings = OllamaEmbeddings(model=EMBEDDING_MODEL)
    
    def create_vector_db(self) -> str:
        docs, message = load_documents()
        if not docs:
            return message
        
        db = FAISS.from_documents(docs, self.embeddings)
        
        if not os.path.exists(VECTOR_DB_DIR):
            os.makedirs(VECTOR_DB_DIR)
        db.save_local(
            VECTOR_DB_DIR,
            allow_dangerous_deserialization=True  # Add this parameter
        )
        
        return f"{message}\n向量数据库创建成功!"

    def db_exists(self) -> bool:
        return os.path.exists(os.path.join(VECTOR_DB_DIR, "index.faiss"))

# 3. 问答系统核心
class DocumentQASystem:
    def __init__(self):
        self.qa_chain = None
        self.db_manager = VectorDBManager()
    
    def initialize(self) -> str:
        if not self.db_manager.db_exists():
            return "请先创建向量数据库"
        
        db = FAISS.load_local(
            VECTOR_DB_DIR, 
            self.db_manager.embeddings,
            allow_dangerous_deserialization=True
        )
        
        # 使用Ollama类包装模型调用
        llm = Ollama(
            model=MODEL_NAME,
            temperature=0.1,
            system="/no_think 基于提供的上下文回答问题,如果查询不到结果请回答不知道,不要编造结果",
            base_url="http://localhost:11434"  # 添加Ollama服务地址
        )
        
        self.qa_chain = RetrievalQA.from_chain_type(
            llm=llm,
            chain_type="stuff",
            retriever=db.as_retriever(search_kwargs={"k": 3}),
            return_source_documents=True
        )
        return "问答系统初始化完成!"

    def ask(self, question: str) -> Tuple[str, List[str]]:
        if not self.qa_chain:
            return "问答系统未初始化", []
        
        result = self.qa_chain.invoke({"query": question})
        answer = result["result"]
        # 修改为只返回文件名而不是完整路径
        sources = list(set([os.path.basename(doc.metadata["source"]) for doc in result["source_documents"]]))
        return answer, sources

# 4. Gradio 界面增强
def create_interface():
    qa_system = DocumentQASystem()
    db_manager = VectorDBManager()
    
    with gr.Blocks(title="多格式文档问答助手") as demo:
        gr.Markdown("# 📂 多格式文档问答助手")
        gr.Markdown("支持 PDF、Word、Excel、PPT 和文本文件")
        
        with gr.Tab("文档处理"):
            gr.Markdown(f"### 文档目录:`{DOCS_DIR}`")
            gr.Markdown("支持的文件格式:" + ", ".join(SUPPORTED_EXTENSIONS.keys()))
            
            with gr.Row():
                process_btn = gr.Button("处理文档", variant="primary")
                clear_btn = gr.Button("清除数据库")
            
            process_output = gr.Textbox(label="处理状态", interactive=False)
            
            process_btn.click(
                db_manager.create_vector_db,
                outputs=process_output
            )
            clear_btn.click(
                lambda: (os.system(f"rm -rf {VECTOR_DB_DIR}/*"), "向量数据库已清除"),
                outputs=process_output
            )
        
        with gr.Tab("问答系统"):            
            with gr.Row():
                init_btn = gr.Button("初始化系统", variant="primary")
                init_status = gr.Textbox(label="系统状态", value="未初始化", interactive=False)
            
            init_btn.click(
                qa_system.initialize,
                outputs=init_status
            )
            
            with gr.Column():
                question = gr.Textbox(label="输入问题", placeholder="请输入关于文档的问题...")
                ask_btn = gr.Button("提问", variant="primary")
                
                answer = gr.Textbox(label="答案", lines=5, interactive=False)
                sources = gr.Textbox(label="来源文档", lines=3, interactive=False)  # 改为文本框显示文件名
            
            ask_btn.click(
                qa_system.ask,
                inputs=question,
                outputs=[answer, sources]
            )
    
    return demo

if __name__ == "__main__":
    demo = create_interface()
    demo.launch(server_name="0.0.0.0", server_port=7860)

文档问答运行效果如下:

image.png

​6. 客户端

支持ollama的客户端有很多。由于ollama是兼容openai api规范的,所以只要支持自定义openai url的客户端都是兼容的。也有一些为ollama进行专门优化的,例如chatwise
在此为不同场景各推荐一个客户端。

🌐web端

chrome插件Page Assist,专门负责浏览网页时同ollama进行交互,例如读取网页内容,针对网页进行提问等,而无需担心隐私泄露。
如果无法访问谷歌插件商店可直接使用搜索引擎进行查询,有很多第三方插件商店。

image.png

🖥️desktop

个人推荐cherry studio,目前功能最丰富也是最完善的ai集成客户端。支持多ai平台、mcp、知识库等功能。
github仓库
image.png

📱手机端
ios

App Store下载Enchanted LLM

c0df4d50076222f50682e28bf62bf25.jpg

android

安卓可以使用ollama的官方app。
点击仓库地址以访问官方仓库。
image.png

点击Releases页面进行下载

安装后界面如下图所示
559a193f8e18cef8ad44641f95ba6f8.jpg

🔗远程访问方案

方法有很多种,此处以之前写的一个小工具为例。
访问 gradio_share仓库,下载releases程序

运行命令

gradio-tunnel_windows_amd64.exe -port 11434

image.png

复制出访问地址,这个地址即后续ollama的代理地址。

在客户端配置ollama url,以ios上的Enchanted LLM为例

9f80b9c205b7d0cbd248996fc9a6ea2.jpg

聊天一切正常
微信图片_20250525172634.jpg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值