1. 项目概述与核心价值

最近在折腾本地大模型部署和集成开发时,发现了一个非常趁手的工具—— aaronrussell/ollama-ex 。这本质上是一个为 Elixir 语言生态量身打造的 Ollama 客户端库。如果你和我一样,正在用 Elixir 或 Phoenix 框架构建需要集成本地大语言模型能力的应用,比如智能客服后台、代码辅助工具,或是任何需要离线、可控 AI 推理的场景,那么这个库很可能就是你一直在找的那块拼图。

简单来说,Ollama 是一个强大的工具,它让你能在自己的电脑或服务器上,像拉取 Docker 镜像一样,轻松运行 Llama 3、Mistral、Gemma 等各类开源大模型。而 ollama-ex 则是在 Elixir 世界里,一个优雅的“接线员”,它用 Elixir 的方式封装了与 Ollama 服务通信的所有细节。你不用再去手动拼接 HTTP 请求、处理 JSON 解析和连接管理,只需要调用几个清晰的函数,就能完成模型拉取、对话生成、嵌入向量计算等一系列操作。这大大降低了在 Elixir 应用中引入 AI 能力的门槛,让开发者能更专注于业务逻辑本身。

2. 核心功能与设计思路拆解

2.1 为什么选择 Elixir 与 Ollama 的组合?

在深入 ollama-ex 之前,有必要先理解这个技术栈搭配的合理性。Elixir 基于 Erlang VM (BEAM),以其高并发、低延迟、容错性强和“任其崩溃”的哲学闻名,特别适合构建需要高可靠性和实时性的分布式系统,比如聊天应用、数据流处理管道。而现代的大语言模型应用,尤其是面向生产环境的,往往也要求能够处理大量并发请求、保持服务稳定,并且能够优雅地处理模型推理可能出现的超时或错误。

Ollama 解决了模型部署和运行环境一致性的问题,它通过容器化的方式封装了模型及其依赖,提供了统一的 REST API 和命令行接口。 ollama-ex 的出现,正是为了弥合 Elixir 生态与 Ollama API 之间的鸿沟。它的设计思路非常“Elixir化”:提供一套简洁的 API,底层利用 Elixir 强大的 Req Tesla 等 HTTP 客户端库处理网络通信,将 Ollama 的响应转化为 Elixir 原生的数据结构(如 Map、Struct),并且充分考虑到了 Elixir 的并发模型,使得在 GenServer、Task 或 Phoenix Channel 中调用模型变得非常自然。

2.2 库的核心能力全景

ollama-ex 覆盖了 Ollama 官方 API 的绝大部分核心功能,我们可以将其能力分为几个层次:

  1. 模型管理层 :这是基础。包括从 Ollama 服务器拉取(Pull)模型、查看本地已有模型列表(List)、删除(Delete)模型等。这对应着 Ollama CLI 中的 ollama pull , ollama list , ollama rm 等操作。
  2. 对话与生成层 :这是最常用的功能。给定一个提示词(Prompt)和模型名,库会帮你发起生成请求,并以流式或非流式的方式返回模型的文本响应。这对应着 ollama run 或 API 的 /api/generate 端点。流式响应对于构建实时交互体验至关重要。
  3. 嵌入向量层 :许多高级应用(如语义搜索、文本分类、聚类)依赖于文本的向量表示。 ollama-ex 提供了便捷的函数来获取文本的嵌入向量,这对应着 Ollama API 的 /api/embed 端点。
  4. 服务与管理层 :包括复制模型、查看模型信息等进阶操作。

这个库的设计并非简单地将 HTTP 端点映射为函数,而是做了良好的抽象。例如,它将生成请求的众多可选参数(如温度 temperature 、最大 token 数 num_predict 、停止词 stop 等)封装在一个清晰的结构体中,提高了代码的可读性和可维护性。

3. 环境准备与基础配置

3.1 前置条件:Ollama 的安装与运行

在使用 ollama-ex 之前,必须确保 Ollama 服务已经在你的开发或生产环境中运行起来。这个过程非常简单。

在 macOS 或 Linux 上 ,通常一行命令就能搞定:

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

安装完成后,Ollama 服务会自动启动。你可以通过 ollama serve 来显式启动服务,默认会在 11434 端口监听。

在 Windows 上 ,可以直接从 Ollama 官网下载安装程序。安装后,Ollama 会作为系统服务运行。

验证 Ollama 是否运行正常:

ollama list

如果正常,它会列出已拉取的模型(初始为空),或者返回一个空列表。你也可以尝试拉取一个小模型进行测试:

ollama pull llama3.2:1b

这个命令会下载 Meta 最新的 Llama 3.2 1B 参数模型,体积较小,适合快速测试。

注意 :Ollama 服务默认绑定在 127.0.0.1:11434 。如果你计划让运行在 Docker 容器内或另一台主机上的 Elixir 应用访问,需要在启动 Ollama 时指定主机参数,如 OLLAMA_HOST=0.0.0.0 ollama serve 。请注意,将服务暴露在非本地网络环境时,务必考虑网络安全问题。

3.2 在 Elixir 项目中集成 ollama-ex

假设你已经有一个现成的 Elixir 或 Phoenix 项目。集成 ollama-ex 的第一步是将其添加到依赖中。

打开你的 mix.exs 文件,在 deps 函数中添加:

defp deps do
  [
    {:ollama_ex, "~> 0.1.0"}, # 请检查 Hex.pm 以获取最新版本
    # ... 你的其他依赖
  ]
end

然后运行 mix deps.get 来获取这个库。

接下来,通常需要配置 Ollama 服务器的连接信息。虽然 ollama-ex 有默认值( http://localhost:11434 ),但在生产环境中,我们最好将其放在配置文件中。

config/config.exs 或环境特定的配置文件中(如 config/dev.exs ),添加:

config :ollama_ex, :base_url, System.get_env("OLLAMA_BASE_URL") || "http://localhost:11434"

这里我推荐使用环境变量 OLLAMA_BASE_URL 来管理连接地址,这样在不同环境(开发、测试、生产)中可以灵活切换,也避免了在代码库中硬编码敏感信息。

3.3 初步测试:建立连接与列出模型

配置完成后,我们可以写一个简单的测试脚本来验证一切是否就绪。创建一个新文件 test_ollama.exs (或者直接在 IEx 中运行):

# 在 IEx 中,或使用 `elixir test_ollama.exs` 运行
IO.puts("正在连接 Ollama 服务...")

case OllamaEx.Models.list() do
  {:ok, %{models: models}} ->
    IO.puts("连接成功!本地模型列表:")
    Enum.each(models, fn model -> IO.puts("  - #{model.name}") end)
    if Enum.empty?(models) do
      IO.puts("  (暂无模型,请使用 `ollama pull <model-name>` 拉取)")
    end

  {:error, reason} ->
    IO.puts("连接失败:#{inspect(reason)}")
    IO.puts("请检查:")
    IO.puts("  1. Ollama 服务是否正在运行?(`ollama serve`)")
    IO.puts("  2. 配置的 base_url (#{Application.get_env(:ollama_ex, :base_url)}) 是否正确?")
    IO.puts("  3. 网络是否通畅?")
end

这个脚本尝试调用 OllamaEx.Models.list/0 函数。如果成功,它会打印出本地已有的所有模型;如果失败,则会给出清晰的错误排查指引。这是与 Ollama 交互的第一步,确保通信链路是通的。

4. 核心操作详解与实战

4.1 模型管理:拉取、查看与删除

模型是 Ollama 的核心资产。 ollama-ex OllamaEx.Models 模块下提供了完整的管理功能。

拉取模型 :这是最耗时的操作,因为需要从网络下载模型文件。 ollama-ex pull/2 函数支持流式响应,这对于在命令行或 Web 界面中显示下载进度非常友好。

# 拉取一个模型,并实时打印进度
stream = OllamaEx.Models.pull("llama3.2:3b", stream: true)

Task.async(fn ->
  for chunk <- stream do
    case chunk do
      {:ok, %{status: status, digest: digest}} when status in ["pulling", "downloading"] ->
        IO.write("\r状态: #{status} | 摘要: #{String.slice(digest, 0, 12)}...")
      {:ok, %{status: "success"}} ->
        IO.puts("\n模型拉取成功!")
      {:error, error} ->
        IO.puts("\n拉取出错: #{inspect(error)}")
    end
  end
end)
# 等待任务完成

在实际应用中,你可以将这些进度事件通过 Phoenix Channel 推送到前端,实现一个漂亮的下载进度条。

列出与删除模型

# 列出所有模型
{:ok, response} = OllamaEx.Models.list()
models = response.models

# 删除一个模型
case OllamaEx.Models.delete("old-model:tag") do
  {:ok, _} -> IO.puts("模型删除成功。")
  {:error, reason} -> IO.puts("删除失败: #{inspect(reason)}")
end

实操心得 :在删除模型前,尤其是生产环境,最好有一个确认机制,或者确保该模型确实没有被任何正在运行的服务所使用。因为模型文件通常很大,重新拉取会消耗时间和带宽。

4.2 文本生成:从简单问答到复杂对话

文本生成是 ollama-ex 最主要的功能,通过 OllamaEx.Generations.generate/2 函数实现。

基础生成

prompt = "用简单的语言解释一下什么是 Elixir 的宏(Macro)?"

case OllamaEx.Generations.generate("llama3.2:3b", prompt: prompt) do
  {:ok, %{response: answer}} ->
    IO.puts("模型回答:\n#{answer}")

  {:error, error} ->
    IO.puts("生成失败:#{inspect(error)}")
end

这将会阻塞执行,直到模型生成完整的回答。对于较长的文本,这可能需要几秒到几十秒。

流式生成 :为了更好的用户体验,特别是构建聊天应用时,流式生成是必须的。它允许你一边生成,一边将 token 推送给用户。

prompt = "写一个关于一只会编程的猫的短故事。"
stream = OllamaEx.Generations.generate("llama3.2:3b", prompt: prompt, stream: true)

full_response = ""
for chunk <- stream do
  case chunk do
    {:ok, %{response: token}} ->
      # 逐个 token 输出,模拟打字机效果
      IO.write(token)
      full_response = full_response <> token
    {:done, _} ->
      IO.puts("\n\n--- 生成完毕 ---")
    {:error, error} ->
      IO.puts("\n流式中断:#{inspect(error)}")
  end
end

在 Phoenix 应用中,你可以将每个 {:ok, %{response: token}} 事件通过 Channel 实时推送到浏览器。

高级参数调控 :生成的质量和风格可以通过参数精细控制。

options = %{
  prompt: "将以下英文翻译成中文:'The quick brown fox jumps over the lazy dog.'",
  model: "llama3.2:3b",
  stream: false,
  options: %{
    temperature: 0.3, # 温度越低,输出越确定、保守;越高越有创造性、随机性。通常 0.7-0.9 用于创意,0.1-0.3 用于事实性任务。
    top_p: 0.9,       # 核采样,与温度配合使用,控制输出 token 的候选集。
    num_predict: 100, # 生成的最大 token 数。
    stop: ["\n", "。"] # 遇到这些序列时停止生成。
  }
}

{:ok, result} = OllamaEx.Generations.generate(options)

理解这些参数对产出结果的影响至关重要。例如,在代码生成场景下,较低的 temperature (如 0.2) 能产生更稳定、可预测的代码片段;而在创意写作中,较高的 temperature (如 0.8) 能带来更多惊喜。

4.3 嵌入向量:解锁语义理解能力

嵌入向量是将文本转换为高维空间中的数值向量的过程,语义相似的文本其向量距离也近。 ollama-ex 通过 OllamaEx.Embeddings.create/2 提供此功能。

texts = [
  "我喜欢吃苹果和香蕉。",
  "水果中,苹果和香蕉是我的最爱。",
  "今天的天气真好,适合出去散步。"
]

case OllamaEx.Embeddings.create("nomic-embed-text", texts) do
  {:ok, %{embeddings: embeddings}} ->
    # `embeddings` 是一个列表,其中每个元素是对应文本的向量(浮点数列表)
    IO.puts("成功生成 #{length(embeddings)} 个嵌入向量。")
    IO.puts("第一个向量的维度是:#{length(hd(embeddings))}")

    # 简单计算前两个句子的余弦相似度(需要额外实现)
    # vec1 = hd(embeddings)
    # vec2 = hd(tl(embeddings))
    # similarity = cosine_similarity(vec1, vec2)
    # IO.puts("句子1和句子2的语义相似度:#{similarity}")

  {:error, error} ->
    IO.puts("生成嵌入失败:#{inspect(error)}")
end

嵌入向量可以用于:

  • 语义搜索 :将用户查询和文档库都转换为向量,然后计算相似度,返回最相关的文档。
  • 文本分类/聚类 :基于向量进行机器学习任务。
  • 去重 :识别内容高度相似的文本。

注意事项 :不同的模型生成的嵌入向量维度不同(如 768, 1024, 4096),且向量空间不可直接跨模型比较。选择一个合适的嵌入模型(如 nomic-embed-text , all-minilm )并全程使用它非常重要。此外,生成嵌入向量本身也有计算开销,对于大批量文本,需要考虑异步处理和缓存策略。

5. 在 Phoenix 应用中的集成模式

ollama-ex 集成到 Phoenix 框架中,可以构建出功能强大的 AI 应用。以下是几种常见的模式。

5.1 后台任务与 GenServer 封装

模型生成可能耗时较长,不适合在请求-响应周期内同步执行。我们可以用 GenServer 或 Oban(后台作业库)来异步处理。

使用 GenServer 封装一个模型服务

# lib/my_app/ollama_service.ex
defmodule MyApp.OllamaService do
  use GenServer

  @default_model "llama3.2:3b"

  # 客户端 API
  def start_link(opts \\ []) do
    GenServer.start_link(__MODULE__, opts, name: __MODULE__)
  end

  def generate(prompt, opts \\ %{}) do
    GenServer.call(__MODULE__, {:generate, prompt, opts})
  end

  # 服务器端回调
  @impl true
  def init(_opts) do
    {:ok, %{model: @default_model}}
  end

  @impl true
  def handle_call({:generate, prompt, opts}, _from, state) do
    model = Map.get(opts, :model, state.model)
    generation_opts = %{
      prompt: prompt,
      stream: false,
      options: %{
        temperature: Map.get(opts, :temperature, 0.7),
        num_predict: Map.get(opts, :max_tokens, 512)
      }
    }

    result = OllamaEx.Generations.generate(model, generation_opts)
    {:reply, result, state}
  end
end

application.ex 中将其加入监督树:

children = [
  MyApp.OllamaService,
  # ... 其他子进程
]

这样,在控制器或上下文模块中,就可以异步地调用 MyApp.OllamaService.generate("你好") ,而不会阻塞 Web 请求。

5.2 实时聊天:与 Phoenix Channels 结合

这是最激动人心的集成方式。我们可以创建一个 Channel,让前端 WebSocket 连接上来,发送消息并实时接收流式的模型回复。

# lib/my_app_web/channels/chat_channel.ex
defmodule MyAppWeb.ChatChannel do
  use Phoenix.Channel

  intercept ["new_token"] # 拦截自己广播的消息,可做特殊处理

  def join("chat:room", _payload, socket) do
    {:ok, socket}
  end

  def handle_in("new_message", %{"text" => prompt}, socket) do
    # 异步处理生成任务,避免阻塞 channel
    Task.start(fn ->
      stream = OllamaEx.Generations.generate("llama3.2:3b", prompt: prompt, stream: true)

      for chunk <- stream do
        case chunk do
          {:ok, %{response: token}} ->
            # 将每个 token 实时推送给这个 socket 的所有订阅者
            broadcast!(socket, "new_token", %{token: token})
          {:done, _} ->
            broadcast!(socket, "new_token", %{token: "[DONE]"})
          {:error, error} ->
            broadcast!(socket, "error", %{message: "生成出错: #{inspect(error)}"})
        end
      end
    end)

    {:noreply, socket}
  end

  # 可选:处理 token 广播
  def handle_out("new_token", payload, socket) do
    push(socket, "new_token", payload)
    {:noreply, socket}
  end
end

前端 JavaScript 可以连接到这个 Channel,发送消息并监听 "new_token" 事件,从而实现类似 ChatGPT 的打字机效果。

5.3 构建语义搜索 API

结合嵌入向量和向量数据库(如 PostgreSQL 的 pgvector 扩展,或专用的 Qdrant、Weaviate),可以构建一个本地的语义搜索 API。

  1. 文档预处理与向量化 :在后台任务中,读取你的文档(Markdown、PDF 等),分块,使用 ollama-ex 生成每块的嵌入向量,存入数据库。
  2. 搜索端点 :提供一个 Phoenix 控制器端点,接收查询文本。
# 控制器动作示例
def search(conn, %{"q" => query}) do
  # 1. 将查询文本转换为向量
  {:ok, %{embeddings: [query_vector]}} = OllamaEx.Embeddings.create("nomic-embed-text", [query])

  # 2. 在向量数据库中执行近似最近邻搜索
  results = MyApp.VectorDB.search_similar(query_vector, limit: 5)

  # 3. 返回最相关的文档片段
  render(conn, :search, results: results)
end
  1. 结果展示 :将搜索到的文档片段连同相似度分数一起返回给前端。

这种模式让你摆脱了对 OpenAI API 等外部服务的依赖,所有数据都在本地,隐私和安全得到保障,且没有调用次数限制。

6. 性能调优、错误处理与生产实践

6.1 性能考量与优化建议

  1. 模型选择 :在资源受限的环境(如低配 VPS、笔记本电脑)下,选择参数量更小的模型(如 1B、3B、7B 参数)至关重要。 llama3.2:1b phi3:mini qwen2.5:0.5b 等都是不错的起点。使用 ollama ps 可以查看模型运行时的资源占用。
  2. 参数调优 :减少生成长度 ( num_predict )、使用更高效的注意力实现(如果 Ollama 和模型支持)可以提升速度。对于嵌入任务,确保使用了针对嵌入优化的模型(如 nomic-embed-text ),而非通用的对话模型。
  3. 并发与连接池 :Elixir 天生擅长并发,但要注意到 Ollama 服务本身可能成为瓶颈。如果应用并发请求量很高,考虑:
    • 使用 连接池 管理到 Ollama 的 HTTP 连接。可以为 ollama-ex 配置一个专用的 HTTP 客户端(如使用 Finch 并设置连接池)。
    • 在 GenServer 中实现 请求队列 ,避免瞬间过多请求压垮 Ollama。
    • 对于非实时任务,使用 Oban 等后台作业库进行异步处理,平滑请求压力。
  4. 缓存策略 :对于频繁出现的、结果确定的查询(例如,“公司的介绍是什么?”),可以将模型的响应缓存起来(使用 Cachex Nebulex ),避免重复计算。

6.2 健壮的错误处理

网络服务总是不稳定的,必须为各种错误做好准备。

defp safe_generate(prompt, model \\ "llama3.2:3b") do
  case OllamaEx.Generations.generate(model, prompt: prompt, stream: false) do
    {:ok, %{response: response}} ->
      {:ok, response}

    {:error, %{status: status}} when status >= 500 ->
      # Ollama 服务器内部错误
      {:error, :ollama_server_error, "模型服务暂时不可用,请稍后重试。"}

    {:error, %{status: 404}} ->
      # 模型不存在
      {:error, :model_not_found, "未找到模型 '#{model}',请检查模型名称或先拉取模型。"}

    {:error, %{reason: :econnrefused}} ->
      # 连接被拒绝,Ollama 服务未运行
      {:error, :service_unavailable, "无法连接到 AI 服务,请确保服务已启动。"}

    {:error, reason} ->
      # 其他未知错误
      {:error, :unknown, "请求处理失败: #{inspect(reason)}"}
  end
end

在 Phoenix 控制器或 Channel 中,你可以根据这些结构化的错误信息,向用户返回友好的提示。

6.3 生产环境部署要点

  1. Ollama 服务管理 :在生产服务器上,建议使用 systemd Docker 来管理 Ollama 服务,确保其能随系统启动,并在崩溃后自动重启。
    • Docker 示例
    # 使用官方镜像
    docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama
    # 然后在容器内拉取模型
    docker exec -it ollama ollama pull llama3.2:3b
    
  2. 资源监控 :监控 Ollama 进程的内存和 CPU 使用情况。大模型加载时会占用大量 RAM。确保服务器有足够的交换空间或物理内存。
  3. 安全
    • 如果 Ollama 服务需要被外部网络访问,务必设置防火墙规则,仅允许受信任的 IP 段访问 11434 端口。
    • 考虑在 Ollama 前放置一个反向代理(如 Nginx),并配置 HTTPS 和基本的身份验证。
    • 永远不要在生产环境中使用默认的或弱的管理员密码(如果未来 Ollama 添加管理功能)。
  4. 版本固化 :在 mix.exs 中固定 ollama-ex 的版本,避免因库的自动升级导致线上服务意外中断。同时,记录所使用的 Ollama 版本和模型版本,便于问题复现和回滚。

7. 常见问题与排查技巧实录

在实际开发和运维中,你肯定会遇到各种问题。下面是我踩过的一些坑和解决方案。

7.1 连接与超时问题

问题: 调用 ollama-ex 函数时,返回 {:error, %{reason: :econnrefused}} 或超时错误。

  • 排查步骤 1:检查 Ollama 服务状态
    systemctl status ollama # 如果使用 systemd
    # 或
    docker ps | grep ollama # 如果使用 Docker
    
  • 排查步骤 2:确认端口和主机
    curl -v http://localhost:11434/api/tags
    
    如果本机 curl 成功,但 Elixir 应用失败,检查 Elixir 应用配置的 base_url (如 http://host.docker.internal:11434 用于容器间通信)。如果 curl 也失败,重启 Ollama 服务。
  • 排查步骤 3:调整超时设置 如果模型响应慢,可能需要增加 HTTP 客户端超时。如果你使用的是 Req ollama-ex 可能内部使用),可以在配置中调整:
    # config/config.exs
    config :ollama_ex, :http_client_opts, [
      receive_timeout: 300_000, # 5分钟,用于长文本生成
      connect_timeout: 10_000,
      pool_timeout: 10_000
    ]
    

7.2 模型相关错误

问题: {:error, %{status: 404, body: %{"error" => "model 'xxx' not found"}}}

  • 原因与解决 :指定的模型不存在。首先用 ollama list 确认本地是否有该模型。如果没有,使用 ollama pull <model-name> 拉取。注意模型名称严格区分大小写和标签(tag),例如 llama3.2:3b llama3.2:1b 是两个不同的模型。

问题: 生成速度异常缓慢,或内存占用飙升。

  • 排查 :首先通过 ollama ps 查看是哪个模型在运行及其资源占用。可能是模型太大,硬件撑不住。尝试换用更小的模型。此外,检查是否有多个进程在同时调用同一个模型,造成资源竞争。可以考虑用队列串行化请求。

7.3 流式响应中断

问题: 在 Phoenix Channel 中推送流式 token 时,连接偶尔会提前关闭,导致生成不完整。

  • 根因 :网络不稳定,或前端页面关闭/刷新。
  • 解决 :在 Task 中做好错误捕获,并将 Channel 的推送包装在 rescue 中。更健壮的做法是,将长文本生成任务放入 Oban 作业,将最终结果存入数据库,并通过一个独立的轮询或通知机制告知前端任务完成,而非完全依赖长连接的流式推送。

7.4 嵌入式部署的存储问题

问题: 在 Docker 或 Kubernetes 中,Ollama 拉取的模型在容器重启后丢失。

  • 解决 :必须将 Ollama 的数据目录(默认 ~/.ollama )挂载到宿主机持久化存储卷。
    docker run -d -v /path/on/host:/root/.ollama -p 11434:11434 --name ollama ollama/ollama
    
    在 Kubernetes 中,使用 PersistentVolumeClaim

7.5 内容安全与过滤

问题: 如何防止模型生成不受欢迎的内容?

  • 方案 :Ollama 本身有一些内置的模型安全机制,但不可完全依赖。必须在应用层(Elixir 后端)添加后处理过滤。
    • 使用关键词黑名单进行过滤。
    • 集成一个轻量级的文本分类模型,对输出进行二次检查。
    • 对于公开应用,设置清晰的内容政策,并建立用户举报和人工审核流程。
    • 在调用 ollama-ex generate 函数时,可以通过 options 中的 system 参数给模型一个强力的系统提示,约束其行为。例如:
    options = %{
      model: "llama3.2:3b",
      prompt: user_input,
      stream: false,
      system: "你是一个严谨、专业的助手。请确保你的回答安全、合法,且不包含任何有害或歧视性内容。",
      options: %{temperature: 0.5}
    }
    

ollama-ex 集成到你的 Elixir 项目中,就像是给一辆性能卓越的跑车(Elixir/ Phoenix)装上了一颗智能的引擎(本地大模型)。它开启了许多可能性,从简单的自动化脚本到复杂的、保护隐私的 AI 应用。关键在于理解整个技术栈的每个环节——从 Ollama 服务的运维,到 ollama-ex API 的调用方式,再到如何利用 Elixir 的并发模型进行优雅的集成。

Logo

免费领 50 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐