官方API与OpenAI SDK的关键差异及实现原理

先放两个代码看看有什么不同,分别用的哪两种方法,让他联网

第一个:

from fastapi import FastAPI, Request
from openai import OpenAI
import os
from dotenv import load_dotenv

load_dotenv()
app = FastAPI()

@app.post('/chat')
async def get_response(request: Request):
    data = await request.json()
    messages = data['messages']

    # 联网参数配置
    enable_search = True
    search_options = {
        "forced_search": True,
        "search_strategy": "pro"
    }

    client = OpenAI(
        api_key=os.getenv("QW_API_KEY"),
        base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    )

    completion = client.chat.completions.create(
        model="qwen-plus",
        messages=messages,
        # 核心联网检索参数
        enable_search=enable_search,
        search_options=search_options
    )
    response_text = completion.choices[0].message.content
    return {"response": response_text}

if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8005)

第二个:

from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
import httpx
import os
from dotenv import load_dotenv

load_dotenv()
app = FastAPI()

# 添加 CORS 支持
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

DASHSCOPE_API_KEY = os.getenv("QW_API_KEY")
DASHSCOPE_CHAT_URL = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation"

# 我们需要通过 HTTP 请求直接调用 DashScope 的兼容模式 API 来发送请求,而不是依赖 openai SDK 的封装方式。
@app.post('/chat')
async def get_response(request: Request):
    data = await request.json()
    messages = data['messages']

    headers = {
        "Authorization": f"Bearer {DASHSCOPE_API_KEY}",
        "Content-Type": "application/json"
    }

    payload = {
        "model": "qwen-plus",
        "input": {
            "prompt": messages[-1]["content"],
            "history": [{"user": m["content"] if m["role"]=="user" else None,
                         "bot": m["content"] if m["role"]=="assistant" else None}
                        for m in messages[:-1] if m["role"] in ["user", "assistant"]]
        },
        "parameters": {
            "enable_search": True
        }
    }

    async with httpx.AsyncClient() as client:
        try:
            response = await client.post(DASHSCOPE_CHAT_URL, json=payload, headers=headers, timeout=60)
            result = response.json()
            return {"response": result.get("output", {}).get("text", "未获取到返回结果")}
        except Exception as e:
            return {"response": f"调用失败: {str(e)}"}

if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8005)


问题核心:为什么有的代码能联网,有的不能?

许多开发者在对接通义千问(Qwen)时遇到一个关键问题:为什么有些实现能够触发联网搜索功能,而有些则不能? 本文将深入解析这一问题的技术根源,对比官方API与OpenAI SDK的实现差异。

能联网的实现

官方API直连方案

通过直接调用DashScope官方的 /text-generation/generation 端点, 并正确设置 enable_search 参数, 可以触发通义千问的联网搜索功能。

不能联网的实现

OpenAI SDK兼容方案

使用OpenAI兼容接口(/compatible-mode/v1)时, 即使传递了 enable_search 参数, 服务端也可能忽略该参数或无法正确处理。

关键代码:能联网的API调用实现

以下Python代码展示了如何正确调用DashScope API触发联网搜索功能:

联网搜索的关键API调用

import httpx

# DashScope官方API端点
url = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation"

headers = {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json"
}

# 正确的请求体结构
payload = {
    "model": "qwen-plus",
    "input": {
        "prompt": messages[-1]["content"],
        "history": [
            {"user": m["content"] if m["role"]=="user" else None,
            "bot": m["content"] if m["role"]=="assistant" else None
            } for m in messages[:-1] if m["role"] in ["user", "assistant"]
        ]
    },
    # 关键参数:启用联网搜索
    "parameters": {
        "enable_search": True  # 这是启动联网搜索的核心参数
    }
}

response = httpx.post(url, headers=headers, json=payload)

关键点分析

1. 端点正确: 使用DashScope官方的 /text-generation/generation 端点
2. 参数位置正确: enable_search 参数位于 parameters 对象中
3. 结构完整: 包含完整的 modelinputparameters 结构

技术流程对比:联网 vs 非联网

联网搜索流程

前端应用 → FastAPI后端 → HTTP POST到generation API → DashScope服务端

服务端检测到 enable_search: True → 执行联网搜索 → 整合实时结果 → 返回响应

非联网流程

前端应用 → FastAPI后端 → OpenAI兼容接口调用 → DashScope兼容接口

兼容接口可能忽略 enable_search 参数 → 仅使用模型内部知识 → 返回响应

结果:成功联网

服务端自动进行联网查询,将最新搜索结果作为模型输入的一部分,生成包含实时信息的回复。

结果:无法联网

即使请求中包含 enable_search 参数,服务端可能直接忽略,模型仅使用训练时的知识生成回复。

官方文档侧证

 DashScope官方文档 - 文本生成APIhttps://help.aliyun.com/document_detail/611911.html

官方文档关键说明

parameters.enable_search: 布尔值,可选。
开启后模型会自动根据用户意图检索互联网实时信息并结合生成内容。

// 注意:此参数仅在text-generation API中有效
// OpenAI兼容接口可能不支持此参数

重要提示

官方文档明确指出:只有 /generation 接口完全支持所有参数, OpenAI兼容接口可能无法支持RAG等新功能参数。

联网搜索技术解析

1. 联网搜索触发条件

服务端检测到 enable_search: true 参数时,自动触发联网搜索流程

2. 实时信息检索

根据用户query,从可信来源获取最新信息(新闻、百科、技术文档等)

3. RAG整合

将检索结果与模型知识结合,生成既准确又实时的回答

4. 高级参数控制

可使用 search_options 进一步控制搜索行为:

  • 搜索策略选择
  • 结果数量限制
  • 特定网站优先

高级搜索参数示例

"parameters": {
    "enable_search": True,
    "search_options": {
        "strategy": "balanced",  # 搜索策略:balanced/focused/comprehensive
        "max_results": 5,         # 最大结果数
        "prefer_sites": [        # 优先考虑的网站
            "*.wikipedia.org",
            "*.stackoverflow.com"
        ]
    }
}

技术总结

代码能联网,是因为使用的是DashScope官方text-generation接口,并且正确传递了enable_search参数。

而之前使用OpenAI SDK或兼容接口的方式,无法保证enable_search参数能被正确处理,因为:

  • 兼容接口可能未实现RAG功能参数转发
  • 参数位置和格式可能与官方API不同
  • 服务端对兼容接口的参数支持不完整

要实现可靠的联网搜索功能,必须直接调用DashScope的/generation接口,并遵循官方文档的参数格式要求。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐