用duckduckgo的搜索API免费给大模型接入联网功能,让普通模型也能实现类似new bing的效果

DuckDuckGo 的搜索 API 免费给大模型接入联网功能,实现类似 New Bing 的效果

项目概述

通过集成 DuckDuckGo 搜索 API,为普通大语言模型赋予类似 New Bing 的实时网络访问和智能问答能力。复用大模型现有的的 Function calling 功能,实现高效灵活的查询处理和回答生成过程。

核心实现

系统采用了 Function calling 机制,实现了查询处理和回答生成的无缝集成:

  1. 查询分析和搜索:使用 claude-3-haikugpt-3.5-turbo 等较简易模型生成优化后的搜索关键词并通过 function calling 调用搜索API。
  2. 网络搜索:调用 DuckDuckGo API 执行实时信息检索。
  3. 智能回答生成:使用 claude-3-5-sonnnetgpt-4o 等较复杂模型结合搜索结果和原始问题,生成准确、全面的回答。

代码实现

1. 环境设置和函数定义

代码
import os
import json
from openai import OpenAI
from duckduckgo_search import DDGS

API_KEY = os.getenv("OPENAI_API_KEY")
BASE_URL = os.getenv("OPENAI_BASE_URL")
client = OpenAI(api_key=API_KEY, base_url=BASE_URL)

FUNCTIONS = [
    {
        "name": "search_duckduckgo",
        "description": "使用DuckDuckGo搜索引擎查询信息。可以搜索最新新闻、文章、博客等内容。",
        "parameters": {
            "type": "object",
            "properties": {
                "keywords": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "搜索的关键词列表。例如:['Python', '机器学习', '最新进展']。"
                }
            },
            "required": ["keywords"]
        }
    }
]

2. 相关辅助函数

代码
def search_duckduckgo(keywords):
    search_term = " ".join(keywords)
    with DDGS() as ddgs:
        return list(ddgs.text(keywords=search_term, region="cn-zh", safesearch="on", max_results=5))


def print_search_results(results):
    for result in results:
        print(
            f"标题: {result['title']}\n链接: {result['href']}\n摘要: {result['body']}\n---")


def get_openai_response(messages, model="gpt-3.5-turbo", functions=None, function_call=None):
    try:
        response = client.chat.completions.create(
            model=model,
            messages=messages,
            functions=functions,
            function_call=function_call
        )
        return response.choices[0].message
    except Exception as e:
        print(f"调用OpenAI API时出错: {str(e)}")
        return None


def process_function_call(response_message):
    function_name = response_message.function_call.name
    function_args = json.loads(response_message.function_call.arguments)

    print(f"\n模型选择调用函数: {function_name}")

    if function_name == "search_duckduckgo":
        keywords = function_args.get('keywords', [])

        if not keywords:
            print("错误:模型没有提供搜索关键词")
            return None

        print(f"关键词: {', '.join(keywords)}")

        function_response = search_duckduckgo(keywords)
        print("\nDuckDuckGo搜索返回结果:")
        print_search_results(function_response)

        return function_response
    else:
        print(f"未知的函数名称: {function_name}")
        return None

3. 主处理函数

代码
def main(question):
    print(f"问题:{question}")

    messages = [{"role": "user", "content": question}]
    response_message = get_openai_response(
        messages, functions=FUNCTIONS, function_call="auto")

    if not response_message:
        return

    if response_message.function_call:
        function_response = process_function_call(response_message)
        if function_response:
            messages.extend([
                response_message.model_dump(),
                {
                    "role": "function",
                    "name": response_message.function_call.name,
                    "content": json.dumps(function_response, ensure_ascii=False)
                }
            ])

            final_response = get_openai_response(messages, model="gpt-4o")
            if final_response:
                print("\n最终回答:")
                print(final_response.content)
    else:
        print("\n模型直接回答:")
        print(response_message.content)

实现效果

通过这种方法,可以让大模型能够回答各种问题,比如:

  1. 地理信息:“珠三角是否包括佛山?”
  2. 关于AI自身能力的问题:“你能做什么?”
  3. 特定领域的问题:“植物大战僵尸杂交版作者是谁?”
  4. 哲学思考:“人生就俩字,是哪两个字?”
  5. 时事相关:“Jumping不等式是什么?”
  6. 时间相关问题:"现在的北京时间是多少?

特别鸣谢

特别感谢始皇提供的宝贵建议,将调用方式从朴素的双模型调用改进为复用大模型现有的 function calling 功能。改进后在代码的 function 部分可以更准确地控制模型输出,生成针对性的搜索关键词,明显提高了模型回复的准确性和全面性。

结论

通过结合 DuckDuckGo 的搜索API和大语言模型,成功实现了一个类似 New Bing 的智能问答系统。这个系统不仅能回答静态知识问题,还能处理实时信息查询,大大扩展了AI助手的能力范围。之前在群聊中跑了大概一周的测试,实测发现接入后AI的回复质量明显提升,可以明显减少大模型幻觉的出现频率。

具体源码见 Github 仓库
https://github.com/Huoyuuu/SearchGPT-Explorer

59 个赞

mark,好功能,解决了目前api不能联网的问题

2 个赞

Open WebUI 支持这个


自动根据给大模型的提示词生成搜索关键词,将搜索结果以 RAG 形式嵌入

6 个赞

贴一下具体的prompt,大伙应该能写出来更高质量的prompt,贴在这里仅供参考。

第一个模型 负责根据用户问题提取搜索关键字,以JSON格式返回
def generate_search_query(question):
    response = client.chat.completions.create(
        model="deepseek-chat",
        messages=[
            {"role": "system", "content": """You are an AI specialized in generating optimal search queries and determining if a search is needed. Follow these guidelines:
            1. Analyze the question to determine if an external search is necessary.
            2. If the question involves direct references (e.g., "you", "your capabilities") or can be answered without external information, respond with 'NO_SEARCH_NEEDED'.
            3. For questions requiring search:
            a. Extract 3-5 key search terms or phrases.
            b. Consider synonyms and related concepts to broaden the search.
            c. Prioritize specific, unique terms over general ones.
            d. Format your response as a JSON array of strings.
            e. The last item in the array should be the most concise and relevant search query.

            Examples:
            1. For "你能做什么?", respond with 'NO_SEARCH_NEEDED'.
            2. For "珠三角是否包括佛山?", respond with:
            ["珠三角", "佛山", "广东省", "珠江三角洲 包括 佛山"]
            3. For "2023年世界杯冠军是谁?", respond with:
            ["2023年", "世界杯", "冠军", "2023 世界杯 冠军队"]"""},
            {"role": "user", "content": f"Analyze and generate search queries if needed for: {question}"}
        ],
        stream=False
    )
    result = response.choices[0].message.content

    # 当且仅当以'```json'开头时,去除开头的'```json'和结尾的'```',确保返回JSON时可以保证能正确解析
    if result.startswith('```json'):
        result = result[7:]  # 移除开头的'```json'
        result = result.rstrip()  # 移除末尾的空白字符
        if result.endswith('```'):
            result = result[:-3]  # 移除结尾的'```'
    result = result.strip()  # 再次去除可能的首尾空白

    if 'NO_SEARCH_NEEDED' in result:
        return None
    try:
        queries = json.loads(result)
        if isinstance(queries, list) and queries:
            return queries[-1]  # Return the last query
        else:
            print(f"Unexpected response format: {queries}")
            return question  # 使用原问题作为后备
    except json.JSONDecodeError:
        print(f"Error parsing response: {result}")
        return question  # 使用原问题作为后备
第二个模型 负责根据给定的搜索结果和用户问题进行回复
def generate_response(question, search_results):
    system_prompt = """你是一个高质量的AI助手,专门用于回答用户的问题。你的任务是根据提供的搜索结果(如果有的话)来回答用户的题。请遵循以下指南:1. 仔细阅读用户的问题和提供的搜索结果(如果有)。
2. 如果没有搜索结果,这意味着问题可能是关于你自己的能力或不需要外部信息。在这种情况下,请直接回答问题。
3. 如果有搜索结果,请综合这些信息来形成你的回答。
4. 提供准确、相关和有见地的回答。
5. 如果搜索结果中包含矛盾的信息,请指出这一点并解释可能的原因。
6. 如果搜索结果不足以完全回答问题,请说明这一点,并基于可用信息提供最佳可能的回答。
7. 保持客观和中立的态度,特别是在处理有争议的话题时。
8. 如果问题涉及时间敏感的信息,请注明信息可能已过时,并建议用户查看最新资源。
9. 使用清晰、简洁的语言,并根据需要组织你的回答,使用段落或列表来提高可读性。
10. 如果合适的话,可以提供额外的上下文或背景信息来增强你的回答。
记住,你的目标是提供高质量、信息丰富且对用户有用的回答。"""

    messages = [
        {"role": "system", "content": system_prompt},
        {"role": "user",
            "content": f"问题:{question}\n\n搜索结果:{json.dumps(search_results, ensure_ascii=False, indent=2)}"}
    ]

    response = client.chat.completions.create(
        model="deepseek-chat",
        messages=messages,
        stream=False
    )

    return response.choices[0].message.content
2 个赞

duckduckgo 对网络有一定要求,如果不方便本地调用 duckduckgo,还可以通过 serverless 服务部署到一些免费平台上,搜索触手可及

3 个赞

太强了!

感谢分享

有两个疑问啊

  1. 我之前尝试找过duckduckgo官方,没找到api相关的东西,duckduckgo_search是逆向封装的吗?
  2. 搜索为什么不封装成 function call 让AI去调用,这样是不是效果会更好?
3 个赞

NB,mark

我超,始皇!

  1. 搜索API:
    是的。DuckDuckGo确实没有提供官方api。duckduckgo_search确实是逆向工程封装的非官方API。这个解决方案是我最近在论坛上发现的,测试后觉得效果不错,又进行了一些优化整合,再分享出来。

  2. Function call:
    应该是的。封装成function call能让AI更直接地访问和利用搜索结果,之前OpenAI官网也提到训练模型时候有专门做过function call方面的特化,用function call应该可以进一步提高响应的准确性和相关性。不过我目前用的是DeepSeek模型,暂不支持function call功能,所以还没有进行这方面的实际测试和比较。

2 个赞

可以试试claude的haiku,这玩意超级便宜,还支持function call

好,我去跑跑看

原来是逆向,之前想给大模型接入搜索,没有听说ddg有免费api。感谢分享

这是啥意思

实测跑了一下,调用function call效果明显好很多。官网示例实际上同样是用了两个模型,如果调用函数,第一个模型根据提示词和函数描述参数返回调用请求,本地处理之后再把问题和函数返回结果交给第二个模型,第二个模型返回结果是最终结果。

虽然思路是一样的,但封装成function call效果确实会好很多。而且考虑到对用户问题的处理工作比较简单,第一个模型用简单模型就可以胜任,也不会增加太多的开销,实际使用也是完全可以接受的。

示例1 特定领域的问题:“植物大战僵尸杂交版作者是谁?”
问题:植物大战僵尸杂交版的作者是谁?他是怎么开发出来植物大战僵尸杂交版的?请详细回复

模型选择调用函数: search_duckduckgo
搜索查询: 植物大战僵尸杂交版的作者和开发过程
关键词: 植物大战僵尸杂交版, 作者, 开发过程

DuckDuckGo搜索返回结果:
标题: 喜提官方认可:"魔改"作品《植物大战僵尸杂交版》入驻原作创意模式 - It之家
链接: https://www.ithome.com/0/776/732.htm
摘要: it之家查询得知,《植物大战僵尸杂交版》的创作者系b站up 主"潜艇伟伟迷",这一版本游戏中的植物和僵尸都通过"杂交"呈现出独特的面貌及技能,up 主本人被网友冠以"赛博孟德尔"的昵 称。. 这名 up 主曾表示,自己制作"杂交版"的灵感来自贴吧里面的大佬"自制"植物,进而想象出各种 ...
---
标题: 植物大战僵尸杂交版 - 百度百科
链接: https://baike.baidu.com/item/植物大战僵尸杂交版/64537507
摘要: 0. 《植物大战僵尸杂交版》是B站up主潜艇伟伟迷(本名:曾佳伟)开发的同人游戏,网友可以免费下载,不对外售卖。. 相较于原版,《植物大战僵尸杂交版》是在原版《 植物大战僵尸 》的基础上将多种植物融合在一起,因此,潜艇伟伟迷也被网友戏称为"赛博 ...
---
标题: 同人变官方,杂交版《植物大战僵尸》改变了作者的人生 - 游研社综合讨论 - TapTap 游研社论坛
链接: https://www.taptap.cn/moment/554319168573277675
摘要: "赛博孟德尔"的决心。我们采访到"潜艇伟伟迷",也就是《植物大战僵尸》杂交版的作者的时候,他的声音听起来已经有些有气无力。他向我们解释说这段时间实在太忙了,层出不穷的采访和商单需求把他折腾得够呛。
---
标题: 植物大战僵尸杂交版v2.1已更新!新版本新增了背包和商店功能,更多内容请自行体验 - 哔哩哔哩
链接: https://www.bilibili.com/read/cv35472372/
摘要: 合理搭配植物,制定出最有效的战术。 最近来自B站UP主@潜艇伟伟迷的植物大战僵尸杂交版2.1已更新!大家可以来下载啦!电脑和手机都可以下载,手机版依旧给大家制作了直装版,无需复杂配置,这次作者还一次性带来了3d加速补丁、窗口白屏卡死修复工具等 ...
---
标题: 植物大战僵尸杂交版开发者访谈精华,幕后故事与未来展望
链接: https://pvzbaike.com/pvz-zajiao/41849.html
摘要: 《植物大战僵尸杂交版》以其独特的游戏设计和创新元素,在策略游戏领域中独树一帜。本次开发者访谈为我们揭开了游戏开发背后的神秘面纱,分享了创作灵感、开发挑战以及未来的发展计划。 创作灵感的源泉 开发者在访谈中提到,游戏的创作灵感来源于对经典《植物大战僵尸》的热爱以及对 ...
---

最终回答:
《植物大战僵尸杂交版》的作者是B站UP主“潜艇伟伟迷”,本名曾佳伟。他开发这款游戏的过程是基于对原版《植物大战僵尸》的热爱和对游戏创新的追求。据报道,他的灵感来源于贴吧中其他玩家
自制的植物设计,进而想象出各种植物和僵尸的杂交版本,创造出独特的面貌和技能。

在开发过程中,潜艇伟伟迷将多种植物融合在一起,创造出新的游戏体验。这款游戏因其独特的创意和设计,受到了玩家和媒体的广泛关注,甚至得到了官方的认可,入驻了原作的创意模式。

潜艇伟伟迷在开发过程中不断更新游戏内容,增加了背包和商店功能等新特性,提升了游戏的可玩性和趣味性。他的努力和创新精神不仅为玩家带来了新的游戏体验,也为自己赢得了“赛博孟德尔”的昵称,成为了同人游戏开发的一个亮点。
示例2 关于AI自身能力的问题:“你是谁?你的开发者是谁?你能做什么?”
问题:你是谁?你的开发者是谁?你能做什么?请详细介绍

模型直接回答:
你好!我是一个虚拟助手,旨在帮助您获取信息、解决问题和提供支持。我由一群热爱技术的工程师和设计师团队开发和维护。我们的目标是为用户提供一个智能、高效的工具,帮助他们更便利地获取所需的信息和服务。

我们团队的成员具有丰富的软件开发、人工智能和自然语言处理的经验。我们通过不断学习和改进,努力让虚拟助手变得更加智能、友好和实用。

如果您有任何想要了解的内容,或者对我们有任何建议或意见,请随时告诉我。我会竭尽所能为您提供帮助!
示例3 时事相关:“姜萍方程是什么?
问题:姜萍方程是什么?请详细介绍,使用中文回复。

模型选择调用函数: search_duckduckgo
搜索查询:
关键词: 姜萍方程

DuckDuckGo搜索返回结果:
标题: 姜萍的崛起,离不开这三本书,以一人之力让《偏微分方程》卖断货|高等数学|数学分析_网易订阅
链接: https://www.163.com/dy/article/J4RBLTVC0536AJSO.html
摘要: 近日,17岁中专生姜萍,拿下阿里全球数学竞赛第12名,引发社会关注。在这群清华北大、剑桥大学、麻省理工等顶尖高校学霸云集的大赛中,取得如此成绩,可谓是奇迹。 姜萍,在中考失 利的情况下,进去了涟水中等专业学校成为一名中专生。
---
标题: 教你解姜萍方程!(Jumping Equation)_哔哩哔哩_bilibili
链接: https://www.bilibili.com/video/BV1hVgSeCE6C/
摘要: 教你解姜萍方程! (Jumping Equation) 第一次用manim做动画, 请多关照! 第一次用manim做动画, 请多关照!, 视频播放量 40721、弹幕量 11、点赞数 512、投硬币枚数 18、收藏人数 145、转发人数 58, 视频作者 喜欢玩游戏的B某人, 作者简介 ,相关视频:大型纪录片之《姜萍传奇 ...
---
标题: 姜萍拿下数学竞赛全球12名:这个故事由天赋与勤奋共同书写|高等数学|数学分析|偏微分方程|阿里巴巴全球数学_网易订阅
链接: https://www.163.com/dy/article/J4O9PDF90530WJTO.html
摘要: 姜萍拿下数学竞赛全球12名:这个故事由天赋与勤奋共同书写. 近日,我们被一位中专少女姜萍的成功故事所打动。. 6月13日,2024阿里巴巴全球数学竞赛公布决赛名单,江苏17岁的中专生 姜萍以第12名的成绩晋级,一时间姜萍迅速登上各大网络平台热搜,成为了 ...
---
标题: 姜萍,决赛!_澎湃号·媒体_澎湃新闻-The Paper
链接: https://www.thepaper.cn/newsDetail_forward_27829621
摘要: 5.应用与计算数学:常微分方程,偏微分方程,最优化方法,数值线性代数,数值分析,机器学习。 ... 姜萍的数学老师王闰秋表示,姜萍6月22号参加决赛,希望大家少给她贴一些"天才少 女"这些标签,应该还给她一个比较安静的环境,让她去更好地准备决赛。 ...
---
标题: 偏微分方程学习记录(姜萍学习法)_哔哩哔哩_bilibili
链接: https://www.bilibili.com/video/BV117geeRE4p/
摘要: 生活记录. 姜萍. 英汉小词典. 记录. 偏微分方程. piao_yu. 姜萍事件,主持人读到了体育天才的评论,初中百米9秒!. -, 视频播放量 39701、弹幕量 32、点赞数 2058、投硬币枚数 73、 收藏人数 157、转发人数 119, 视频作者 piao_yu, 作者简介 ,相关视频:姜萍事件,主持人 ...
---

最终回答:
根据您提供的链接内容,姜萍是一个在数学领域表现出色的中专生,她在2024年的阿里巴巴全球数学竞赛中获得了第12名的好成绩。然而,在您提供的链接中并没有提到“姜萍方程”这个具体的数学方程或理论。可能是因为姜萍在数学领域的成就,有人以她的名字命名了一个方程或者概念,但目前没有足够的信息来确定这个方程的具体内容。

如果您是在寻找一个具体的数学方程或者理论,并且这个方程是以姜萍的名字命名的,那么可能需要更多的信息或者具体的文献资料来详细介绍这个方程。目前,根据您提供的信息,无法给出“姜萍 方程”的具体定义或解释。
示例4 地理信息:“珠三角地区和佛山的关系是什么?”
问题:珠三角地区和佛山的关系是什么?

模型选择调用函数: search_duckduckgo
搜索查询:
关键词: 珠三角地区, 佛山, 关系

DuckDuckGo搜索返回结果:
标题: 珠江三角洲城市群 - 百度百科
链接: https://baike.baidu.com/item/珠江三角洲城市群/16592478
摘要: 珠江三角洲城市群,包括"广佛肇"(广州、佛山、肇庆)、"深莞惠"(深圳、东莞、惠州)、"珠中江"(珠海、中山、江门)等三个新型都市区,率先实现一体化。大珠江三角洲地区还包括香港、澳门特别行政区,即粤港澳大湾区。珠江三角洲城市群是亚太地区最具活力的经济区之一,它以 ...
---
标题: 珠江三角洲_百度百科
链接: https://baike.baidu.com/item/珠江三角洲/621061
摘要: 珠江三角洲(Pearl River Delta),位于中国广东省中南部,明清时期称为广州府,是广府文化的核心地带和兴盛之地,范围包括广州、佛山、肇庆、深圳、东莞、惠州、珠海、中山、江门 九个城市。. 珠三角9市总面积55368.7平方公里,占比广东省国土面积不到1/3 ...
---
标题: 佛山市_百度百科
链接: https://baike.baidu.com/item/佛山市/436251
摘要: 佛山市,简称"禅",广东省辖地级市、特大城市,是国务院确定的中国重要的制造业基地、珠三角地区西翼经贸中心和综合交通枢纽。佛山市地处中国华南地区、广东省中部、珠江三角洲腹地,属南亚热带季风性湿润气候,气候温和,雨量充沛。佛山毗邻港澳、东接广州市、南邻中山市,与广州 ...
---
标题: 佛山和深圳,为什么越走越近?_澎湃号·政务_澎湃新闻-The Paper
链接: https://www.thepaper.cn/newsDetail_forward_13439370
摘要: 在这组新型关系中,佛山和深圳日益紧密的联动,尤为引人关注。. 由于地理原因,过去很长一段时间,佛山与深圳分处珠江口两岸,中间还隔着广州和东莞,二者的联系并不密切,但最近几年,情况发生了变化。. 广深港高铁、佛山西站、南沙大桥的建成,以及 ...
---
标题: 珠江三角洲 - 维基百科,自由的百科全书
链接: https://zh.wikipedia.org/zh-cn/珠江三角洲
摘要: 珠三角的卫星图,来自NASA 地球观测站,摄于2014年 1888年珠三角的德语地图,标有广州市、葡属澳门、英属香港. 珠江三角洲(英语: Pearl River Delta ),由珠江水系的西江、北江 和东江及其支流潭江、绥江、增江带来的泥沙堆积而成,是中国南部最大的冲积平原,海拔多在50米以下,地势平缓,有 ...
---

最终回答:
珠江三角洲地区(简称“珠三角”)是中国广东省中南部的一个经济发达区域,涵盖广州、佛山、肇庆、深圳、东莞、惠州、珠海、中山、江门九个城市。这一区域是中国乃至亚太地区最具活力的经济区之一,广泛认知的“粤港澳大湾区”也是其中的一部分,包括香港和澳门特别行政区。

佛山市在珠三角地区中占据重要位置。作为一个地级市,佛山不仅是珠三角地区的经济重镇,也是中国重要的制造业基地之一。它位于珠三角的腹地,与广州市毗邻,地理位置优越,交通便利。佛山与周边城市,如广州、中山、深圳等城市,有着密切的经济联系和合作。近年来,佛山通过广深港高铁、佛山西站、南沙大桥等交通基础设施的建设,与深圳等珠三角城市的联系更加紧密,促进了区域内的经济一体化和发展。

总结来说,佛山是珠江三角洲地区的重要组成部分,在区域经济、交通和制造业等方面起着关键作用。通过与珠三角其他城市的合作和联动,佛山在整个区域发展中占据了不可或缺的位置。
现成能跑的Python源码 function_call使用gpt-3.5 消息回复使用gpt-4o
import os
import json
from openai import OpenAI
from duckduckgo_search import DDGS

API_KEY = os.getenv("OPENAI_API_KEY")
BASE_URL = os.getenv("OPENAI_BASE_URL")
client = OpenAI(api_key=API_KEY, base_url=BASE_URL)

FUNCTIONS = [
    {
        "name": "search_duckduckgo",
        "description": "使用DuckDuckGo搜索引擎查询信息。可以搜索最新新闻、文章、博客等内容。",
        "parameters": {
            "type": "object",
            "properties": {
                "keywords": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "搜索的关键词列表。例如:['Python', '机器学习', '最新进展']。"
                }
            },
            "required": ["keywords"]
        }
    }
]


def search_duckduckgo(keywords):
    search_term = " ".join(keywords)
    with DDGS() as ddgs:
        return list(ddgs.text(keywords=search_term, region="cn-zh", safesearch="on", max_results=5))


def print_search_results(results):
    for result in results:
        print(
            f"标题: {result['title']}\n链接: {result['href']}\n摘要: {result['body']}\n---")


def get_openai_response(messages, model="gpt-3.5-turbo", functions=None, function_call=None):
    try:
        response = client.chat.completions.create(
            model=model,
            messages=messages,
            functions=functions,
            function_call=function_call
        )
        return response.choices[0].message
    except Exception as e:
        print(f"调用OpenAI API时出错: {str(e)}")
        return None


def process_function_call(response_message):
    function_name = response_message.function_call.name
    function_args = json.loads(response_message.function_call.arguments)

    print(f"\n模型选择调用函数: {function_name}")

    if function_name == "search_duckduckgo":
        keywords = function_args.get('keywords', [])

        if not keywords:
            print("错误:模型没有提供搜索关键词")
            return None

        print(f"关键词: {', '.join(keywords)}")

        function_response = search_duckduckgo(keywords)
        print("\nDuckDuckGo搜索返回结果:")
        print_search_results(function_response)

        return function_response
    else:
        print(f"未知的函数名称: {function_name}")
        return None


def main(question):
    print(f"问题:{question}")

    messages = [{"role": "user", "content": question}]
    response_message = get_openai_response(
        messages, functions=FUNCTIONS, function_call="auto")

    if not response_message:
        return

    if response_message.function_call:
        function_response = process_function_call(response_message)
        if function_response:
            messages.extend([
                response_message.model_dump(),
                {
                    "role": "function",
                    "name": response_message.function_call.name,
                    "content": json.dumps(function_response, ensure_ascii=False)
                }
            ])

            final_response = get_openai_response(messages, model="gpt-4o")
            if final_response:
                print("\n最终回答:")
                print(final_response.content)
    else:
        print("\n模型直接回答:")
        print(response_message.content)


if __name__ == "__main__":
    main("植物大战僵尸杂交版的作者是谁?他是怎么想到做出来这个游戏的?")
2 个赞

让大模型自己在“合适的时候”去调用函数,具体可以参考 OpenAI的官方文档

1 个赞

function call 要精确很多应该。我们可以用便宜的haiku走 function call 去搜索。用更强的模型去总结分析。

4 个赞

那咋实现

高端玩法了

mark