Google 于 2026 年初弃用了其免费的自定义搜索引擎 JSON API 层,破坏了数千个依赖其进行网络基础的本地 LLM 设置。如果您的基于 Ollama 的助手使用 CSE 进行搜索,您需要一个直接替换,它返回结构化 JSON,不需要 OAuth,并使用简单的 API 密钥。 Scavio 搜索端点接受相同的查询输入、结果输出模式,并返回更丰富的数据,包括 AI 概述和 People Also Ask。本教程只需不到 20 行代码即可将 Ollama 搜索集成从 CSE 迁移到 Scavio。
前置条件
- Ollama 在本地安装并运行
- 已安装 Python 3.9+
- 请求已安装库
- 来自 scavio.dev 的 Scavio API 密钥
操作指南
步骤 1: 删除旧的 CSE 集成
识别并删除 Google CSE 客户端代码。典型的 CSE 模式使用 cx 参数和不再有效的 googleapis.com 端点。
# OLD CSE code (no longer works as of 2026):
# response = requests.get(
# 'https://www.googleapis.com/customsearch/v1',
# params={'key': CSE_KEY, 'cx': CSE_ID, 'q': query}
# )
# NEW: Scavio replaces the above
import os, requests
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'}
URL = 'https://api.scavio.dev/api/v1/search'步骤 2: 为 Ollama 构建 Scavio 搜索功能
创建一个与 Ollama 工具期望的界面相匹配的搜索功能。以 LLM 可以解析的格式返回结果。
def web_search(query: str, num_results: int = 5) -> str:
"""Search the web and return formatted results for the LLM."""
resp = requests.post(URL, headers=H,
json={'query': query, 'country_code': 'us', 'num_results': num_results})
resp.raise_for_status()
data = resp.json()
results = data.get('organic_results', [])
formatted = []
for r in results:
formatted.append(f"Title: {r['title']}\nURL: {r['link']}\nSnippet: {r.get('snippet', '')}")
return '\n\n'.join(formatted)步骤 3: 连线搜索 Ollama 的工具调用
将搜索函数注册为 Ollama 在生成过程中可以调用的工具。这使用 Ollama 的 Python 客户端和工具支持。
import ollama
def run_ollama_with_search(prompt: str, model: str = 'llama3.1') -> str:
tools = [{
'type': 'function',
'function': {
'name': 'web_search',
'description': 'Search the web for current information',
'parameters': {
'type': 'object',
'properties': {
'query': {'type': 'string', 'description': 'Search query'}
},
'required': ['query']
}
}
}]
response = ollama.chat(model=model, messages=[{'role': 'user', 'content': prompt}], tools=tools)
# Handle tool calls
if response.message.tool_calls:
for tc in response.message.tool_calls:
if tc.function.name == 'web_search':
search_results = web_search(tc.function.arguments.get('query', prompt))
# Feed results back to the model
messages = [
{'role': 'user', 'content': prompt},
response.message,
{'role': 'tool', 'content': search_results}
]
final = ollama.chat(model=model, messages=messages)
return final.message.content
return response.message.content
print(run_ollama_with_search('What are the top Python web frameworks in 2026?'))Python 示例
import os, requests, ollama
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'}
def web_search(query, num=5):
resp = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'query': query, 'country_code': 'us', 'num_results': num})
results = resp.json().get('organic_results', [])
return '\n'.join(f'{r["title"]}: {r.get("snippet","")}' for r in results)
def ask_with_search(prompt, model='llama3.1'):
tools = [{'type': 'function', 'function': {
'name': 'web_search', 'description': 'Search the web',
'parameters': {'type': 'object', 'properties': {
'query': {'type': 'string'}}, 'required': ['query']}}}]
resp = ollama.chat(model=model, messages=[{'role': 'user', 'content': prompt}], tools=tools)
if resp.message.tool_calls:
results = web_search(resp.message.tool_calls[0].function.arguments.get('query', prompt))
final = ollama.chat(model=model, messages=[
{'role': 'user', 'content': prompt}, resp.message,
{'role': 'tool', 'content': results}])
return final.message.content
return resp.message.content
print(ask_with_search('Latest AI news 2026'))JavaScript 示例
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;
async function webSearch(query) {
const resp = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query, country_code: 'us', num_results: 5 })
});
const data = await resp.json();
return (data.organic_results || []).map(r => `${r.title}: ${r.snippet || ''}`).join('\n');
}
async function askOllamaWithSearch(prompt) {
const resp = await fetch('http://localhost:11434/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'llama3.1', messages: [{ role: 'user', content: prompt }],
tools: [{ type: 'function', function: { name: 'web_search',
description: 'Search the web', parameters: { type: 'object',
properties: { query: { type: 'string' } }, required: ['query'] }}}]
})
});
const data = await resp.json();
if (data.message?.tool_calls?.length) {
const results = await webSearch(data.message.tool_calls[0].function.arguments.query);
console.log('Search results:', results);
}
}
askOllamaWithSearch('Latest AI news 2026');预期输出
Search results for: 'top Python web frameworks 2026'
Title: FastAPI 1.0 Released: The Modern Python Web Framework
URL: https://fastapi.tiangolo.com/release-notes/
Snippet: FastAPI 1.0 brings stable APIs and improved performance...
Title: Django 6.0 Features Overview
URL: https://docs.djangoproject.com/en/6.0/
Snippet: Django 6.0 introduces async-first ORM and built-in AI...
Ollama response: Based on current search results, the top Python web frameworks in 2026 are FastAPI 1.0, Django 6.0, and Litestar...