使用 Docker Testcontainers 的本地 AI

社区文章 发布于 2024 年 8 月 3 日

🙋🏻‍♂️ 大家好,我非常喜欢使用 Docker 新收购的开源启动项目 test containers。

  • 请参阅下面的 [链接](### 链接)
  • 他们希望你将其用于 [测试](### 测试层)
  • 我将其用于 [简单的 AI/ML 服务](### 为 AI 尝试 Testcontainers)
  • [加入我们,制作更多有用且酷炫的 testcontainers](### 加入我们)

什么是 Testcontainers?

Testcontainers 是一个开源框架,用于提供一次性的轻量级数据库、消息代理、Web 浏览器或几乎任何可以在 Docker 容器中运行的实例。

测试层

利用容器进行测试可提高可靠性,减少配置开销,并改善测试环境的一致性,最终实现更健壮和可维护的代码。

Test Containers 在不同测试层中提供了显著的优势

  • 集成测试:容器为数据访问测试提供隔离、可重现的环境,确保一致性并降低设置复杂性。
  • UI/验收测试:容器化浏览器通过消除本地浏览器设置造成的差异,实现一致、可靠的 UI 测试。
  • 应用程序集成测试:使用容器测试所有依赖项的应用程序,可以在与生产环境高度相似的环境中进行准确的端到端测试。

数据访问层集成测试

启示

  • 隔离性和一致性: 将数据库容器化可确保每个测试都在全新的已知状态下运行。这种隔离消除了因不同本地数据库设置或先前测试的残留数据而导致的变异性和不一致性。
  • 降低设置复杂性: 开发人员无需在本地机器上进行复杂的数据库设置,这有助于整个团队获得更一致的开发体验。
  • 可伸缩性和可靠性: 测试可以轻松扩展,而无需担心本地资源,容器编排工具可以高效地管理测试数据库实例。

示例: 开发人员使用 PostgreSQL 为应用程序的数据访问层编写集成测试。通过为每个测试启动一个 PostgreSQL 容器,他们确保每个测试都从一个干净的状态开始,避免因残留数据或来自其他测试的模式更改而导致的冲突。

UI/验收测试

启示

  • 一致的测试环境:使用 Selenium 等工具的容器化浏览器可确保 UI 测试在一致的环境中运行,减少浏览器特定问题或不同版本或插件引起的变异的影响。
  • 易于设置和维护:容器通过提供预配置、标准化的浏览器实例来简化 UI 测试的设置过程,无需手动管理浏览器版本或扩展。
  • 可重现性:每次测试执行都从全新的浏览器实例开始,从而获得更可靠和可重现的测试结果。

示例:使用容器化的 Chrome 实例运行 Web 应用程序的自动化 UI 测试套件。每个测试都从一个干净的浏览器开始,确保与浏览器缓存或扩展相关的问题不会影响测试结果。

应用程序集成测试

启示

  • 端到端测试:容器化环境可实现对应用程序及其所有依赖项(例如数据库、消息队列、Web 服务器)的全面测试,在一个独立的单一环境中进行。
  • 资源管理:短生命周期的测试容器有助于高效管理资源,避免长时间运行的服务开销,并实现快速测试执行和拆卸。
  • 环境对等:测试可以在与生产环境高度相似的环境中执行,从而提高测试结果的准确性,并降低测试与生产环境之间差异的风险。

示例:使用容器测试基于微服务的应用程序,每个微服务都带有 Redis 缓存和 RabbitMQ 消息代理等相关依赖项。此设置允许进行端到端测试,以在受控的隔离环境中验证服务之间的交互。

“非常有用,现在我们可以用 AI 玩耍了”

这很棒,我相信它对于节省生产构建的 DevOps 管道以及更多方面都非常有用,但我喜欢用它的 Ollama 对象!

为 AI 尝试 Testcontainers

Python 库 testcontainers 中的 OllamaContainer 类有助于设置和管理容器化环境,以通过 Ollama 提供 AI 模型。这使您能够在一致且隔离的环境中运行推理任务,从而更轻松地测试和开发 AI 应用程序,而无需担心本地配置问题。

用于 Ollama AI 服务推理的 Testcontainers 对象

OllamaContainer 类提供了一种与 Ollama 容器化实例交互的简化方式,Ollama 用于为推理提供 AI 模型。它简化了启动 Ollama 服务、列出可用模型、拉取新模型以及查询服务以获取预测等任务。以下是使用 OllamaContainer 类的详细说明,以及说明典型用例的代码片段。

功能

  1. 容器管理

    • 自动处理 Ollama 容器的生命周期。
    • 启动容器并确保在使用后正确停止和清理。
  2. 模型管理

    • 允许列出可用模型。
    • 支持拉取新模型(如果尚未可用)。
  3. 推理请求

    • 提供通过 HTTP 端点与模型进行推理任务的方法。

代码示例

testcontainers 库中的 OllamaContainer 类是 AI 模型开发人员的强大工具,它提供了一种管理容器化推理环境的直接方式。通过封装设置和拆卸的复杂性,它允许开发人员专注于构建和测试其应用程序,并获得可靠和可重现的结果。

基本用法

以下代码片段演示了如何使用 OllamaContainer 类设置环境、列出可用模型并执行推理任务。


from json import loads
from pathlib import Path
from requests import post, RequestException
from testcontainers.ollama import OllamaContainer

def split_by_line(generator):
    data = b''
    for each_item in generator:
        for line in each_item.splitlines(True):
            data += line
            if data.endswith((b'\r\r', b'\n\n', b'\r\n\r\n', b'\n')):
                yield from data.splitlines()
                data = b''
    if data:
        yield from data.splitlines()

def main():
    with OllamaContainer(ollama_home=Path.home() / ".ollama") as ollama:
        # List available models
        models = ollama.list_models()
        print("Available models:", models)

        # Choose a specific model, for example 'yi:6b-v1.5'
        model_name = "yi:6b-v1.5"
        if model_name not in [model["name"] for model in models]:
            print(f"Model '{model_name}' not found, pulling the model.")
            ollama.pull_model(model_name)
            print(f"Model '{model_name}' has been pulled.")
        
        # Use the model to generate responses in an interactive chat
        try:
            endpoint = ollama.get_endpoint()
            print("You can now start chatting with the model. Type 'exit' to quit.")

            while True:
                user_input = input("You: ")
                if user_input.lower() == "exit":
                    print("Exiting chat.")
                    break
                
                response = post(
                    url=f"{endpoint}/api/chat", 
                    stream=True, 
                    json={
                        "model": model_name,
                        "messages": [{
                            "role": "user",
                            "content": user_input
                        }]
                    }
                )
                response.raise_for_status()

                for chunk in split_by_line(response.iter_content()):
                    model_response = loads(chunk)["message"]["content"]
                    print(f"Model: {model_response}", end="")

        except RequestException as e:
            print(f"An error occurred: {e}")

if __name__ == "__main__":
    main()

关键方法和属性

  1. __init__(ollama_home: Path):

    • 参数: ollama_home (Path) - Ollama 配置和模型文件存储的目录。
    • 描述: 使用 Ollama 指定的主目录初始化容器。
  2. list_models():

    • 返回: 可用模型的列表。
    • 描述: 检索容器中当前可用模型的列表。
  3. pull_model(model_name: str):

    • 参数: model_name (str) - 要拉取的模型名称。
    • 描述: 如果指定的模型尚未可用,则拉取它。
  4. get_endpoint():

    • 返回: 包含用于访问模型的端点 URL 的字符串。
    • 描述: 提供模型推理 API 的访问 URL。
  5. __enter__()__exit__()

    • 描述: 处理容器的上下文管理,根据需要启动和停止它。

最棒的部分

现在您可以在代码中直接部署容器,移除容器,节省资源,更严格地进行测试,并创建自己的对象!

加入我们

链接

在下方提问!👇🏻

运行此脚本有困难吗?在下方提出大量问题,没问题!

社区

注册登录 以评论