Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support sync response & add laf module doc #72

Merged
merged 1 commit into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added docSite/assets/imgs/laf1.webp
Binary file not shown.
Binary file added docSite/assets/imgs/laf2.webp
Binary file not shown.
Binary file added docSite/assets/imgs/laf3.webp
Binary file not shown.
Binary file added docSite/assets/imgs/laf4.webp
Binary file not shown.
88 changes: 88 additions & 0 deletions docSite/content/docs/workflow/modules/laf.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
title: "Laf 函数调用"
description: "FastGPT Laf 函数调用模块介绍"
icon: "Laf"
draft: false
toc: true
weight: 355
---

## 特点

- 可重复添加
- 有外部输入
- 手动配置
- 触发执行
- 核中核模块

![](/imgs/Laf1.webp)

## 介绍

Laf 函数调用模块可以调用 Laf 账号下的云函数,其操作与 HTTP 模块相同,可以理解为封装了请求 Laf 云函数的 http 模块,值得注意的不同之处为:

- 只能使用 POST 请求
- 请求自带系统参数 systemParams

## 具体使用

要能调用 Laf 云函数,首先需要绑定 Laf 账号和应用,并且在应用中创建云函数。

Laf 提供了 PAT(访问凭证) 来实现 Laf 平台外的快捷登录,可以访问 [Laf 文档](https://doc.Laf.run/zh/cli/#%E7%99%BB%E5%BD%95)查看详细如何获取 PAT。

在获取到 PAT 后,我们可以进入 fastgpt 的账号页或是直接在高级编排中使用 Laf 模块,填入 PAT 验证后,选择需要绑定的应用(应用需要是 Running 状态),即可调用 Laf 云函数。

> 如果需要解绑则取消绑定后,点击“更新”即可

![](/imgs/Laf2.webp)

为了更便捷地调用 Laf 云函数,可以参照下面的代码编写云函数,以便 openAPI 识别

```ts
import cloud from '@Lafjs/cloud'

interface IRequestBody {
username: string // 用户名
passwd?: string // 密码
}

interface IResponse {
message: string // 返回信息
data: any // 返回数据
}

type extendedBody = IRequestBody & {
systemParams?: {
appId: string,
variables: string,
histories: string,
cTime: string,
chatId: string,
responseChatItemId: string
}
}

export default async function (ctx: FunctionContext): Promise<IResponse> {
const body: extendedBody = ctx.body;

console.log(body.systemParams.chatId);

return {
message: 'ok',
data: '查找到用户名为' + body.username + '的用户'
};
}
```

具体操作可以是,进入 Laf 的函数页面,新建函数(注意 fastgpt 只会调用 post 请求的函数),然后复制上面的代码或者点击更多模板搜索“fastgpt”,使用下面的模板

![](/imgs/Laf3.webp)

这样就能直接通过点击“同步参数”,一键填写输入输出

![](/imgs/Laf4.webp)

当然也可以手动添加,手动修改后的参数不会被“同步参数”修改

## 作用
Laf 账号是绑定在团队上的,团队的成员可以轻松调用已经编写好的云函数
1 change: 1 addition & 0 deletions packages/global/core/plugin/httpPlugin/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export type PathDataType = {
path: string;
params: any[];
request: any;
response: any;
};

export type OpenApiJsonSchema = {
Expand Down
3 changes: 2 additions & 1 deletion packages/global/core/plugin/httpPlugin/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export const str2OpenApiSchema = async (yamlStr = ''): Promise<OpenApiJsonSchema
name: methodInfo.operationId || path,
description: methodInfo.description || methodInfo.summary,
params: methodInfo.parameters,
request: methodInfo?.requestBody
request: methodInfo?.requestBody,
response: methodInfo.responses
};
return result;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import { useSystemStore } from '@/web/common/system/useSystemStore';
import { ChevronRightIcon } from '@chakra-ui/icons';
import { useQuery } from '@tanstack/react-query';
import dynamic from 'next/dynamic';
import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/module/node/constant';
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum
} from '@fastgpt/global/core/module/node/constant';
import { useToast } from '@fastgpt/web/hooks/useToast';
import Divider from '../modules/Divider';
import RenderToolInput from '../render/RenderToolInput';
Expand All @@ -31,7 +34,7 @@ const NodeLaf = (props: NodeProps<FlowModuleItemType>) => {
const { toast } = useToast();
const { feConfigs } = useSystemStore();
const { data, selected } = props;
const { moduleId, inputs } = data;
const { moduleId, inputs, outputs } = data;

const requestUrl = inputs.find((item) => item.key === ModuleInputKeyEnum.httpReqUrl);

Expand Down Expand Up @@ -144,11 +147,48 @@ const NodeLaf = (props: NodeProps<FlowModuleItemType>) => {
});
});

const responseParams =
lafFunction?.response?.default.content?.['application/json'].schema.properties || {};
const requiredResponseParams =
lafFunction?.response?.default.content?.['application/json'].schema.required || [];

const allResponseParams = [
...Object.keys(responseParams).map((key) => ({
valueType: responseParams[key].type,
name: key,
desc: responseParams[key].description,
required: requiredResponseParams?.includes(key) || false
}))
].filter((item) => !outputs.find((output) => output.key === item.name));
allResponseParams.forEach((param) => {
onChangeNode({
moduleId,
type: 'addOutput',
key: param.name,
value: {
key: param.name,
valueType: param.valueType,
label: param.name,
type: FlowNodeOutputTypeEnum.source,
required: param.required,
description: param.desc || '',
edit: true,
editField: {
key: true,
description: true,
dataType: true,
defaultValue: true
},
targets: []
}
});
});

toast({
status: 'success',
title: t('common.Sync success')
});
}, [inputs, lafData?.lafFunctions, moduleId, selectedFunction, t, toast]);
}, [inputs, lafData?.lafFunctions, moduleId, outputs, selectedFunction, t, toast]);

return (
<NodeCard minW={'350px'} selected={selected} {...data}>
Expand All @@ -174,9 +214,9 @@ const NodeLaf = (props: NodeProps<FlowModuleItemType>) => {
{/* auto set params and go to edit */}
{!!selectedFunction && (
<Flex justifyContent={'flex-end'} mt={2} gap={2}>
{/* <Button variant={'whiteBase'} size={'sm'} onClick={onSyncParams}>
<Button variant={'grayBase'} size={'sm'} onClick={onSyncParams}>
{t('core.module.Laf sync params')}
</Button> */}
</Button>
<Button
variant={'grayBase'}
size={'sm'}
Expand Down
Loading