Ollama API 实战:5分钟搭建你的第一个AI聊天机器人(Python版)

最近身边不少做开发的朋友都在聊,想自己动手搞个AI聊天机器人玩玩,但一看到那些大模型的部署和API调用就头大,觉得门槛太高。其实,现在有个工具能让这件事变得像搭积木一样简单,那就是Ollama。它把本地运行大模型这件事封装得极其友好,你不需要关心复杂的模型部署和环境配置,只需要几行Python代码,就能让一个拥有“智能”的对话程序跑起来。这篇文章,我就从一个Python开发者的视角,带你从零开始,手把手地构建一个属于你自己的聊天机器人。我们会聚焦于最核心的Ollama API,用最直白的代码,在5分钟内看到第一个对话结果。无论你是想做个智能客服原型、一个有趣的个人助手,还是单纯想理解AI应用的后端逻辑,这篇实战指南都能给你一个清晰、落地的起点。

1. 起手式:环境准备与Ollama初探

在开始写代码之前,我们得先把“舞台”搭好。Ollama的核心思想是让大模型在本地运行变得轻而易举,它本身是一个服务端程序。因此,第一步永远是在你的机器上安装并启动Ollama服务。

对于macOS和Linux用户,安装通常是一行命令的事。以macOS为例,打开终端直接执行:

curl -fsSL https://ollama.com/install.sh | sh

安装完成后,Ollama服务会自动启动。你可以在终端里输入 ollama run llama3 来快速测试。这个命令会拉取(如果本地没有)并运行Meta的Llama 3模型,你会直接进入一个交互式聊天界面。这证明了你的Ollama服务是健康的。

对于Windows用户,过程同样简单,直接从Ollama官网下载安装程序,像安装普通软件一样完成即可。安装后,你会在系统托盘或服务列表里找到它。

提示:首次运行 ollama run <模型名> 会触发模型下载。Llama 3 8B版本大约4-5GB,请确保网络通畅和足够的磁盘空间。你也可以选择更小的模型如 phi3mistral 来快速开始。

接下来是我们的Python环境。我强烈建议使用虚拟环境来管理项目依赖,这能避免包版本冲突。打开你的终端或命令行,进入项目目录,执行以下操作:

# 创建并激活虚拟环境(以venv为例)
python -m venv venv
# Windows
venv\Scripts\activate
# macOS/Linux
source venv/bin/activate

激活虚拟环境后,安装我们唯一必需的Python库:requests。它是我们与Ollama API通信的桥梁。

pip install requests

至此,我们的基础环境就绪了。Ollama服务在后台运行,监听默认的 http://localhost:11434 端口,Python环境也准备好了。我们可以通过一个简单的API调用来验证一切是否正常。创建一个名为 test_connection.py 的文件,写入以下代码:

import requests
import json

try:
    # 尝试获取本地已下载的模型列表
    response = requests.get("http://localhost:11434/api/tags")
    if response.status_code == 200:
        models = response.json().get('models', [])
        print("✅ Ollama 服务连接成功!")
        print(f"本地已有模型: {[m['name'] for m in models]}")
    else:
        print(f"❌ API返回异常状态码: {response.status_code}")
except requests.exceptions.ConnectionError:
    print("❌ 无法连接到Ollama服务,请确保Ollama已启动。")
    print("   可以尝试在终端执行 'ollama serve' 来启动服务。")

运行这个脚本,如果看到成功信息和模型列表,恭喜你,舞台已经搭好,演员(模型)也已就位,接下来就是编写我们的剧本(聊天逻辑)了。

2. 核心对话引擎:理解并调用 /api/chat 接口

Ollama提供了多个API端点,但对于构建一个聊天机器人,/api/chat 是最自然、最合适的选择。它原生支持多轮对话的消息格式,与我们熟悉的OpenAI的Chat Completion API非常相似,降低了学习成本。

这个接口的核心在于 messages 参数。它是一个字典列表,每个字典代表对话中的一条消息,包含 role(角色)和 content(内容)两个字段。角色通常只有两种:user 代表用户输入,assistant 代表AI助手的回复。通过维护这个消息列表,我们就实现了对话上下文的保持。

让我们先抛开复杂的流式处理和错误处理,构建一个最基础的、一次性的问答函数。在项目根目录创建 simple_chatbot.py

import requests
import json

def ask_ollama(prompt, model="llama3"):
    """
    向Ollama发送一个简单的提示并获取回复。
    """
    url = "http://localhost:11434/api/chat"
    
    # 构建请求数据
    payload = {
        "model": model,
        "messages": [
            {"role": "user", "content": prompt}
        ],
        "stream": False  # 先使用非流式,一次性获取全部回复
    }
    
    try:
        response = requests.post(url, json=payload)
        response.raise_for_status()  # 如果状态码不是200,抛出HTTPError异常
        result = response.json()
        # 从响应中提取助手的回复内容
        assistant_reply = result['message']['content']
        return assistant_reply
    except requests.exceptions.RequestException as e:
        return f"请求出错: {e}"
    except KeyError:
        return "解析响应数据时出错。"

if __name__ == "__main__":
    # 测试我们的小机器人
    user_question = "用Python写一个简单的Hello World程序。"
    answer = ask_ollama(user_question)
    print(f"你: {user_question}")
    print(f"AI: {answer}")

运行这个脚本,你应该能看到AI返回的Python代码。这已经是一个功能完整的“一问一答”式聊天机器人了!但它的记忆只有一句话,无法进行连续对话。为了让机器人拥有“记忆”,我们需要在每次对话时,把历史记录也传给API。

我们来升级一下,创建一个能记住上下文的聊天类。新建 context_chatbot.py

import requests
import json

class SimpleChatBot:
    def __init__(self, model="llama3", system_prompt=None):
        """
        初始化聊天机器人。
        :param model: 使用的模型名称。
        :param system_prompt: 系统提示词,用于设定AI的角色和行为。
        """
        self.model = model
        self.conversation_history = []
        self.api_url = "http://localhost:11434/api/chat"
        
        # 如果有系统提示,将其作为第一条消息加入历史
        if system_prompt:
            self.conversation_history.append({
                "role": "system",
                "content": system_prompt
            })
    
    def chat(self, user_input):
        """
        发送用户输入并获取AI回复,同时更新对话历史。
        """
        # 将用户输入加入历史
        self.conversation_history.append({"role": "user", "content": user_input})
        
        payload = {
            "model": self.model,
            "messages": self.conversation_history,
            "stream": False
        }
        
        try:
            response = requests.post(self.api_url, json=payload)
            response.raise_for_status()
            result = response.json()
            
            # 获取AI回复
            ai_reply = result['message']['content']
            # 将AI回复加入历史
            self.conversation_history.append({"role": "assistant", "content": ai_reply})
            
            return ai_reply
        except requests.exceptions.RequestException as e:
            return f"网络或请求错误: {e}"
        except (KeyError, json.JSONDecodeError) as e:
            return f"处理响应时出错: {e}"
    
    def get_history(self):
        """获取当前的完整对话历史。"""
        return self.conversation_history
    
    def clear_history(self):
        """清空对话历史。"""
        # 保留系统提示(如果有)
        self.conversation_history = [msg for msg in self.conversation_history if msg['role'] == 'system']

# 使用示例
if __name__ == "__main__":
    # 创建一个具有特定角色的机器人
    bot = SimpleChatBot(
        model="llama3",
        system_prompt="你是一个幽默的编程助手,喜欢用比喻解释技术概念。"
    )
    
    print("聊天机器人已启动(输入 'quit' 退出)")
    while True:
        user_input = input("\n你: ")
        if user_input.lower() == 'quit':
            print("再见!")
            break
        
        reply = bot.chat(user_input)
        print(f"AI: {reply}")

现在,你的机器人不仅能够连续对话,还能通过 system_prompt 被赋予特定的人格或职责,比如“严谨的代码审查员”或“风趣的故事讲述者”。这就是构建个性化聊天机器人的基石。

3. 提升体验:实现流式响应与参数调优

如果你用过ChatGPT网页版,一定会对那种逐字打印出来的回复效果印象深刻。这种“打字机”效果不仅能降低用户等待的焦虑感,在生成长文本时体验也更佳。Ollama的API同样支持流式响应,实现起来并不复杂。

流式传输的关键在于将请求参数 "stream" 设置为 True,并且客户端(我们的Python程序)需要以流的方式处理HTTP响应。requests 库的 stream=True 参数和 iter_lines() 方法正是为此而生。

让我们修改 SimpleChatBot 类,增加一个流式聊天的方法。创建新文件 streaming_chatbot.py,或者直接在之前的类中添加:

import requests
import json

class StreamingChatBot(SimpleChatBot):  # 假设继承自上一节的SimpleChatBot
    def __init__(self, model="llama3", system_prompt=None):
        super().__init__(model, system_prompt)
    
    def chat_stream(self, user_input):
        """
        以流式方式发送用户输入并实时获取AI回复。
        返回一个生成器,每次yield一个回复片段。
        """
        self.conversation_history.append({"role": "user", "content": user_input})
        
        payload = {
            "model": self.model,
            "messages": self.conversation_history,
            "stream": True  # 启用流式
        }
        
        try:
            # 注意这里设置了 stream=True
            with requests.post(self.api_url, json=payload, stream=True) as response:
                response.raise_for_status()
                
                full_reply = ""
                for line in response.iter_lines():
                    if line:
                        # 每行是一个JSON字符串
                        line_decoded = line.decode('utf-8')
                        # Ollama的流式响应每行以 "data: " 开头
                        if line_decoded.startswith('data: '):
                            json_str = line_decoded[6:]  # 去掉 "data: " 前缀
                            try:
                                chunk = json.loads(json_str)
                                # 获取当前片段的文本
                                piece = chunk.get('message', {}).get('content', '')
                                if piece:
                                    full_reply += piece
                                    yield piece  # 实时产出片段
                                # 如果收到 done 为 True,表示流结束
                                if chunk.get('done', False):
                                    break
                            except json.JSONDecodeError:
                                # 忽略非JSON行(如心跳包)
                                continue
                
                # 流结束后,将完整的AI回复加入历史
                self.conversation_history.append({"role": "assistant", "content": full_reply})
                
        except requests.exceptions.RequestException as e:
            yield f"[流式请求出错: {e}]"

# 使用流式聊天的示例
if __name__ == "__main__":
    bot = StreamingChatBot(system_prompt="你是一位诗人。")
    
    print("流式诗人聊天机器人已启动(输入 'quit' 退出)")
    while True:
        user_input = input("\n你: ")
        if user_input.lower() == 'quit':
            break
        
        print("AI: ", end="", flush=True)
        full_response = ""
        for chunk in bot.chat_stream(user_input):
            print(chunk, end="", flush=True)  # 关键:逐块打印,不换行
            full_response += chunk
        print()  # 最后换行
        
        # 此时,full_response 包含了完整的回复,也已存入历史

运行这段代码,你会看到AI的回复像真人打字一样逐个单词或词组地出现。这种交互体验对于终端界面或WebSocket驱动的网页应用至关重要。

除了流式传输,通过调整生成参数,我们可以精细控制AI的“性格”和输出质量。Ollama在请求的 options 字段中提供了丰富的调参选项。下表列出了一些最常用、效果最直观的参数:

参数 类型 默认值 作用与影响
temperature float 0.8 创造性/随机性。值越低(如0.1),输出越确定、保守;值越高(如1.5),输出越随机、有创意。
top_p float 0.9 核采样。与temperature配合,控制从概率质量最高的词汇中采样。通常0.7-0.9效果较好。
num_predict int 128 最大生成长度。限制单次回复的最大token数,防止生成过长内容。
repeat_penalty float 1.1 重复惩罚。大于1的值会降低重复词汇的概率,有助于减少循环和啰嗦。
seed int 随机 随机种子。设置固定的种子可以使相同输入的输出具有可重复性,便于调试。

在代码中应用这些参数非常简单,只需在请求的payload中加入 options 字典。例如,我们想要一个更严谨、更简洁的代码助手:

def ask_with_options(prompt, model="llama3"):
    url = "http://localhost:11434/api/chat"
    payload = {
        "model": model,
        "messages": [{"role": "user", "content": prompt}],
        "stream": False,
        "options": {  # 加入调优参数
            "temperature": 0.3,      # 降低随机性,让回答更专注
            "num_predict": 500,      # 允许更长的回答
            "repeat_penalty": 1.2,   # 加强重复惩罚
            "top_p": 0.8
        }
    }
    response = requests.post(url, json=payload)
    return response.json()['message']['content']

通过组合流式响应和生成参数调优,你的聊天机器人已经从“能用”进化到了“好用”的阶段。

4. 从脚本到应用:构建一个简单的命令行交互界面

到目前为止,我们的机器人还停留在脚本层面。为了让其更像一个真正的应用,我们可以为其打造一个更友好的命令行界面(CLI),并增加一些实用功能,比如模型切换、历史记录查看、对话导出等。

我们将使用Python内置的 argparse 库来解析命令行参数,并构建一个功能菜单。最终目标是实现一个可以通过命令如 python chatbot_cli.py --model mistral --temp 0.5 来启动,并支持交互式对话的程序。

首先,规划一下我们CLI工具的功能点:

  1. 交互式聊天模式:核心功能,支持流式输出。
  2. 模型管理:列出本地可用模型,并允许运行时切换。
  3. 参数配置:允许通过命令行参数设置温度、最大生成长度等。
  4. 对话管理:查看当前对话历史,清空历史,或将历史导出为文件。
  5. 单次问答模式:不进入循环,直接回答一个问题后退出。

下面是一个简化但功能完整的CLI聊天机器人实现框架,保存在 chatbot_cli.py 中:

import argparse
import json
import sys
from datetime import datetime
# 假设我们使用了之前定义的 StreamingChatBot 类
# from streaming_chatbot import StreamingChatBot

class ChatBotCLI:
    def __init__(self, model, temperature, max_tokens):
        self.bot = StreamingChatBot(model=model)
        # 这里可以初始化时设置options,但为了灵活,我们在每次请求时动态设置
        self.default_options = {
            "temperature": temperature,
            "num_predict": max_tokens,
        }
        self.model = model
    
    def list_local_models(self):
        """获取并打印本地已下载的模型列表。"""
        try:
            resp = requests.get("http://localhost:11434/api/tags")
            models = resp.json().get('models', [])
            print("\n本地可用模型:")
            for m in models:
                print(f"  - {m['name']}")
        except Exception as e:
            print(f"获取模型列表失败: {e}")
    
    def interactive_chat(self):
        """进入交互式聊天循环。"""
        print(f"\n开始与 '{self.model}' 对话 (温度: {self.default_options['temperature']})")
        print("输入 '/help' 查看命令, '/quit' 退出聊天。")
        
        while True:
            try:
                user_input = input("\n你: ").strip()
                if not user_input:
                    continue
                    
                # 处理命令
                if user_input.startswith('/'):
                    self._handle_command(user_input)
                    continue
                
                # 正常聊天
                print("AI: ", end="", flush=True)
                full_reply = ""
                # 注意:这里需要修改bot的chat_stream方法,使其能接收options参数
                for chunk in self.bot.chat_stream(user_input, options=self.default_options):
                    print(chunk, end="", flush=True)
                    full_reply += chunk
                print()  # 换行
                
            except KeyboardInterrupt:
                print("\n\n中断。输入 /quit 退出。")
            except EOFError:
                print("\n检测到文件结束符。退出。")
                break
    
    def _handle_command(self, cmd):
        """处理用户输入的命令。"""
        cmd = cmd.lower()
        if cmd == '/quit' or cmd == '/exit':
            print("再见!")
            sys.exit(0)
        elif cmd == '/help':
            self._print_help()
        elif cmd == '/history':
            self._show_history()
        elif cmd == '/clear':
            self.bot.clear_history()
            print("对话历史已清空。")
        elif cmd == '/models':
            self.list_local_models()
        elif cmd == '/save':
            self._save_history()
        else:
            print(f"未知命令: {cmd}。输入 /help 查看可用命令。")
    
    def _print_help(self):
        help_text = """
        可用命令:
          /help      - 显示此帮助信息
          /history   - 显示当前对话历史
          /clear     - 清空对话历史
          /models    - 列出本地可用模型
          /save      - 将对话历史保存为JSON文件
          /quit      - 退出程序
        """
        print(help_text)
    
    def _show_history(self):
        history = self.bot.get_history()
        if not history:
            print("对话历史为空。")
            return
        print("\n=== 对话历史 ===")
        for msg in history:
            role_display = {"user": "你", "assistant": "AI", "system": "系统"}.get(msg['role'], msg['role'])
            print(f"{role_display}: {msg['content'][:100]}...")  # 只显示前100字符
    
    def _save_history(self):
        filename = f"chat_history_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
        history = self.bot.get_history()
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(history, f, ensure_ascii=False, indent=2)
        print(f"历史已保存至文件: {filename}")

def main():
    parser = argparse.ArgumentParser(description="Ollama 命令行聊天机器人")
    parser.add_argument('--model', '-m', default='llama3', help='指定使用的模型 (默认: llama3)')
    parser.add_argument('--temperature', '-t', type=float, default=0.7, help='生成温度 (默认: 0.7)')
    parser.add_argument('--max-tokens', '-n', type=int, default=1024, help='最大生成长度 (默认: 1024)')
    parser.add_argument('--list-models', '-l', action='store_true', help='列出本地模型后退出')
    
    args = parser.parse_args()
    
    if args.list_models:
        # 简单调用列表函数
        try:
            resp = requests.get("http://localhost:11434/api/tags")
            models = resp.json().get('models', [])
            for m in models:
                print(m['name'])
        except:
            print("无法获取模型列表。")
        sys.exit(0)
    
    # 启动CLI
    cli = ChatBotCLI(args.model, args.temperature, args.max_tokens)
    cli.interactive_chat()

if __name__ == "__main__":
    # 需要导入requests
    import requests
    main()

这个CLI程序已经具备了实用工具的雏形。你可以通过 python chatbot_cli.py --model mistral --temperature 0.9 启动一个更具创造性的Mistral模型对话,也可以在聊天过程中使用 /history 查看上下文,用 /save 将有趣的对话保存下来。

5. 进阶整合:打造一个极简的Web聊天界面

命令行工具适合开发者,但对于想分享给朋友或需要更直观交互的场景,一个网页界面显然更合适。利用Python的轻量级Web框架,比如Flask或FastAPI,我们可以用不到100行代码,为聊天机器人加上一个Web API和前端页面。

这里我们选择Flask,因为它足够简单。我们将创建两个端点:一个用于提供HTML页面,另一个用于处理聊天请求的API。前端使用简单的HTML和JavaScript,通过Fetch API与后端通信,并模拟流式输出。

首先,安装Flask:pip install flask。然后创建 app.py

from flask import Flask, render_template, request, Response, jsonify
import json
import requests

app = Flask(__name__)

# Ollama API的基础URL
OLLAMA_API_BASE = "http://localhost:11434/api"

@app.route('/')
def index():
    """提供主页面。"""
    return render_template('index.html')  # 稍后创建这个模板

@app.route('/api/chat', methods=['POST'])
def chat_api():
    """处理聊天请求的API端点。"""
    data = request.json
    user_message = data.get('message', '')
    model = data.get('model', 'llama3')
    
    # 构建发送给Ollama的请求数据
    # 注意:这里简化了,没有维护服务端的对话历史。实际应用应使用会话(如Flask-Session)来存储不同用户的历史。
    payload = {
        "model": model,
        "messages": [{"role": "user", "content": user_message}],
        "stream": True,
        "options": {
            "temperature": 0.7,
            "num_predict": 1000
        }
    }
    
    # 定义一个生成器函数,作为服务器发送事件(Server-Sent Events)的响应
    def generate():
        try:
            # 将请求转发给Ollama
            resp = requests.post(f"{OLLAMA_API_BASE}/chat", json=payload, stream=True)
            resp.raise_for_status()
            
            for line in resp.iter_lines():
                if line:
                    line_decoded = line.decode('utf-8')
                    if line_decoded.startswith('data: '):
                        json_str = line_decoded[6:]
                        try:
                            chunk = json.loads(json_str)
                            content_piece = chunk.get('message', {}).get('content', '')
                            if content_piece:
                                # 将每个片段以SSE格式发送
                                yield f"data: {json.dumps({'content': content_piece})}\n\n"
                            if chunk.get('done', False):
                                yield "data: [DONE]\n\n"
                                break
                        except json.JSONDecodeError:
                            continue
        except Exception as e:
            yield f"data: {json.dumps({'error': str(e)})}\n\n"
    
    # 返回一个流式响应,内容类型为 text/event-stream
    return Response(generate(), mimetype='text/event-stream')

if __name__ == '__main__':
    app.run(debug=True, port=5000)

接下来,在项目根目录创建一个 templates 文件夹,并在其中创建 index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>我的Ollama聊天机器人</title>
    <style>
        body { font-family: sans-serif; max-width: 800px; margin: 20px auto; padding: 20px; }
        #chatbox { border: 1px solid #ccc; height: 400px; overflow-y: auto; padding: 10px; margin-bottom: 10px; }
        .message { margin-bottom: 10px; }
        .user { text-align: right; color: #0066cc; }
        .assistant { text-align: left; color: #333; }
        #inputArea { display: flex; }
        #userInput { flex-grow: 1; padding: 10px; }
        #sendBtn { padding: 10px 20px; }
        .thinking { color: #888; font-style: italic; }
    </style>
</head>
<body>
    <h1>🤖 我的AI聊天伙伴</h1>
    <div id="chatbox"></div>
    <div id="inputArea">
        <input type="text" id="userInput" placeholder="输入你的问题..." autocomplete="off">
        <button id="sendBtn">发送</button>
    </div>
    <div>
        <label>模型: </label>
        <select id="modelSelect">
            <option value="llama3">Llama 3</option>
            <option value="mistral">Mistral</option>
            <option value="phi3">Phi-3</option>
        </select>
    </div>

    <script>
        const chatbox = document.getElementById('chatbox');
        const userInput = document.getElementById('userInput');
        const sendBtn = document.getElementById('sendBtn');
        const modelSelect = document.getElementById('modelSelect');

        function addMessage(content, sender) {
            const msgDiv = document.createElement('div');
            msgDiv.className = `message ${sender}`;
            msgDiv.textContent = `${sender === 'user' ? '你' : 'AI'}: ${content}`;
            chatbox.appendChild(msgDiv);
            chatbox.scrollTop = chatbox.scrollHeight; // 滚动到底部
        }

        function appendToLastMessage(content) {
            const lastMsg = chatbox.lastChild;
            if (lastMsg && lastMsg.className.includes('assistant')) {
                lastMsg.textContent += content;
                chatbox.scrollTop = chatbox.scrollHeight;
            }
        }

        async function sendMessage() {
            const message = userInput.value.trim();
            const model = modelSelect.value;
            if (!message) return;

            // 显示用户消息
            addMessage(message, 'user');
            userInput.value = '';
            userInput.focus();

            // 显示“思考中”提示
            const thinkingDiv = document.createElement('div');
            thinkingDiv.className = 'message assistant thinking';
            thinkingDiv.textContent = 'AI: 思考中...';
            chatbox.appendChild(thinkingDiv);

            try {
                // 发起流式请求
                const response = await fetch('/api/chat', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ message, model })
                });

                if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);

                const reader = response.body.getReader();
                const decoder = new TextDecoder();
                
                // 移除“思考中”提示,准备显示真实回复
                chatbox.removeChild(thinkingDiv);
                addMessage('', 'assistant'); // 先创建一个空消息容器

                while (true) {
                    const { done, value } = await reader.read();
                    if (done) break;

                    const chunk = decoder.decode(value);
                    const lines = chunk.split('\n').filter(line => line.trim());

                    for (const line of lines) {
                        if (line.startsWith('data: ')) {
                            const dataStr = line.slice(6);
                            if (dataStr === '[DONE]') {
                                return;
                            }
                            try {
                                const data = JSON.parse(dataStr);
                                if (data.error) {
                                    console.error('Error:', data.error);
                                    appendToLastMessage(` [错误: ${data.error}]`);
                                } else if (data.content) {
                                    appendToLastMessage(data.content);
                                }
                            } catch (e) {
                                console.error('解析SSE数据失败:', e);
                            }
                        }
                    }
                }
            } catch (error) {
                console.error('请求失败:', error);
                chatbox.removeChild(thinkingDiv);
                addMessage(`抱歉,请求出错: ${error.message}`, 'assistant');
            }
        }

        sendBtn.addEventListener('click', sendMessage);
        userInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter') sendMessage();
        });
    </script>
</body>
</html>

现在,运行 python app.py,打开浏览器访问 http://localhost:5000,一个拥有流式输出效果的Web聊天机器人就诞生了。你可以选择不同的模型,体验实时对话。这个例子虽然简单,但它清晰地展示了如何将Ollama API无缝集成到Web应用中,为后续开发更复杂的AI应用(如知识库问答、智能客服工单系统)提供了可扩展的骨架。

走到这一步,你已经完成了一个从环境搭建、核心API调用、参数调优、CLI工具开发到Web界面整合的完整闭环。整个过程没有复杂的理论,全是可运行、可修改的实战代码。我自己的体验是,Ollama极大地降低了个人开发者探索大模型应用的门槛,让你能快速将想法变成可交互的原型。在实际项目中,你可能还需要考虑用户会话管理、历史记录持久化(比如存数据库)、更复杂的错误处理以及前端界面的美化。但有了今天打下的这个基础,那些扩展都将是顺理成章的事情。最让我惊喜的是,整个开发过程是如此地“Pythonic”——简洁、直接、高效,这正是Python生态的魅力所在。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐