在 Go 中使用 Ollama Web Search API

发布: (2025年12月5日 GMT+8 13:40)
5 min read
原文: Dev.to

Source: Dev.to

使用 Ollama Web Search API 的 Go 示例封面图片

入门

Ollama 是否有官方的 Go Web 搜索库?
Ollama 提供了一个适用于任何 Go HTTP 客户端的 REST Web 搜索 API。虽然目前还没有官方的 Go SDK,但你可以使用标准库轻松实现 API 调用。

  1. 从你的 Ollama 账户 创建一个 API 密钥。
  2. 将 API 密钥设置为环境变量。
export OLLAMA_API_KEY="your_api_key"

在 Windows PowerShell 中:

$env:OLLAMA_API_KEY = "your_api_key"

想要获取 Ollama 命令和使用方式的完整参考,请参阅 Ollama cheatsheet

项目设置

创建一个新的 Go 模块:

mkdir ollama-search
cd ollama-search
go mod init ollama-search

基础 Web 搜索

如何在 Go 中使用 Ollama 的 Web 搜索 API 进行身份验证?
在请求头中使用 Authorization 并将你的 API 密钥作为 Bearer token 传入。

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
)

// Request/Response types for web_search
type WebSearchRequest struct {
	Query      string `json:"query"`
	MaxResults int    `json:"max_results,omitempty"`
}

type WebSearchResult struct {
	Title   string `json:"title"`
	URL     string `json:"url"`
	Content string `json:"content"`
}

type WebSearchResponse struct {
	Results []WebSearchResult `json:"results"`
}

func webSearch(query string, maxResults int) (*WebSearchResponse, error) {
	apiKey := os.Getenv("OLLAMA_API_KEY")
	if apiKey == "" {
		return nil, fmt.Errorf("OLLAMA_API_KEY environment variable not set")
	}

	reqBody := WebSearchRequest{
		Query:      query,
		MaxResults: maxResults,
	}
	jsonData, err := json.Marshal(reqBody)
	if err != nil {
		return nil, fmt.Errorf("failed to marshal request: %w", err)
	}

	req, err := http.NewRequest("POST", "https://ollama.com/api/web_search", bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %w", err)
	}
	req.Header.Set("Authorization", "Bearer "+apiKey)
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("request failed: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return nil, fmt.Errorf("API error (status %d): %s", resp.StatusCode, string(body))
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("failed to read response: %w", err)
	}

	var searchResp WebSearchResponse
	if err := json.Unmarshal(body, &searchResp); err != nil {
		return nil, fmt.Errorf("failed to unmarshal response: %w", err)
	}
	return &searchResp, nil
}

func truncate(s string, maxLen int) string {
	if len(s) = 5 {
			fmt.Printf("  ... and %d more\n", len(result.Links)-5)
			break
		}
		fmt.Printf("  - %s\n", link)
	}
}

可复用的客户端包

创建一个可复用的 Ollama 客户端包,以获得更简洁的代码。

// ollama/client.go
package ollama

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

type Client struct {
	apiKey     string
	httpClient *http.Client
	baseURL    string
}

func NewClient() (*Client, error) {
	apiKey := os.Getenv("OLLAMA_API_KEY")
	if apiKey == "" {
		return nil, fmt.Errorf("OLLAMA_API_KEY environment variable not set")
	}
	return &Client{
		apiKey: apiKey,
		httpClient: &http.Client{
			Timeout: 30 * time.Second,
		},
		baseURL: "https://ollama.com/api",
	}, nil
}

// Generic POST helper
func (c *Client) post(endpoint string, payload interface{}, out interface{}) error {
	jsonData, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("marshal error: %w", err)
	}
	req, err := http.NewRequest("POST", c.baseURL+endpoint, bytes.NewBuffer(jsonData))
	if err != nil {
		return fmt.Errorf("request creation error: %w", err)
	}
	req.Header.Set("Authorization", "Bearer "+c.apiKey)
	req.Header.Set("Content-Type", "application/json")

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("request error: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return fmt.Errorf("API error (status %d): %s", resp.StatusCode, string(body))
	}
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("read error: %w", err)
	}
	if err := json.Unmarshal(body, out); err != nil {
		return fmt.Errorf("unmarshal error: %w", err)
	}
	return nil
}

// WebSearch calls the /web_search endpoint
func (c *Client) WebSearch(query string, maxResults int) (*WebSearchResponse, error) {
	req := WebSearchRequest{
		Query:      query,
		MaxResults: maxResults,
	}
	var resp WebSearchResponse
	if err := c.post("/web_search", req, &resp); err != nil {
		return nil, err
	}
	return &resp, nil
}

// WebFetch calls the /web_fetch endpoint
func (c *Client) WebFetch(url string) (*WebFetchResponse, error) {
	req := WebFetchRequest{URL: url}
	var resp WebFetchResponse
	if err := c.post("/web_fetch", req, &resp); err != nil {
		return nil, err
	}
	return &resp, nil
}

现在可以在你的应用中使用该客户端:

package main

import (
	"fmt"
	"log"

	"yourmodule/ollama"
)

func main() {
	client, err := ollama.NewClient()
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}

	// 示例:网页搜索
	searchRes, err := client.WebSearch("Ollama Go SDK", 3)
	if err != nil {
		log.Fatalf("Search error: %v", err)
	}
	for _, r := range searchRes.Results {
		fmt.Printf("- %s (%s)\n", r.Title, r.URL)
	}

	// 示例:获取页面内容
	fetchRes, err := client.WebFetch("https://ollama.com")
	if err != nil {
		log.Fatalf("Fetch error: %v", err)
	}
	fmt.Printf("\nFetched title: %s\n", fetchRes.Title)
}
Back to Blog

相关文章

阅读更多 »