agentApi.ts 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. import type { FunctionDefinition } from "../types/chat"
  2. import {
  3. SearchByQueryArgs,
  4. SearchByPageRefArgs,
  5. GetTermDefinitionArgs,
  6. SearchPaliArgs,
  7. SearchResponse,
  8. } from "../types/search"; // 假设你的类型定义文件名为 apiTypes.ts
  9. /**
  10. * 基础 API URL
  11. * 请替换为你的实际后端 API 地址
  12. */
  13. const API_BASE_URL = "http://localhost:8000/api/v3";
  14. export const system_prompt = `
  15. 你是一个专业的、精通巴利语和汉语的佛教文献检索助手。你的任务是分析用户的查询,并利用你拥有的工具(函数)来获取信息。
  16. 严格遵守以下原则:
  17. 1. 优先并恰当地使用提供的工具来满足用户的查询需求。
  18. 2. 你的回答必须简洁、直接,仅包含从工具中获得的信息,不添加任何额外闲聊。
  19. 3. 如果一个查询无法被任何工具处理,或者需要与用户进行澄清,请清晰地说明。
  20. 4. 当用户的查询包含**页码标记**(例如:M3.58, V3.81)时,必须使用 search_by_page_ref 函数。
  21. 5. 当用户的查询是**明确的佛教术语或词汇**(例如:四圣谛, mettā)时,必须使用 search_pali 和 get_term_definition 函数 进行两次搜索,获取巴利文原文和术语字典结果。
  22. 6. 当用户的查询是**描述性、自然语言问题**(例如:佛陀关于慈悲的教导)时,必须使用 search_by_query 函数。
  23. 7. 当用户的查询是**普通关键词**(例如:比丘, 袈裟)时,使用 search_by_query 函数。
  24. 以下是你的工具箱:
  25. - search_by_query: 用于通用的模糊和语义搜索。
  26. - search_by_page_ref: 专门用于处理页码搜索。
  27. - get_term_definition: 专门用于获取术语定义。
  28. - search_pali: 专门用于处理巴利文搜索。
  29. 请严格根据上述原则,选择最恰当的工具来处理用户的请求。
  30. 如果用户追问的问题可以使用之前的数据回答,那么无需再次调用工具。
  31. `;
  32. export type AICallbackFunction = {
  33. name:
  34. | "search_by_query"
  35. | "search_by_page_ref"
  36. | "get_term_definition"
  37. | "search_pali";
  38. arguments:
  39. | SearchByQueryArgs
  40. | SearchByPageRefArgs
  41. | GetTermDefinitionArgs
  42. | SearchPaliArgs;
  43. };
  44. // ---------------------------------------------------------------- //
  45. // 低层 API 客户端(使用 fetch) //
  46. // ---------------------------------------------------------------- //
  47. const apiClient = async <T>(
  48. endpoint: string,
  49. params: Record<string, any>
  50. ): Promise<T> => {
  51. const searchParams = new URLSearchParams();
  52. for (const key in params) {
  53. if (params[key] !== undefined && params[key] !== null) {
  54. if (Array.isArray(params[key])) {
  55. searchParams.append(key, params[key].join(","));
  56. } else {
  57. searchParams.append(key, String(params[key]));
  58. }
  59. }
  60. }
  61. const url = `${API_BASE_URL}${endpoint}?${searchParams.toString()}`;
  62. try {
  63. const response = await fetch(url);
  64. if (!response.ok) {
  65. throw new Error(`HTTP error! Status: ${response.status}`);
  66. }
  67. const data: SearchResponse = await response.json();
  68. if (data.success) {
  69. return data.data as T;
  70. } else {
  71. throw new Error("API request was not successful.");
  72. }
  73. } catch (error) {
  74. console.error("API call failed:", error);
  75. throw new Error("An unexpected error occurred.");
  76. }
  77. };
  78. // ---------------------------------------------------------------- //
  79. // 封装的搜索函数(每个函数对应一个意图) //
  80. // ---------------------------------------------------------------- //
  81. /**
  82. * 通用搜索函数,处理模糊和语义查询。
  83. */
  84. export const searchByQuery = async (
  85. args: SearchByQueryArgs
  86. ): Promise<SearchResponse> => {
  87. return apiClient<SearchResponse>("/search", {
  88. q: args.query,
  89. });
  90. };
  91. /**
  92. * 专门处理页码搜索的函数。
  93. */
  94. export const searchByPageRef = async (
  95. args: SearchByPageRefArgs
  96. ): Promise<SearchResponse> => {
  97. return apiClient<SearchResponse>("/search", {
  98. q: args.page_refs, // query参数使用页码
  99. search_mode: "page_search", // 固定搜索模式为页码搜索
  100. page_refs: args.page_refs,
  101. });
  102. };
  103. /**
  104. * 专门用于获取术语定义的函数。
  105. */
  106. export const getTermDefinition = async (
  107. args: GetTermDefinitionArgs
  108. ): Promise<SearchResponse> => {
  109. return apiClient<SearchResponse>("/search", {
  110. q: args.term,
  111. resource_type: "term",
  112. });
  113. };
  114. /**
  115. * 专门用于巴利文精确搜索的函数。
  116. */
  117. export const searchPali = async (
  118. args: SearchPaliArgs
  119. ): Promise<SearchResponse> => {
  120. return apiClient<SearchResponse>("/search", {
  121. q: args.query,
  122. resource_type: "original_text", // 仅搜索原文
  123. language: "pali", // 仅搜索巴利文
  124. });
  125. };
  126. // ---------------------------------------------------------------- //
  127. // 核心 Function Calling 处理函数 //
  128. // ---------------------------------------------------------------- //
  129. /**
  130. * 核心函数:根据 AI 助手返回的函数调用对象,执行相应的操作。
  131. *
  132. * @param functionCall AI 助手返回的函数调用对象。
  133. * @returns 返回一个 Promise,包含搜索结果。
  134. */
  135. export const handleFunctionCall = async (
  136. functionCall: AICallbackFunction
  137. ): Promise<SearchResponse> => {
  138. switch (functionCall.name) {
  139. case "search_by_query":
  140. return searchByQuery(functionCall.arguments as SearchByQueryArgs);
  141. case "search_by_page_ref":
  142. return searchByPageRef(functionCall.arguments as SearchByPageRefArgs);
  143. case "get_term_definition":
  144. return getTermDefinition(functionCall.arguments as GetTermDefinitionArgs);
  145. case "search_pali":
  146. return searchPali(functionCall.arguments as SearchPaliArgs);
  147. default:
  148. throw new Error(`Unknown function call: ${functionCall.name}`);
  149. }
  150. };
  151. export const tools: FunctionDefinition[] = [
  152. {
  153. type: "function",
  154. function: {
  155. name: "search_by_query",
  156. description: "通用搜索函数,支持模糊与语义查询。",
  157. parameters: {
  158. type: "object",
  159. properties: {
  160. query: {
  161. type: "string",
  162. description: "用户输入的查询语句(如: 佛陀关于慈悲的教导)",
  163. },
  164. search_mode: {
  165. type: "string",
  166. enum: ["fuzzy", "semantic"],
  167. description: "搜索模式: fuzzy=模糊, semantic=语义",
  168. },
  169. },
  170. required: ["query", "search_mode"],
  171. additionalProperties: false,
  172. },
  173. },
  174. strict: true,
  175. },
  176. {
  177. type: "function",
  178. function: {
  179. name: "search_by_page_ref",
  180. description: "根据页码标记(如 M3.58, V3.81)搜索对应内容。",
  181. parameters: {
  182. type: "object",
  183. properties: {
  184. page_refs: {
  185. type: "string",
  186. description: "经文页码标记(如 M3.58)",
  187. },
  188. },
  189. required: ["page_refs"],
  190. additionalProperties: false,
  191. },
  192. },
  193. strict: true,
  194. },
  195. {
  196. type: "function",
  197. function: {
  198. name: "get_term_definition",
  199. description: "获取佛教术语的精确定义,主要从字典资源。",
  200. parameters: {
  201. type: "object",
  202. properties: {
  203. term: {
  204. type: "string",
  205. description: "佛教术语(如: 四圣谛, 五蕴, 涅槃)",
  206. },
  207. },
  208. required: ["term"],
  209. additionalProperties: false,
  210. },
  211. },
  212. strict: true,
  213. },
  214. {
  215. type: "function",
  216. function: {
  217. name: "search_pali",
  218. description:
  219. "在巴利文语料中进行关键词搜索,被搜索词可以是巴利文或者其他语言。",
  220. parameters: {
  221. type: "object",
  222. properties: {
  223. query: {
  224. type: "string",
  225. description:
  226. "被搜索词,巴利文词汇或短语(如: mettā, anicca)或者其他语言的佛教专有名词",
  227. },
  228. },
  229. required: ["query"],
  230. additionalProperties: false,
  231. },
  232. },
  233. strict: true,
  234. },
  235. ];
  236. // ---------------------------------------------------------------- //
  237. // 使用示例 //
  238. // ---------------------------------------------------------------- //
  239. /**
  240. *
  241. *
  242. const main = async () => {
  243. // 模拟从 AI 助手获得的函数调用对象
  244. const mockCalls: AICallbackFunction[] = [
  245. {
  246. name: "search_by_query",
  247. arguments: { query: "佛陀关于慈悲的教导", search_mode: "semantic" },
  248. },
  249. { name: "search_by_page_ref", arguments: { page_refs: "M3.58" } },
  250. { name: "get_term_definition", arguments: { term: "四圣谛" } },
  251. { name: "search_pali", arguments: { query: "mettā" } },
  252. ];
  253. for (const call of mockCalls) {
  254. try {
  255. console.log(`\n正在处理函数调用:${call.name}`);
  256. const result = await handleFunctionCall(call);
  257. console.log("搜索成功,找到结果数量:", result.data.hits.total.value);
  258. // 根据你的需求,你可以在这里处理并展示结果
  259. } catch (error) {
  260. console.error(`处理函数调用失败:${call.name}`, error);
  261. }
  262. }
  263. };
  264. */