google search docs

This commit is contained in:
archer
2023-08-16 18:42:39 +08:00
parent 2c174aa91c
commit 38e4a41cfd
8 changed files with 786 additions and 69 deletions

View File

@@ -52,7 +52,7 @@ export const jsonRes = <T = any>(
} else if (openaiError[error?.response?.statusText]) { } else if (openaiError[error?.response?.statusText]) {
msg = openaiError[error.response.statusText]; msg = openaiError[error.response.statusText];
} }
console.log(error?.response); console.log(error);
} }
res.status(code).json({ res.status(code).json({
@@ -92,7 +92,7 @@ export const sseErrRes = (res: NextApiResponse, error: any) => {
} else if (openaiError[error?.response?.statusText]) { } else if (openaiError[error?.response?.statusText]) {
msg = openaiError[error.response.statusText]; msg = openaiError[error.response.statusText];
} }
console.log('sse error => ', error?.response); console.log('sse error => ', error);
sseResponse({ sseResponse({
res, res,

View File

@@ -1,37 +0,0 @@
import axios from 'axios';
import { Obj2Query } from '../tools';
export const getClientToken = (googleClientVerKey?: string) => {
if (!googleClientVerKey || typeof window.grecaptcha === 'undefined' || !window.grecaptcha?.ready)
return '';
return new Promise<string>((resolve, reject) => {
window.grecaptcha.ready(async () => {
try {
const token = await window.grecaptcha.execute(googleClientVerKey, {
action: 'submit'
});
resolve(token);
} catch (error) {
reject(error);
}
});
});
};
// service run
export const authGoogleToken = async (data: {
secret: string;
response: string;
remoteip?: string;
}) => {
const res = await axios.post<{
score?: number;
success: boolean;
'error-codes': string[];
}>(`https://www.recaptcha.net/recaptcha/api/siteverify?${Obj2Query(data)}`);
if (res.data.success) {
return Promise.resolve('');
}
return Promise.reject(res?.data?.['error-codes']?.[0] || '非法环境');
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 368 KiB

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 KiB

After

Width:  |  Height:  |  Size: 280 KiB

View File

@@ -15,16 +15,20 @@ As shown in the above images, with the help of the HTTP module, you can easily i
```ts ```ts
import cloud from '@lafjs/cloud'; import cloud from '@lafjs/cloud';
const googleSearchKey = ''; const googleSearchKey = '';
const googleCxId = ''; const googleCxId = '';
const baseurl = 'https://www.googleapis.com/customsearch/v1'; const baseurl = 'https://www.googleapis.com/customsearch/v1';
export default async function (ctx: FunctionContext) { export default async function (ctx: FunctionContext) {
const { searchKey } = ctx.body; const { searchKey } = ctx.body;
if (!searchKey) { if (!searchKey) {
return { return {
prompt: '' prompt: ''
}; };
} }
try { try {
const { data } = await cloud.fetch.get(baseurl, { const { data } = await cloud.fetch.get(baseurl, {
params: { params: {
@@ -33,15 +37,12 @@ export default async function (ctx: FunctionContext) {
key: googleSearchKey, key: googleSearchKey,
c2coff: 1, c2coff: 1,
start: 1, start: 1,
num: 5, end: 5,
dateRestrict: 'm[1]' dateRestrict: 'm[1]'
} }
}); });
const result = data.items.map((item) => item.snippet).join('\n'); const result = data.items.map((item) => item.snippet).join('\n');
return { return { prompt: `搜索词: ${searchKey};google 搜索结果: ${result}` };
prompt: `Here are the search results from Google: ${result}`,
searchKey: `\nSearch term: ${searchKey}`
};
} catch (err) { } catch (err) {
console.log(err); console.log(err);
return { return {
@@ -53,18 +54,395 @@ export default async function (ctx: FunctionContext) {
## Workflow ## Workflow
Drag out a FastGPT workflow as shown in the image, where the request URL of the HTTP module is the interface address, and the input and output parameters are as follows: Copy the following configuration, click the Import button in the upper right corner of Advanced orchestration, import the configuration, and copy the interface address to [HTTP module] after import.
**Input**
``` ```json
searchKey: Search Key Word [
{
"moduleId": "userChatInput",
"name": "用户问题(对话入口)",
"flowType": "questionInput",
"position": {
"x": 464.32198615344566,
"y": 1602.2698463081606
},
"inputs": [
{
"key": "userChatInput",
"type": "systemInput",
"label": "用户问题",
"connected": true
}
],
"outputs": [
{
"key": "userChatInput",
"label": "用户问题",
"type": "source",
"valueType": "string",
"targets": [
{
"moduleId": "6g2075",
"key": "content"
},
{
"moduleId": "aijmbb",
"key": "userChatInput"
}
]
}
]
},
{
"moduleId": "history",
"name": "聊天记录",
"flowType": "historyNode",
"position": {
"x": 452.5466249541586,
"y": 1276.3930310334215
},
"inputs": [
{
"key": "maxContext",
"type": "numberInput",
"label": "最长记录数",
"value": 6,
"min": 0,
"max": 50,
"connected": true
},
{
"key": "history",
"type": "hidden",
"label": "聊天记录",
"connected": true
}
],
"outputs": [
{
"key": "history",
"label": "聊天记录",
"valueType": "chat_history",
"type": "source",
"targets": [
{
"moduleId": "6g2075",
"key": "history"
},
{
"moduleId": "aijmbb",
"key": "history"
}
]
}
]
},
{
"moduleId": "6g2075",
"name": "文本内容提取",
"flowType": "contentExtract",
"showStatus": true,
"position": {
"x": 971.5119545668634,
"y": 1118.186021718385
},
"inputs": [
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": false
},
{
"key": "description",
"type": "textarea",
"valueType": "string",
"label": "提取要求描述",
"description": "写一段提取要求,告诉 AI 需要提取哪些内容",
"required": true,
"placeholder": "例如: \n1. 你是一个实验室预约助手。根据用户问题,提取出姓名、实验室号和预约时间",
"value": "你是谷歌搜索机器人,可以生成搜索词。你需要自行判断是否需要生成搜索词,如果不需要则返回空字符串。",
"connected": true
},
{
"key": "history",
"type": "target",
"label": "聊天记录",
"valueType": "chat_history",
"connected": true
},
{
"key": "content",
"type": "target",
"label": "需要提取的文本",
"required": true,
"valueType": "string",
"connected": true
},
{
"key": "extractKeys",
"type": "custom",
"label": "目标字段",
"description": "由 '描述' 和 'key' 组成一个目标字段,可提取多个目标字段",
"value": [
{
"desc": "搜索词",
"key": "searchKey",
"required": false
}
],
"connected": true
}
],
"outputs": [
{
"key": "success",
"label": "字段完全提取",
"valueType": "boolean",
"type": "source",
"targets": []
},
{
"key": "failed",
"label": "提取字段缺失",
"valueType": "boolean",
"type": "source",
"targets": [
{
"moduleId": "aijmbb",
"key": "switch"
}
]
},
{
"key": "fields",
"label": "完整提取结果",
"description": "一个 JSON 字符串,例如:{\"name:\":\"YY\",\"Time\":\"2023/7/2 18:00\"}",
"valueType": "string",
"type": "source",
"targets": []
},
{
"key": "searchKey",
"label": "提取结果-搜索词",
"description": "无法提取时不会返回",
"valueType": "string",
"type": "source",
"targets": [
{
"moduleId": "5fk9ru",
"key": "searchKey"
}
]
}
]
},
{
"moduleId": "5fk9ru",
"name": "HTTP模块",
"flowType": "httpRequest",
"showStatus": true,
"position": {
"x": 1481.5339897373183,
"y": 1290.2958964143072
},
"inputs": [
{
"key": "url",
"value": "https://d8dns0.laf.dev/google_web_search",
"type": "input",
"label": "请求地址",
"description": "请求目标地址",
"placeholder": "https://api.fastgpt.run/getInventory",
"required": true,
"connected": true
},
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": false
},
{
"valueType": "string",
"type": "target",
"label": "搜索词",
"edit": true,
"key": "searchKey",
"required": true,
"connected": true
}
],
"outputs": [
{
"label": "搜索词",
"valueType": "string",
"type": "source",
"edit": true,
"targets": [],
"key": "searchKey"
},
{
"label": "搜索结果",
"valueType": "string",
"type": "source",
"edit": true,
"targets": [
{
"moduleId": "aijmbb",
"key": "systemPrompt"
}
],
"key": "prompt"
},
{
"key": "finish",
"label": "请求结束",
"valueType": "boolean",
"type": "source",
"targets": [
{
"moduleId": "aijmbb",
"key": "switch"
}
]
}
]
},
{
"moduleId": "aijmbb",
"name": "AI 对话",
"flowType": "chatNode",
"showStatus": true,
"position": {
"x": 2086.6387991825745,
"y": 1090.812798225035
},
"inputs": [
{
"key": "model",
"type": "custom",
"label": "对话模型",
"value": "gpt-3.5-turbo-16k",
"list": [],
"connected": true
},
{
"key": "temperature",
"type": "slider",
"label": "温度",
"value": 0,
"min": 0,
"max": 10,
"step": 1,
"markList": [
{
"label": "严谨",
"value": 0
},
{
"label": "发散",
"value": 10
}
],
"connected": true
},
{
"key": "maxToken",
"type": "custom",
"label": "回复上限",
"value": 8000,
"min": 100,
"max": 4000,
"step": 50,
"markList": [
{
"label": "100",
"value": 100
},
{
"label": "4000",
"value": 4000
}
],
"connected": true
},
{
"key": "systemPrompt",
"type": "textarea",
"label": "系统提示词",
"valueType": "string",
"description": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"placeholder": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"value": "",
"connected": true
},
{
"key": "limitPrompt",
"type": "textarea",
"valueType": "string",
"label": "限定词",
"description": "限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。可使用变量,例如 {{language}}。引导例子:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 \"Laf\" 无关内容,直接回复: \"我不知道\"。\n2. 你仅回答关于 \"xxx\" 的问题,其他问题回复: \"xxxx\"",
"placeholder": "限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。可使用变量,例如 {{language}}。引导例子:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 \"Laf\" 无关内容,直接回复: \"我不知道\"。\n2. 你仅回答关于 \"xxx\" 的问题,其他问题回复: \"xxxx\"",
"value": "上文是谷歌搜索的结果,你可以提供实时信息,根据搜索结果回答问题。当前时间是{{cTime}}。",
"connected": true
},
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": true
},
{
"key": "quoteQA",
"type": "target",
"label": "引用内容",
"valueType": "kb_quote",
"connected": false
},
{
"key": "history",
"type": "target",
"label": "聊天记录",
"valueType": "chat_history",
"connected": true
},
{
"key": "userChatInput",
"type": "target",
"label": "用户问题",
"required": true,
"valueType": "string",
"connected": true
}
],
"outputs": [
{
"key": "answerText",
"label": "模型回复",
"description": "直接响应,无需配置",
"type": "hidden",
"targets": []
},
{
"key": "finish",
"label": "回复结束",
"description": "AI 回复完成后触发",
"valueType": "boolean",
"type": "source",
"targets": []
}
]
}
]
``` ```
**Output** **Process Description**
``` 1. The extraction module extracts the user's question into search keywords.
prompt: Search Result 2. The search keywords are passed to the HTTP module.
``` 3. The HTTP module calls the Google search API and returns the search results.
4. The search results are passed to the prompt of the "AI Dialogue" to guide the model in generating an answer.
- The HTTP module will send the searchKey to laf, and laf will perform a Google search based on the received input. It will then return the search results through the prompt parameter.
- After receiving the response, the HTTP module connects to the prompt of the "AI Dialogue" to guide the model in providing an answer.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 368 KiB

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 KiB

After

Width:  |  Height:  |  Size: 280 KiB

View File

@@ -38,12 +38,12 @@ export default async function (ctx: FunctionContext) {
key: googleSearchKey, key: googleSearchKey,
c2coff: 1, c2coff: 1,
start: 1, start: 1,
num: 5, end: 5,
dateRestrict: 'm[1]' dateRestrict: 'm[1]'
} }
}); });
const result = data.items.map((item) => item.snippet).join('\n'); const result = data.items.map((item) => item.snippet).join('\n');
return { prompt: `这是 google 搜索的结果: ${result}`, searchKey: `\n搜索词为: ${searchKey}` }; return { prompt: `搜索词: ${searchKey};google 搜索结果: ${result}` };
} catch (err) { } catch (err) {
console.log(err); console.log(err);
return { return {
@@ -55,19 +55,395 @@ export default async function (ctx: FunctionContext) {
## 编排 ## 编排
按上图拖出一个 FastGPT 编排组合,其中 HTTP 模块的请求地址为接口地址,出入参如下: 复制下面配置,点击高级编排右上角的导入按键,导入该配置,导入后将接口地址复制到 【HTTP 模块】。
**入参** ```json
[
``` {
searchKey: 搜索词 "moduleId": "userChatInput",
"name": "用户问题(对话入口)",
"flowType": "questionInput",
"position": {
"x": 464.32198615344566,
"y": 1602.2698463081606
},
"inputs": [
{
"key": "userChatInput",
"type": "systemInput",
"label": "用户问题",
"connected": true
}
],
"outputs": [
{
"key": "userChatInput",
"label": "用户问题",
"type": "source",
"valueType": "string",
"targets": [
{
"moduleId": "6g2075",
"key": "content"
},
{
"moduleId": "aijmbb",
"key": "userChatInput"
}
]
}
]
},
{
"moduleId": "history",
"name": "聊天记录",
"flowType": "historyNode",
"position": {
"x": 452.5466249541586,
"y": 1276.3930310334215
},
"inputs": [
{
"key": "maxContext",
"type": "numberInput",
"label": "最长记录数",
"value": 6,
"min": 0,
"max": 50,
"connected": true
},
{
"key": "history",
"type": "hidden",
"label": "聊天记录",
"connected": true
}
],
"outputs": [
{
"key": "history",
"label": "聊天记录",
"valueType": "chat_history",
"type": "source",
"targets": [
{
"moduleId": "6g2075",
"key": "history"
},
{
"moduleId": "aijmbb",
"key": "history"
}
]
}
]
},
{
"moduleId": "6g2075",
"name": "文本内容提取",
"flowType": "contentExtract",
"showStatus": true,
"position": {
"x": 971.5119545668634,
"y": 1118.186021718385
},
"inputs": [
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": false
},
{
"key": "description",
"type": "textarea",
"valueType": "string",
"label": "提取要求描述",
"description": "写一段提取要求,告诉 AI 需要提取哪些内容",
"required": true,
"placeholder": "例如: \n1. 你是一个实验室预约助手。根据用户问题,提取出姓名、实验室号和预约时间",
"value": "你是谷歌搜索机器人,可以生成搜索词。你需要自行判断是否需要生成搜索词,如果不需要则返回空字符串。",
"connected": true
},
{
"key": "history",
"type": "target",
"label": "聊天记录",
"valueType": "chat_history",
"connected": true
},
{
"key": "content",
"type": "target",
"label": "需要提取的文本",
"required": true,
"valueType": "string",
"connected": true
},
{
"key": "extractKeys",
"type": "custom",
"label": "目标字段",
"description": "由 '描述' 和 'key' 组成一个目标字段,可提取多个目标字段",
"value": [
{
"desc": "搜索词",
"key": "searchKey",
"required": false
}
],
"connected": true
}
],
"outputs": [
{
"key": "success",
"label": "字段完全提取",
"valueType": "boolean",
"type": "source",
"targets": []
},
{
"key": "failed",
"label": "提取字段缺失",
"valueType": "boolean",
"type": "source",
"targets": [
{
"moduleId": "aijmbb",
"key": "switch"
}
]
},
{
"key": "fields",
"label": "完整提取结果",
"description": "一个 JSON 字符串,例如:{\"name:\":\"YY\",\"Time\":\"2023/7/2 18:00\"}",
"valueType": "string",
"type": "source",
"targets": []
},
{
"key": "searchKey",
"label": "提取结果-搜索词",
"description": "无法提取时不会返回",
"valueType": "string",
"type": "source",
"targets": [
{
"moduleId": "5fk9ru",
"key": "searchKey"
}
]
}
]
},
{
"moduleId": "5fk9ru",
"name": "HTTP模块",
"flowType": "httpRequest",
"showStatus": true,
"position": {
"x": 1481.5339897373183,
"y": 1290.2958964143072
},
"inputs": [
{
"key": "url",
"value": "https://d8dns0.laf.dev/google_web_search",
"type": "input",
"label": "请求地址",
"description": "请求目标地址",
"placeholder": "https://api.fastgpt.run/getInventory",
"required": true,
"connected": true
},
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": false
},
{
"valueType": "string",
"type": "target",
"label": "搜索词",
"edit": true,
"key": "searchKey",
"required": true,
"connected": true
}
],
"outputs": [
{
"label": "搜索词",
"valueType": "string",
"type": "source",
"edit": true,
"targets": [],
"key": "searchKey"
},
{
"label": "搜索结果",
"valueType": "string",
"type": "source",
"edit": true,
"targets": [
{
"moduleId": "aijmbb",
"key": "systemPrompt"
}
],
"key": "prompt"
},
{
"key": "finish",
"label": "请求结束",
"valueType": "boolean",
"type": "source",
"targets": [
{
"moduleId": "aijmbb",
"key": "switch"
}
]
}
]
},
{
"moduleId": "aijmbb",
"name": "AI 对话",
"flowType": "chatNode",
"showStatus": true,
"position": {
"x": 2086.6387991825745,
"y": 1090.812798225035
},
"inputs": [
{
"key": "model",
"type": "custom",
"label": "对话模型",
"value": "gpt-3.5-turbo-16k",
"list": [],
"connected": true
},
{
"key": "temperature",
"type": "slider",
"label": "温度",
"value": 0,
"min": 0,
"max": 10,
"step": 1,
"markList": [
{
"label": "严谨",
"value": 0
},
{
"label": "发散",
"value": 10
}
],
"connected": true
},
{
"key": "maxToken",
"type": "custom",
"label": "回复上限",
"value": 8000,
"min": 100,
"max": 4000,
"step": 50,
"markList": [
{
"label": "100",
"value": 100
},
{
"label": "4000",
"value": 4000
}
],
"connected": true
},
{
"key": "systemPrompt",
"type": "textarea",
"label": "系统提示词",
"valueType": "string",
"description": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"placeholder": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"value": "",
"connected": true
},
{
"key": "limitPrompt",
"type": "textarea",
"valueType": "string",
"label": "限定词",
"description": "限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。可使用变量,例如 {{language}}。引导例子:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 \"Laf\" 无关内容,直接回复: \"我不知道\"。\n2. 你仅回答关于 \"xxx\" 的问题,其他问题回复: \"xxxx\"",
"placeholder": "限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。可使用变量,例如 {{language}}。引导例子:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 \"Laf\" 无关内容,直接回复: \"我不知道\"。\n2. 你仅回答关于 \"xxx\" 的问题,其他问题回复: \"xxxx\"",
"value": "上文是谷歌搜索的结果,你可以提供实时信息,根据搜索结果回答问题。当前时间是{{cTime}}。",
"connected": true
},
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": true
},
{
"key": "quoteQA",
"type": "target",
"label": "引用内容",
"valueType": "kb_quote",
"connected": false
},
{
"key": "history",
"type": "target",
"label": "聊天记录",
"valueType": "chat_history",
"connected": true
},
{
"key": "userChatInput",
"type": "target",
"label": "用户问题",
"required": true,
"valueType": "string",
"connected": true
}
],
"outputs": [
{
"key": "answerText",
"label": "模型回复",
"description": "直接响应,无需配置",
"type": "hidden",
"targets": []
},
{
"key": "finish",
"label": "回复结束",
"description": "AI 回复完成后触发",
"valueType": "boolean",
"type": "source",
"targets": []
}
]
}
]
``` ```
**出参** **流程说明**
``` 1. 提取模块将用户的问题提取成搜索关键词
prompt: 搜索结果 2. 将搜索关键词传入 HTTP 模块
``` 3. HTTP 模块调用谷歌搜索接口,返回搜索内容
4. 将搜索内容传入【AI 对话】的提示词,引导模型进行回答。
- HTTP 模块会将 searchKey 发送到 laflaf 接收后去进行谷歌搜索,并将搜索的结果通过 prompt 参数返回。
- 返回后HTTP 模块连接到【AI 对话】的提示词,引导模型进行回答。