吳恩達MCP課程(1):chat_bot

原課程代碼是用Anthropic寫的,下面代碼是用OpenAI改寫的,模型則用阿里巴巴的模型做測試
.env 文件為:

OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
OPENAI_API_BASE=https://dashscope.aliyuncs.com/compatible-mode/v1

完整代碼

import arxiv
import json
import os
from typing import List
from dotenv import load_dotenv
import openaiPAPER_DIR = "papers"def search_papers(topic: str, max_results: int = 5) -> List[str]:"""Search for papers on arXiv based on a topic and store their information.Args:topic: The topic to search formax_results: Maximum number of results to retrieve (default: 5)Returns:List of paper IDs found in the search"""# Use arxiv to find the papersclient = arxiv.Client()# Search for the most relevant articles matching the queried topicsearch = arxiv.Search(query = topic,max_results = max_results,sort_by = arxiv.SortCriterion.Relevance)papers = client.results(search)# Create directory for this topicpath = os.path.join(PAPER_DIR, topic.lower().replace(" ", "_"))os.makedirs(path, exist_ok=True)file_path = os.path.join(path, "papers_info.json")# Try to load existing papers infotry:with open(file_path, "r") as json_file:papers_info = json.load(json_file)except (FileNotFoundError, json.JSONDecodeError):papers_info = {}# Process each paper and add to papers_infopaper_ids = []for paper in papers:paper_ids.append(paper.get_short_id())paper_info = {'title': paper.title,'authors': [author.name for author in paper.authors],'summary': paper.summary,'pdf_url': paper.pdf_url,'published': str(paper.published.date())}papers_info[paper.get_short_id()] = paper_info# Save updated papers_info to json filewith open(file_path, "w") as json_file:json.dump(papers_info, json_file, indent=2)print(f"Results are saved in: {file_path}")return paper_idsdef extract_info(paper_id: str) -> str:"""Search for information about a specific paper across all topic directories.Args:paper_id: The ID of the paper to look forReturns:JSON string with paper information if found, error message if not found"""for item in os.listdir(PAPER_DIR):item_path = os.path.join(PAPER_DIR, item)if os.path.isdir(item_path):file_path = os.path.join(item_path, "papers_info.json")if os.path.isfile(file_path):try:with open(file_path, "r") as json_file:papers_info = json.load(json_file)if paper_id in papers_info:return json.dumps(papers_info[paper_id], indent=2)except (FileNotFoundError, json.JSONDecodeError) as e:print(f"Error reading {file_path}: {str(e)}")continuereturn f"There's no saved information related to paper {paper_id}."tools = [{"type": "function","function": {"name": "search_papers","description": "Search for papers on arXiv based on a topic and store their information","parameters": {"type": "object","properties": {"topic": {"type": "string","description": "The topic to search for"},"max_results": {"type": "integer","description": "Maximum number of results to retrieve","default": 5}},"required": ["topic"]}}},{"type": "function","function": {"name": "extract_info","description": "Search for information about a specific paper across all topic directories","parameters": {"type": "object","properties": {"paper_id": {"type": "string","description": "The ID of the paper to look for"}},"required": ["paper_id"]}}}
]mapping_tool_function = {"search_papers": search_papers,"extract_info": extract_info
}def execute_tool(tool_name, tool_args):result = mapping_tool_function[tool_name](**tool_args)if result is None:result = "The operation completed but didn't return any results."elif isinstance(result, list):result = ', '.join(result)elif isinstance(result, dict):# Convert dictionaries to formatted JSON stringsresult = json.dumps(result, indent=2)else:# For any other type, convert using str()result = str(result)return resultload_dotenv()
client = openai.OpenAI(api_key = os.getenv("OPENAI_API_KEY"),base_url= os.getenv("OPENAI_API_BASE")
) def process_query(query):messages = [{"role": "user", "content": query}]response = client.chat.completions.create(model="qwen-turbo",  # 或其他OpenAI模型max_tokens=2024,tools=tools,messages=messages)process_query = Truewhile process_query:# 獲取助手的回復message = response.choices[0].message# 檢查是否有普通文本內容if message.content:print(message.content)process_query = False# 檢查是否有工具調用elif message.tool_calls:# 添加助手消息到歷史messages.append({"role": "assistant", "content": None,"tool_calls": message.tool_calls})# 處理每個工具調用for tool_call in message.tool_calls:tool_id = tool_call.idtool_name = tool_call.function.nametool_args = json.loads(tool_call.function.arguments)print(f"Calling tool {tool_name} with args {tool_args}")# 執行工具調用result = execute_tool(tool_name, tool_args)# 添加工具結果到消息歷史messages.append({"role": "tool","tool_call_id": tool_id,"content": result})# 獲取下一個回復response = client.chat.completions.create(model="qwen-turbo",  # 或其他OpenAI模型max_tokens=2024,tools=tools,messages=messages)# 如果只有文本回復,則結束處理if response.choices[0].message.content and not response.choices[0].message.tool_calls:print(response.choices[0].message.content)process_query = Falsedef chat_loop():print("Type your queries or 'quit' to exit.")while True:try:query = input("\nQuery: ").strip()if query.lower() == 'quit':breakprocess_query(query)print("\n")except Exception as e:print(f"\nError: {str(e)}")if __name__ == "__main__":chat_loop()

代碼解釋

導入模塊

import arxiv        # 用于訪問arXiv API搜索論文
import json         # 處理JSON數據
import os           # 操作系統功能,如文件路徑處理
from typing import List  # 類型提示
from dotenv import load_dotenv  # 加載環境變量
import openai       # OpenAI API客戶端

核心功能函數

1. search_papers 函數

這個函數用于在arXiv上搜索特定主題的論文并保存信息:

def search_papers(topic: str, max_results: int = 5) -> List[str]:
  • 參數
    • topic: 要搜索的主題
    • max_results: 最大結果數量(默認5個)
  • 返回值:找到的論文ID列表

功能流程

  1. 創建arXiv客戶端
  2. 按相關性搜索主題相關論文
  3. 為該主題創建目錄(如papers/machine_learning
  4. 嘗試加載已有的論文信息(如果存在)
  5. 處理每篇論文,提取標題、作者、摘要等信息
  6. 將論文信息保存到JSON文件中
  7. 返回論文ID列表
2. extract_info 函數

這個函數用于在所有主題目錄中搜索特定論文的信息:

def extract_info(paper_id: str) -> str:
  • 參數paper_id - 要查找的論文ID
  • 返回值:包含論文信息的JSON字符串(如果找到),否則返回錯誤信息

功能流程

  1. 遍歷papers目錄下的所有子目錄
  2. 在每個子目錄中查找papers_info.json文件
  3. 如果找到文件,檢查是否包含指定的論文ID
  4. 如果找到論文信息,返回格式化的JSON字符串
  5. 如果未找到,返回未找到的提示信息

工具定義

tools = [...]

定義了兩個函數工具,用于OpenAI API的工具調用:

  1. search_papers - 搜索論文
  2. extract_info - 提取論文信息

每個工具都定義了名稱、描述和參數規范。

工具執行函數

def execute_tool(tool_name, tool_args):

這個函數負責執行指定的工具函數,并處理返回結果:

  • 將None結果轉換為提示信息
  • 將列表結果轉換為逗號分隔的字符串
  • 將字典結果轉換為格式化的JSON字符串
  • 其他類型轉換為字符串

OpenAI客戶端初始化

load_dotenv()
client = openai.OpenAI(api_key = os.getenv("OPENAI_API_KEY"),base_url= os.getenv("OPENAI_API_BASE")
)

從環境變量加載API密鑰和基礎URL,初始化OpenAI客戶端。

查詢處理函數

def process_query(query):

這個函數處理用戶的查詢:

  1. 創建包含用戶查詢的消息列表
  2. 調用OpenAI API創建聊天完成
  3. 處理助手的回復:
    • 如果有普通文本內容,直接打印
    • 如果有工具調用,執行工具并將結果添加到消息歷史
  4. 如果執行了工具調用,獲取下一個回復
  5. 如果最終回復只有文本,打印并結束處理

聊天循環函數

def chat_loop():

這個函數實現了一個簡單的聊天循環:

  1. 提示用戶輸入查詢或輸入’quit’退出
  2. 處理用戶的查詢
  3. 捕獲并顯示任何錯誤

主程序

if __name__ == "__main__":chat_loop()

當腳本直接運行時,啟動聊天循環。

總結

這個腳本實現了一個基于OpenAI API的聊天機器人,它可以:

  1. 搜索arXiv上的論文并保存信息
  2. 提取已保存的論文信息
  3. 通過OpenAI API處理用戶查詢
  4. 支持工具調用功能,實現與arXiv的交互

運行示例

目錄結構
在這里插入圖片描述

運行結果
在這里插入圖片描述
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/85270.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85270.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/85270.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Netty 實戰篇:手寫一個輕量級 RPC 框架原型

本文將基于前文實現的編解碼與心跳機制,構建一個簡單的 RPC 框架,包括請求封裝、響應解析、動態代理調用。為打造微服務通信基礎打下基礎。 一、什么是 RPC? RPC(Remote Procedure Call,遠程過程調用)允許…

邊緣計算新基建:iVX 輕量生成模塊的 ARM 架構突圍

一、引言 隨著工業 4.0 和物聯網的快速發展,邊緣計算作為連接云端與終端設備的關鍵技術,正成為推動數字化轉型的核心力量。在邊緣計算場景中,設備的實時性、低功耗和離線處理能力至關重要。ARM 架構憑借其低功耗、高能效的特點,成…

C# 基于 Windows 系統與 Visual Studio 2017 的 Messenger 消息傳遞機制詳解:發布-訂閱模式實現

🧑 博主簡介:CSDN博客專家、CSDN平臺優質創作者,高級開發工程師,數學專業,10年以上C/C, C#, Java等多種編程語言開發經驗,擁有高級工程師證書;擅長C/C、C#等開發語言,熟悉Java常用開…

js數據類型有哪些?它們有什么區別?

js數據類型共有8種,分別是undefined,null,boolean,number,string,Object,symbol,bigint symbol和bigint是es6中提出來的數據類型 symbol創建后獨一無二不可變的數據類型,它主要是為了解決出現全局變量沖突的問題 bigint 是一種數字類型的數據,它可以表示任意精度格式的整數,…

Vite打包優化實踐:從分包到性能提升

前言: ??????? 隨著前端應用功能的增加,項目的打包體積也會不斷膨脹,影響加載速度和用戶體驗。本文介紹了幾種常見的打包優化策略,通過Vite和相關插件,幫助減少項目體積、提升性能,優化加載速度。 rollup-plugi…

C++語法系列之模板進階

前言 本次會介紹一下非類型模板參數、模板的特化(特例化)和模板的可變參數&#xff0c;不是最開始學的模板 一、非類型模板參數 字面意思,比如&#xff1a; template<size_t N 10> 或者 template<class T,size_t N 10>比如&#xff1a;靜態棧就可以用到&#…

html5的響應式布局的方法示例詳解

以下是HTML5實現響應式布局的5種核心方法及代碼示例: 1. 媒體查詢(核心方案) /* 默認樣式(移動優先) */ .container {padding: 15px; }/* 中等屏幕(平板) */ @media (min-width: 768px) {.container {padding: 30px;max-width: 720px;} }/* 大屏幕(桌面) */ @media …

數字化轉型進階:精讀41頁華為數字化轉型實踐【附全文閱讀】

該文檔聚焦華為數字化轉型實踐&#xff0c;核心內容如下&#xff1a; 轉型本質與目標&#xff1a;數字化轉型是通過數字技術穿透業務&#xff0c;實現物理世界與數字世界的融合&#xff0c;目標是支撐主業成功、提升體驗與效率、探索模式創新。華為以 “平臺 服務” 為核心&am…

C++ - STL #什么是STL #STL的版本 #閉源開源 #STL的六大組件

文章目錄 前言 一、什么是STL 二、STL的版本 1、原始版本 2、P.J.版本 3、RW版本 4、SGI版本 三、閉源、開源 四、STL的六大組件 總結 前言 路漫漫其修遠兮&#xff0c;吾將上下而求索&#xff1b; 一、什么是STL STL(standard template libaray 標準模板庫)&#…

智慧康養護理:科技重塑老齡化社會的健康守護體系

在我國邁入深度老齡化社會的背景下&#xff0c;智慧康養護理作為融合科技與人文的創新模式&#xff0c;正成為提升老年人生活質量、減輕家庭照護壓力、促進健康老齡化的重要路徑。我們將從核心概念、關鍵技術、實際應用與未來趨勢四個維度&#xff0c;為您呈現智慧康養護理的全…

權威認證與質量保障:第三方檢測在科技成果鑒定測試中的核心作用

科技成果鑒定測試是衡量科研成果技術價值與應用潛力的關鍵環節&#xff0c;其核心目標在于通過科學驗證確保成果的可靠性、創新性和市場適配性。第三方檢測機構憑借其獨立性、專業性和權威性&#xff0c;成為科技成果鑒定測試的核心支撐主體。本文從測試流程、第三方檢測的價值…

Linux.docker.k8s基礎概念

1.Linux基本命令 cat 查看文件內容。 cd 進入目標目錄。 ll 查詢當前路勁下文件的詳細信息。 ls 查詢當前路勁下的文件。 touch 建立一個文件。 mkdir 建立一個文件夾。 rm 刪除文件或者目錄。 mv 移動目錄和重新命名文件。 unzip 解壓。 top 查看當前線程的信息。 find …

Python小白的蛻變之旅:從環境搭建到代碼規范(1/10)

摘要&#xff1a;全文圍繞 Python 編程展開&#xff0c;先是介紹如何搭建 Python 開發環境&#xff0c;推薦使用 Anaconda 和 VSCode&#xff0c;并詳細說明了二者的安裝及配置步驟&#xff0c;包括安裝 Anaconda、安裝 VSCode 并配置 Python 插件、選擇 Anaconda 的 Python 解…

linux 1.0.7

用戶和權限的含義與作用 linux中的用戶和文件 用戶的權限是非常重要的 而且有些程序需要使用管理員身份去執行 這些都是非常重要的 不可能讓所有的人擁有所有的權限 這樣的工具可以避免非法的手段來修改計算機中的數據 linux之所以安全還是權限管理做的很棒 每個登錄的用戶都有…

【第4章 圖像與視頻】4.6 結合剪輯區域來繪制圖像

文章目錄 前言示例 前言 本節將綜合運用圖像處理、離屏 canvas 以及剪輯區域等技術實現墨鏡效果。 示例 主線程代碼&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport&qu…

UV 包管理工具:替代 pip 的現代化解決方案

安裝 方法一&#xff1a;使用安裝腳本 # macOS 和 Linux curl -LsSf https://astral.sh/uv/install.sh | sh# Windows PowerShell powershell -c "irm https://astral.sh/uv/install.ps1 | iex" 方法二&#xff1a;使用包管理器 # macOS (Homebrew) brew install uv#…

Java注解規范與使用詳解

注解中的空值限制 在Java注解中,元素值不允許使用null引用。這是注解使用中的一項重要約束規則,違反該規則將導致編譯錯誤。需要注意的是,雖然禁止使用null值,但允許為String類型元素指定空字符串(“”),為數組類型元素指定空數組({})。 空值約束示例 以下兩種注解用法…

從零開始的數據結構教程(八)位運算與狀態壓縮

&#x1f3a9; 標題一&#xff1a;位運算基礎——魔術師的二進制手套 位運算是一種直接操作數字二進制位的運算方式&#xff0c;它高效且巧妙&#xff0c;就像魔術師戴上了二進制手套&#xff0c;能夠精準地操控每一個比特。理解位運算是深入學習狀態壓縮和其他底層優化技巧的…

GraalVM加持下的Quarkus極速啟動

1. 引言 1.1 Quarkus與云原生時代的挑戰 隨著云原生架構的普及,傳統Java應用在部署效率、資源消耗和冷啟動性能方面逐漸暴露出短板。Spring Boot等框架雖然功能強大,但在Serverless、邊緣計算等場景下表現乏力。 Quarkus 是 Red Hat 推出的一個專為云原生設計的 Java/Kotl…

vue3 el-input type=“textarea“ 字體樣式 及高度設置

在Vue 3中&#xff0c;如果你使用的是Element Plus庫中的<el-input>組件作為文本域&#xff08;type"textarea"&#xff09;&#xff0c;你可以通過幾種方式來設置字體樣式和高度。 1. 直接在<el-input>組件上使用style屬性 你可以直接在<el-input&…