主题
JavaScript&Python节点
使用场景
Javascript/Python节点支持我们使用代码的方式完成很多复杂的功能,对于开发者用户来说,这是一个令人兴奋的特性,你可以完全解放你的编码能力做出更复杂更优秀的应用,得益于Code的的灵活性,该节点可以完全覆盖下面的业务场景:
- 我想自定义一个Plugin,但是平台提供的节点和Plugin不包含我的需求
- 我想做一个非常复杂的Flow,但是可视化的逻辑控制和循环控制可读性太差了
- 我希望通过Flow来为Agent实现持久化的记忆
- ...
输入与输出
前置节点中的变量,比如Start节点中定义的表单字段、前置节点的输出变量都已经内置在当前代码的执行环境中了,你可以直接使用,无需重新声明,或者从参数中获取,举个例子:
python
async def main():
# 假设message是start节点定义的一个变量
# 编辑器中可以直接通过start表单中定义的变量名使用该变量
print(message)
# 如果你想使用节点的返回结果
# 你可以直接通过节点的命名去使用
# 这里假设你有一个名为llm_1的LLM节点
print(llm_1)
return message
javascript
async function main() {
/**
* 假设message是start节点定义的一个变量
* 编辑器中可以直接通过start表单中定义的变量名使用该变量
*/
console.log(message);
/**
* 如果你想使用节点的返回结果
* 你可以直接通过节点的命名去使用
* 这里假设你有一个名为llm_1的LLM节点
*/
console.log(llm_1)
return message;
}
当前节点的输出即为当前节点里面main函数的输出,所以你必须要保证编写的代码中有一个入口main函数,如果代码中没有main函数则运行会出错,如果main函数没有return,则默认当前节点输出为null。
💡 Javascript/Python节点的输出必须是一个可序列化的值,所以你不能return正则、函数或者其他不可序列化的值。
全局变量
Flow的执行环境支持设置当前Flow运行时的全局变量,该变量在整个Flow的运行生命周期中,都可访问,不会受所在节点的位置约束,eg:在多个逻辑分支中可以通过全局变量共享数据。
python
async def main():
# 设置全局变量
betterAI.store.set("value", 123);
betterAI.store.set("json", {});
# 获取全局变量
betterAI.store.get("value"); # 123
betterAI.store.get("json"); # {}
# 其他节点可以可以访问该全局变量,比如LLM中,可以通过 {{betterAI.store.get("value")}} 访问
typescript
async function main() {
// 设置全局变量
betterAI.store.set("value", 123);
betterAI.store.set("json", {});
// 获取全局变量
betterAI.store.get("value"); // 123
betterAI.store.get("json"); // {}
// 其他节点可以可以访问该全局变量,比如LLM中,可以通过 {{betterAI.store.get("value")}} 访问
}
💡 在其他节点中,也可以通过
betterAI.store.get
获取全局变量,以LLM为例,可以通过betterAI.store.get("value")
的表达式获取全局变量,其中value为其他节点通过betterAI.store.set("value")
设置的全局变量。
内置包
Javascript/Python的执行环境中,平台内置了很多开发包,来帮助我们更轻松的完成复杂需求,在使用之前我们可以通过语言的导入语法先引入包之后才能使用,但是Javascript只能使用CommonJS的导入语法,不能使用ES Module 的导入语法;
下面以一个示例来演示如何使用环境中的内置包:
python
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
import datetime
# 获取当前日期和时间
now = datetime.datetime.now()
print("当前日期和时间:", now)
# 获取明天的日期
tomorrow = now + datetime.timedelta(days=1)
print("明天的日期:", tomorrow)
# 日期格式化输出
formatted_date = now.strftime("%Y-%m-%d %H:%M:%S")
print("格式化日期:", formatted_date)
javascript
const axios = require('axios');
const dayjs = require('dayjs');
const crypto = require('crypto');
async function main() {
// 示例一:使用内置axios包发起一个http请求
const res = await axios.get('https://resource.bantouyan.com/betteryeah/chat/test_api.json');
console.log("接口的响应为:", res.data);
// 示例二:使用内置dayjs的包,获取当前时间并格式化
const date = dayjs().format('YYYY-MM-DD HH:mm:ss');
console.log("格式化的日期为:", date);
// 示例三:使用crypto对下面的参数进行加签
const params = `api=/example&appKey=test&data=${JSON.stringify({ keyworkd: "母婴" })}×tamp=${Math.floor(new Date().getTime() / 1000)}`;
const base64Str = Buffer.from(params).toString('base64');
const sha1Hash = crypto.createHash('sha1');
sha1Hash.update(base64Str);
const sign = sha1Hash.digest('hex');
console.log("加签后的参数为:", sign);
}
更多平台内置的包,可以在编辑器左侧的内置包模块中找到
BetterYeah SDK
SDK作为内置包安装在Javascript/Python的执行环境中了,所以无需重复安装,该SDK封装了Flow中Node节点的能力,可以让你通过代码的方式自由的使用Flow的节点,完成更复杂的业务需求
快速开始
以构建一个从用户输入向LLM提问,LLM回答用户的案例开始,了解SDK的功能
python
from betteryeah import BetterYeah, Model
better_yeah = BetterYeah()
async def main():
res = better_yeah.llm.chat(system_prompt="你好", model=Model.qwen_plus)
if not res.success:
raise Exception(message="执行失败")
return res.data
typescript
const Betteryeah = require('betteryeah').default
const { LLMModel } = require('betteryeah')
const betteryeah = new Betteryeah()
async function main() {
const res = await betteryeah.llm.chat({
systemPrompt: '你好',
model: LLMModel.qwen_plus,
})
if (!res.success) {
throw new Error(res.message)
}
return res.data
}
导入和实例化
python
# 导入SDK
from betteryeah import BetterYeah, Model
# 实例化SDK
better_yeah = BetterYeah()
typescript
// 导入SDK
const Betteryeah = require('betteryeah').default
// 实例化SDK
const betteryeah = new Betteryeah()
SDK实例介绍
模块列表:
模块名称 | 模块说明 |
---|---|
llm | 封装了LLM节点的能力,可以基于此模块使用各种大模型的能力 |
knowledge | 封装了知识库节点的能力,可以基于此模块查询/插入知识库 |
database | 封装了数据库节点的能力,可以基于此模块使用数据库节点的能力 |
plugin | 封装了平台插件的能力,可以基于此使用平台的插件 |
subFlow | 封装了子流程节点的能力,可以通过Code调用其他Flow |
LLM 模块
模块方法:
方法名称 | 描述 | 参数 | 返回值 |
---|---|---|---|
chat | 发起一次会话 | LLMOptions | Promise<ApiResponse<string | object>> |
示例代码:
python
from betteryeah import BetterYeah, Model
betteryeah = BetterYeah()
message_history = [
{
"role": "user",
"content": "你好"
},
{
"role": "assistant",
"content": "你好,有什么可以帮助您?"
}
]
message_history = []
result = betteryeah.llm.chat(
'中国的汉朝有几位皇帝',
json_mode=False,
model=Model.qwen_plus,
messages=message_history,
temperature=0.7
)
print(result.json())
typescript
const Betteryeah = require('betteryeah').default
const { LLMModel } = require('betteryeah');
const betteryeah = new Betteryeah()
async function main() {
const res = await betteryeah.llm.chat({
systemPrompt: "你是一个电商客服",
model: LLMModel.qwen_plus,
jsonMode: false,
temperature: 0.7,
messages: [
{
role: "user",
content: "你好",
},
{
role: "assistant",
content: "你好,有什么可以帮助你的?"
},
{
role: "user",
content: "请问外省一般几天发货?"
}
]
})
if (!res.success) {
throw new Error(res.message ?? 'llm执行出错')
}
return res.data
}
LLMOptions
Llm chat 方法的参数
字段名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
systemPrompt | string | 必填 | 传给LLM节点的系统提示词 |
model | LLMModel | 必填 | 要使用的模型名称,可以从SDK中导入选项 |
jsonMode | boolean | 非必填 | 控制模型是否以JSON格式输出,注意目前只有部分模型支持此参数 |
messages | Message[] | 非必填 | 传给模型的对话上下文 |
temperature | number | 非必填 | 0 ~ 1, 控制模型的创造性 |
Message
模型对话上下文的具体属性
属性名称 | 类型 | 描述 |
---|---|---|
role | "user" | "assistant" | user表示用户角色,assistant表示模型角色 |
content | string | 消息内容 |
Knowledge模块
模块方法:
方法名称 | 描述 | 参数 | 返回值 |
---|---|---|---|
insertKnowledge | 插入内容到知识库 | InsertKnowledgeOptions | Promise<ApiResponse<InsertKnowledgeResult> |
searchKnowledge | 查询知识库内容 | SearchKnowledgeOptions | Promise<ApiResponse<SearchKnowledgeResult | string> |
示例代码:
python
from betteryeah import BetterYeah, OutPutType, HitStrategyType
betteryeah = BetterYeah()
async def main():
# 插入知识库
# partition_id为知识库的id,file_id为知识库文件的file_id 获取方式见资源获取方式
insert_result = betteryeah.knowledge.insert_knowledge("测试", partition_id="知识库的partition_id", file_id='文件的_file_id')
print(insert_result.data)
# 查询知识库
search_result = betteryeah.knowledge.search_knowledge(
search_content="测试",
partition_id="知识库的partition_id",
tags=[],
file_ids=['文件的_file_id','文件的_file_id'],
output_type=OutPutType.JSON,
hit_strategy=HitStrategyType.MIX,
max_result_num=3,
ranking_strategy=False)
print(result.data)
typescript
const Betteryeah = require('betteryeah').default
const { HitStrategyType } = require('betteryeah');
const betteryeah = new Betteryeah()
async function main() {
// 插入知识库
const res = await betteryeah.knowledge.insertKnowledge({
content: message, // 插入内容,这里直接将用户的输入插入
partitionId: -1, // 知识库id,你可以在左侧资源树中找到你要插入的知识库,点击其右侧复制按钮复制id
fileId: -1, // 需要插入的文件id,可以在右侧资源树中点击复制id
})
if (!res.success) {
throw new Error(res.message ?? '插入知识库出错')
}
// 查询知识库
const res2 = await betteryeah.knowledge.searchKnowledge({
partitionId: -1, // 知识id,需要在左侧资源中,点击知识库模块,选择想要查询的知识库,然后点击知识库条目右侧的复制,来复制知识库id
fileIds: [-1, -1], // 要查询的知识库文件,可以在左侧资源中找到,如果不传就是查询所有文件
searchContent: message, // 查询内容,这里使用用户输入的message作为查询内容
tags: ["标签一"], // 要搜索知识库的标签,如果为空,或者空数组,则查询所有内容,如果不为空则根据传入的标签查询
outputType: "json", // 输出格式
hitStrategy: HitStrategyType.MIX, // 查询方式
maxResultNum: 3, // 最大查询结果
rankingStrategy: false, // 是否开启重排
})
if (!res2.success) {
throw new Error(res.message ?? '知识库节点查询出错')
}
console.log("知识库的查询结果为:", res2.data)
}
InsertKnowledgeOptions
插入知识库方法的参数
字段名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
partitionId | number | 非必填 | 要插入的知识库的id,可以在编辑器左侧资源模块找到 |
fileId | number | 必填 | 要插入的知识库下面的文件id,可以在编辑器左侧资源模块找到 |
content | string | 必填 | 插入知识库的内容 |
InsertKnowledgeResult
插入知识库方法的响应结果
字段名称 | 类型 | 描述 |
---|---|---|
vector_id | string | 向量id |
file_id | number | 插入的知识库的文件id |
chunk_id | number | 插入的知识库的段落id |
content | string | 插入的内容 |
keywords | string[] | 插入知识库后,根据插入内容生产的段落关键词 |
sort_order | number | 段落在文档中的排序 |
enable | boolean | 该段落是否启用了 |
SearchKnowledgeOptions
查询知识库方法的参数
字段名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
partitionId | number | 必填 | 要查询的知识库的id,可以在编辑器左侧资源模块找到 |
searchContent | string | 必填 | 要用于搜索知识库的文本 |
fileIds | number[] | 非必填 | 具体要搜索的知识库下面的文件id,可以在编辑器左侧资源模块找到 如果为空则查询整个知识库 |
tags | string[] | 非必填 | 要搜索知识库的标签,如果为空,或者空数组,则查询所有内容,如果不为空则根据传入的标签查询 |
outputType | "text" | "json" | 非必填 | 输出类型 "text": 文本类型输出,可以非常简单的给大模型使用 "json": 带数据格式的输出,拥有非常丰富的字段,可以用于自定义代码逻辑处理后给大模型,比如我想根据查询结果的相关性二次过滤等等 |
hitStrategy | HitStrategyType | 非必填 | 搜索知识库的方式,默认是混合模式,HitStrategyType.MIX 该选项可以从SDK导入使用 |
maxResultNum | number | 非必填 | 搜索知识库的最大结果数,默认为3 |
rankingStrategy | boolean | 非必填 | 是否开启重排策略,默认不开启 |
HitStrategyType
知识库搜索方式
属性名称 | 描述 |
---|---|
MIX | 混合检索 |
KEY | 关键词检索 |
SEMANTICS | 语义检索 |
SearchKnowledgeResult
字段名称 | 类型 | 描述 |
---|---|---|
cost_time | number | 查询耗时,ms |
match_contents | KnowledgeMatchContent[] | 知识库的匹配结果 |
KnowledgeMatchContent
字段名称 | 类型 | 描述 |
---|---|---|
vector_id | string | 向量id |
file_id | number | 命中段落所在的文件id |
file_type | FileType | 命中文档的类型 |
mimetype | String | null | 文档的mimetype |
chunk_id | number | 该段落在文档中的id |
content | string | 如果是QA类型的文件,该内容为命中的QA的问题如果是其他类型文件,该内容为命中的段落内容 |
keywords | string[] | 命中的段落的所有关键词 |
extra_info | object | null | 如果是QA类型文件,该值存在,里面键值对表示命中的QA的答案,比如{ "答案一": "你好", "答案二": "你好啊" } |
matched_keywords | string[] | 如果是关键词匹配,该值为命中段落的关键词 |
relevance_score | - | 命中的评分信息,可以用来判断相关性 |
Database模块
方法名称 | 描述 | 参数 | 返回值 |
---|---|---|---|
executeDatabase | 在给定的database中执行SQL语句 | ExecuteDatabaseOptions | Promise<ApiResponse<ExecuteDatabaseResult>> |
代码示例:
python
from betteryeah import BetterYeah, Model
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
def main():
# 在使用此示例之前确保自己有一个数据库,并且新建一个名为 「测试数据表」 的数据表
# - user 文本类型
# - age 整数类型
# base_id为数据库id,获取方式见资源获取方式,注意,查询语句必须加限制条数语句
result = better_yeah.database.query_database(
base_id="对应数据库的base_id",
executable_sql="select * from test limit 100"
)
if not result.success:
raise Exception(message=result.message)
print(result.data)
typescript
const Betteryeah = require('betteryeah').default;
const betteryeah = new Betteryeah();
async function main() {
/**
* 在使用此示例之前确保自己有一个数据库,并且新建一个名为 「测试数据表」 的数据表
* - user 文本类型
* - age 整数类型
*/
const databaseId = ''; // databaseId 可以在左侧资源树中找到,点击资源项目右侧的复制按钮复制id
// 演示向数据库中插入一条数据
// 数据库表名可以在左侧资源树中复制
const insertRes = await betteryeah.database.executeDatabase({
databaseId,
executableSql: `
INSERT INTO 测试数据表 ("user", "age") VALUES ('BetterYeah', 3);
`
});
if (!insertRes.success) {
throw new Error(insertRes.message ?? '插入数据库出错')
}
}
ExecuteDatabaseOptions
字段名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
databaseId | string | 必填 | 要操作的数据库id,可以在编辑器左侧资源模块找到 |
executableSql | string | 必填 | 要执行的SQL命令 |
ExecuteDatabaseResult
字段名称 | 类型 | 描述 |
---|---|---|
command | string | 执行的SQL命令 |
rowCount | number | 该SQL命令影响的数据行数 |
data | any[] | SQL命令的执行结果 |
Plugin模块
模块方法列表
image 图片相关插件集合
Parsing 数据解析相关插件集合
search 搜索相关插件集合
xiaohongshu 小红书相关插件集合
douyin 抖音相关插件集合
zhihu 知乎相关插件集合
weibo 微博相关插件集合
bilibili 哔哩哔哩相关插件集合
toutiao 今日头条相关插件集合
generic 通用工具
AI识图
python
from betteryeah import BetterYeah, GenerateImageModel
better_yeah = BetterYeah()
async def main():
result = await better_yeah.plugin.image.vision(
image_path="https://resource.bantouyan.com/betteryeah/temp/FIlP_1716862566510.jpg", # 图片地址
prompt="图片中的物体是什么",
model=GenerateImageModel.gpt_4o
)
print(result)
typescript
const { GenerateImageModel } = require('betteryeah');
const BetterYeah = require('betteryeah').default;
const betteryeah = new BetterYeah()
async function main() {
const result = await betteryeah.plugin.image.vision({
imagePath: ["https://resource.bantouyan.com/betteryeah/temp/FIlP_1716862566510.jpg"], // 要识别的图片地址
model: GenerateImageModel.GPT_4O, // 选择识图模型
prompt: '图片中的物体是什么', // 识图提示词
})
if (!result.success) {
throw new Error(result.message ?? 'AI识图失败')
}
return result.data
}
AI生图
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
async def main():
result = await better_yeah.plugin.image.generate(prompt="生成一座唐代的宝塔")
print(result)
typescript
const BetterYeah = require('betteryeah').default;
const betteryeah = new BetterYeah()
async function main() {
const result = await betteryeah.plugin.image.generate('生成一座唐代宝塔')
if (!result.success) {
throw new Error(result.message ?? 'AI生图失败')
}
return result.data
}
OCR识图
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
result = await better_yeah.plugin.image.ocr("https://resource.bantouyan.com/betteryeah/temp/example.png")
print(result)
return result
typescript
const BetterYeah = require('betteryeah').default;
const betteryeah = new BetterYeah()
async function main() {
const result = await betteryeah.plugin.image.ocr('https://resource.bantouyan.com/betteryeah/temp/example.png')
if (!result.success) {
throw new Error(result.message ?? 'ocr 识图失败')
}
return result.data
}
谷歌搜索
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
async def main():
result = await better_yeah.plugin.search.google(question="汉朝皇帝列表")
print(result)
# 指定域名搜索
result = await better_yeah.plugin.search.google(question="汉朝皇帝列表", parse_web_count=2, domain_name="zhihu.com")
print(result)
typescript
const BetterYeah = require('betteryeah').default;
const betteryeah = new BetterYeah()
async function main() {
const result = await betteryeah.plugin.search.googleSearch({
question: '中国有多少个朝代', // 要搜索的问题
domainName: '', // (可选)限定搜索的域名
parseWebCount: 3, // 可选)解析网页的数量
})
if (!result.success) {
throw new Error(result.message ?? '搜索失败')
}
return result.data
}
Bing搜索
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
async def main():
result = await better_yeah.plugin.search.bing("汉朝皇帝列表")
print(result)
# 指定域名搜索
result = await better_yeah.plugin.search.bing("汉朝皇帝列表", parse_web_count=2, domain_name="zhihu.com")
print(result)
typescript
const BetterYeah = require('betteryeah').default;
const betteryeah = new BetterYeah()
async function main() {
const result = await betteryeah.plugin.search.bingSearch({
question: '中国有多少个朝代', // 要搜索的问题
domainName: '', // (可选)限定搜索的域名
parseWebCount: 3, // 可选)解析网页的数量
})
if (!result.success) {
throw new Error(result.message ?? '搜索失败')
}
return result.data
}
网页解析
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
async def main():
result = await better_yeah.plugin.parsing.web(["https://www.betteryeah.com", "https://www.betteryeah.com/solution"])
print(result)
typescript
const BetterYeah = require('betteryeah').default;
const betteryeah = new BetterYeah();
async function main() {
// 网页解析
const result = await betteryeah.plugin.parsing.web(['https://www.betteryeah.com', 'https://www.betteryeah.com/solution']);
if (!result.success) {
throw new Error(result.message ?? '多网页解析失败');
}
return result.data
}
Excel解析
python
from betteryeah import BetterYeah, ExcelOutputType
better_yeah = BetterYeah()
async def main():
# URL为Excel的文件地址
result = await better_yeah.plugin.parsing.excel("https://resource.bantouyan.com/betteryeah/temp/example.xlsx",
output_format=ExcelOutputType.JSON)
print(result)
typescript
const { ExcelOutputType } = require('betteryeah');
const BetterYeah = require('betteryeah').default;
const betteryeah = new BetterYeah()
async function main() {
// 参数为excel的URl地址
// 默认以JSON格式返回,可以配置解析结果以HTML格式返回
const result = await betteryeah.plugin.parsing.excel(
'https://resource.bantouyan.com/betteryeah/temp/example.xlsx',
ExcelOutputType.JSON
)
if (!result.success) {
throw new Error(result.message ?? '解析失败')
}
return result.data
}
音频解析
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
async def main():
result = await better_yeah.plugin.parsing.audio(
"https://resource.bantouyan.com/betteryeah/temp/example.wav",
False
)
print(result)
typescript
const BetterYeah = require('betteryeah').default;
const betteryeah = new BetterYeah()
async function main() {
/**
* 第一个参数:音频文件的URl地址
* 第二个参数:是否启用智能分轨
*/
const result = await betteryeah.plugin.parsing.audio('https://resource.bantouyan.com/betteryeah/temp/example.wav', false)
if (!result.success) {
throw new Error(result.message ?? '解析失败')
}
return result.data
}
长文本解析
python
from betteryeah import BetterYeah, ArticleParsingModel
better_yeah = BetterYeah()
async def main():
result = await better_yeah.plugin.parsing.article([
"https://resource.bantouyan.com/betteryeah/temp/example.txt",
], analysis_description="请根据url进行解析", model=ArticleParsingModel.Claude)
print(result)
typescript
const { default: BetterYeah, ArticleParsingModel } = require('betteryeah');
const betteryeah = new BetterYeah()
async function main() {
const result = await betteryeah.plugin.parsing.article({
longTextUrlList: ['https://resource.bantouyan.com/betteryeah/temp/example.txt'], // 要解析的文本
analysisDescription: '', // (可选)分析描述。
modelType: ArticleParsingModel.Kimi, // (可选)模型类型。
})
if (!result.success) {
throw new Error(result.message ?? '解析失败')
}
return result.data
}
视频解析
python
from betteryeah import BetterYeah, Model , AnalysisModeType
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
result = await better_yeah.plugin.parsing.video("https://resource.bantouyan.com/betteryeah/temp/example.mp4",AnalysisModeType.OnlyAudio)
print(result)
return result
typescript
const { VideoAnalyzeMode } = require('betteryeah');
const BetterYeah = require('betteryeah').default;
const betteryeah = new BetterYeah()
async function main() {
/**
* 第一个参数:视频文件的URl地址
* 第二个参数(选填):解析方式,默认解析视频 + 音频,可以配置仅解析音频
*/
const result = await betteryeah.plugin.parsing.video('https://resource.bantouyan.com/betteryeah/temp/example.mp4', VideoAnalyzeMode.ScreenshotAndAudio)
if (!result.success) {
throw new Error(result.message ?? '解析失败')
}
return result.data
}
小红书笔记封面批量查询
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.xiaohongshu.search_covers(urls=["https://www.xiaohongshu.com/explore/665e53b60000000005005991"])
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
/**
* 参数为小红书笔记地址,可以多个
*/
const result = await betteryeah.plugin.xiaohongshu.searchCovers(['https://www.xiaohongshu.com/explore/6663fb060000000015009218'])
if (!result.success) {
throw new Error(result.message ?? '查询失败');
}
return result
}
小红书笔记评论批量查询
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.xiaohongshu.search_comments(urls=["https://www.xiaohongshu.com/explore/665e53b60000000005005991"],count=1)
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
/**
* 第一个参数为小红书笔记地址,可以多个
* 第二个参数为每篇笔记要获取的评论数
*/
const result = await betteryeah.plugin.xiaohongshu.searchComments(
['https://www.xiaohongshu.com/explore/6663fb060000000015009218'],
2
);
if (!result.success) {
throw new Error(result.message ?? '查询失败');
}
return result;
}
小红书评论洞察
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.xiaohongshu.get_hot_topic_comments(keyword="中国")
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
/**
* 参数为要搜索的关键词
*/
const result = await betteryeah.plugin.xiaohongshu.getHotTopicComments('咖啡')
if (!result.success) {
throw new Error(result.message ?? '查询失败');
}
return result
}
小红书笔记评论查询
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.xiaohongshu.get_comments(url="https://www.xiaohongshu.com/explore/665e53b60000000005005991")
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
/**
* 参数为小红书笔记地址
*/
const result = await betteryeah.plugin.xiaohongshu.getComments('https://www.xiaohongshu.com/explore/6663fb060000000015009218')
if (!result.success) {
throw new Error(result.message ?? '查询失败');
}
return result
}
小红书获取笔记详情
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.xiaohongshu.get_note_details(url="https://www.xiaohongshu.com/explore/665e53b60000000005005991")
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
/**
* 参数为小红书笔记地址
*/
const result = await betteryeah.plugin.xiaohongshu.getNoteDetails('https://www.xiaohongshu.com/explore/6663fb060000000015009218')
if (!result.success) {
throw new Error(result.message ?? '查询失败');
}
return result
}
小红书笔记搜索
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.xiaohongshu.search_notes(question="中国")
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
/**
* 参数为搜索关键词
*/
const result = await betteryeah.plugin.xiaohongshu.searchNotes('咖啡')
if (!result.success) {
throw new Error(result.message ?? '查询失败');
}
return result
}
小红书爆款笔记搜索
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.xiaohongshu.search_popular_notes(keyword="中国",count=1)
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
/**
* 第一个参数为搜索关键词
* 第二个参数为要获取的笔记数量
*/
const result = await betteryeah.plugin.xiaohongshu.searchPopularNotes('鸡蛋', 1);
if (!result.success) {
throw new Error(result.message ?? '查询失败');
}
return result;
}
小红书低粉爆款笔记查询
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.xiaohongshu.search_low_follower_popular_notes(keyword="滑板车", count=1)
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
/**
* 第一个参数为搜索关键词
* 第二个参数为要获取的笔记数量
*/
const result = await betteryeah.plugin.xiaohongshu.searchLowFollowerPopularNotes('鸡蛋', 1);
if (!result.success) {
throw new Error(result.message ?? '查询失败');
}
return result;
}
小红书查询指定账号下的热门笔记
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 第一个参数为小红书博主账号id, 可以在博主的个人中心页面查看
async def main():
res = await better_yeah.plugin.xiaohongshu.search_account_notes(author_id="7283179518", count=1)
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
/**
* 第一个参数为小红书博主账号id, 可以在博主的个人中心页面查看
* 第二个参数为要获取的笔记数量
*/
const result = await betteryeah.plugin.xiaohongshu.searchAccountNotes('7283179518', 1);
if (!result.success) {
throw new Error(result.message ?? '查询失败');
}
return result;
}
获取小红书实时热点
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.xiaohongshu.get_hot_topics()
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
const result = await betteryeah.plugin.xiaohongshu.getHotTopics()
if (!result.success) {
throw new Error(result.message ?? '查询失败');
}
return result
}
抖音视频分析
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.douyin.analyze_video(url="https://v.douyin.com/ijpRaosx/")
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
/**
* 参数为要分析的视屏短连接
*/
const result = await betteryeah.plugin.douyin.analyzeVideo('https://v.douyin.com/ijpDh74e')
if (!result.success) {
throw new Error(result.message ?? '分析失败');
}
return result;
}
抖音实时热榜
python
from betteryeah import BetterYeah,DouyinHotspotsType
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.douyin.get_hot_topics(type=DouyinHotspotsType.society)
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
/**
* 参数为榜单类型,可选:'热榜' | '娱乐榜' | '社会榜' | '挑战榜'
*/
const result = await betteryeah.plugin.douyin.getHotTopics('热榜')
if (!result.success) {
throw new Error(result.message ?? '获取失败');
}
return result;
}
获取哔哩哔哩实时热榜
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.bilibili.get_hot_topics()
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
const result = await betteryeah.plugin.bilibili.getHotTopics()
if (!result.success) {
throw new Error(result.message ?? '查询失败');
}
return result
}
获取知乎实时热榜
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.zhihu.get_hot_topics()
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
const result = await betteryeah.plugin.zhihu.getHotTopics()
if (!result.success) {
throw new Error(result.message ?? '查询失败');
}
return result
}
获取微博实时热榜
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.weibo.get_hot_topics()
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
const result = await betteryeah.plugin.weibo.getHotTopics()
if (!result.success) {
throw new Error(result.message ?? '查询失败');
}
return result
}
获取今日头条实时热榜
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
res = await better_yeah.plugin.toutiao.get_hot_topics()
return res
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
const result = await betteryeah.plugin.toutiao.getHotTopics()
if (!result.success) {
throw new Error(result.message ?? '查询失败');
}
return result
}
图表绘制
python
import json
from betteryeah import BetterYeah
better_yeah = BetterYeah()
# 必须保证节点中存在一个main函数
# 你的代码应该在main函数中编写
# main函数的返回值为当前节点的返回值
async def main():
# 本插件可以使用直接数据或者文件进行图表绘制
data = {
"Apple": 98,
"XiaoMi": 90,
"HuaWei": 92,
"Oppo": 88
}
result = await better_yeah.plugin.generic.chart_plotting(requirements="按照各个手机品牌的受欢迎统计数据绘制一个柱形图",
data_desc="各个手机品牌受欢迎程度统计结果数据",
data=json.dumps(data))
print(result)
# 使用excel文件进行解析
result = await better_yeah.plugin.generic.chart_plotting(requirements="按照各个手机品牌的受欢迎统计数据绘制一个柱形图",
data_desc="各个手机品牌受欢迎程度统计结果数据",
excel_file="https://resource.bantouyan.com/betteryeah/temp/data_example.xlsx")
print(result)
typescript
const { default: BetterYeah } = require('betteryeah');
const betteryeah = new BetterYeah();
async function main() {
const result = await betteryeah.plugin.generic.chartPlotting({
// 图表绘制的需求描述,包含图表类型(折线、柱状等)、数据维度、工具栏等等图表细节信息
requirements: "按照各个手机品牌的受欢迎统计数据绘制一个柱形图",
// 数据描述,即针对数据的解释,包含数据含义整体描述、字段含义、数据间逻辑关系等等信息
dataDesc: "各个手机品牌受欢迎程度统计结果数据",
// 用于生成图表的自定义数据源,可以是任意格式的json数据
data: {
"Apple": 98,
"XiaoMi": 90,
"HuaWei": 92,
"Oppo": 88
},
// 可是使用data通过JSON传入数据,也可以通过一个excel地址传入数据,data和excelFile的数据传入方式选其一即可。
// excelFile: "https://resource.bantouyan.com/betteryeah/temp/data_example.xlsx"
});
if (!result.success) {
throw new Error(result.message ?? '绘制失败');
}
return result;
}
Subflow模块
Subflow 模块允许你通过 SDK 调用 BetterYeah AI 应用开发平台中已发布的其他工作流,从而提高流程的复用率。对于一些简单的工作流,你可以通过平台搭建这些工作流以提高工作效率,然后使用 Subflow 模块将其集成到你的代码中。
调用子流程示例
python
from betteryeah import BetterYeah
better_yeah = BetterYeah()
async def main():
# flow_id 可以在左侧资源列表中找到
# parameter 为子流程入参,也可以在左侧资源列表查看
result = await better_yeah.sub_flow.execute(
flow_id="a50739fc30534178a8a8028ca660fdad",
parameter={"message": "你好"}
)
print(result)
typescript
const BetterYeah = require('betteryeah').default;
const betteryeah = new BetterYeah()
async function main() {
/**
* 第一个参数:flow_id 可以在左侧资源列表中找到
* 第二个参数:parameter 为子流程入参,也可以在左侧资源列表查看
*/
const result = await betteryeah.subFlow.execute('flow_id', { message: '你好' })
if (!result.success) {
throw new Error(result.message ?? '子流程调用失败')
}
return result.data // 子流程调用结果的返回值
}
响应结果
typescript
interface ApiResponse<T> {
code: number; // 响应状态码
success: boolean; // 响应结果,true表示成功,false,表示失败
message: string; // 失败时的错误内容
data?: T; // 响应结果,当响应结果success为false时,该值可能为null或者undefined
now_time: number;
usage: { // 本次调用的耗费信息
consume: number; // 本次调用耗费Yeah积分信息
}
}
各种ID的获取
错误处理
在返回结果的包装类型中,success
字段为true表示执行成功可以获取到最终SDK函数的执行结果,如果为false表示执行出错,我们需要根据响应的message
字段来判断和处理错误,以LLM为例举一个例子:
python
from betteryeah import BetterYeah, Model
better_yeah = BetterYeah()
async def main():
res = better_yeah.llm.chat(system_prompt="你好", model=Model.qwen_plus)
# 处理错误
if not res.success:
raise Exception(message="执行失败")
return res.data
typescript
const Betteryeah = require('betteryeah').default
const { LLMModel } = require('betteryeah');
const betteryeah = new Betteryeah()
async function main() {
const res = await betteryeah.llm.chat({
systemPrompt: "你好",
model: LLMModel.qwen_plus,
})
// 处理错误
if (!res.success) {
throw new Error(res.message ?? 'llm执行出错')
}
return res.data
}
内置方法
执行环境的上下文中内置了一个名为betterAI
的命名空间,该命名空间下提供了一系列和平台交互的变量、函数;
❗ 比较遗憾的是,目前Javascript节点的执行环境支持该命名空间,Python仅支持命名空间的store模块,session模块暂不支持。
命名空间功能介绍:
typescript
betterAI: {
/**
* @description 用于联动平台Agent模块
*/
agent: {
chat: {
/**
* @description 向指定Agent以Assistant的身份推送一条消息
* @param { AgentPushMessageOptions } pushMsgOptions 推送消息的必填参数
* - agentId: string 指定agent的agentID
* - conversationId: string 会话ID
* - content: string 会话推送消息的内容
*/
pushMsg: (pushMsgOptions: AgentPushMessageOptions) => Promise<any>
/**
* @description 发送通知消息,客户端右上角提示
* @param { AgentSendNotifMsgOptions } sendNotifMsgOptions 发送通知消息的参数
* - conversationId: string 会话ID
* - title: string 通知标题
* - content: string 通知内容
*/
sendNotifMsg: (sendNotifMsgOptions: AgentSendNotifMsgOptions) => Promise<any>
/**
* @description 推送消息并发送通知消息
* @param { AgentPushMsgAndSendNotifOptions } pushMsgAndSendNotifOptions 推送和发送通知的参数
* - agentId: string 指定agent的agentID
* - conversationId: string 会话ID
* - content: string 会话推送消息的内容
* - notifTitle: string 通知的标题
* - notifContent: string 通知的内容
*/
pushMsgAndSendNotif: (pushMsgAndSendNotifOptions: AgentPushMsgAndSendNotifOptions) => Promise<any>
/**
* @description 同步自定义消息到agent当前回复中
* @param { AgentSyncMsgOptions } syncMsgOptions 推送和发送通知的参数
* - message: string 用户自定义内容
*/
syncMsg: (syncMsgOptions: AgentSyncMsgOptions) => Promise<any>
},
},
/**
* @description 当Agent调用Flow时,这个对象中存储Agent的一些元信息
* @description 可以使用此对象和调用Flow的Agent做交互
*/
session: {
/**
* @description 调用当前flow的Agent的会话id,会话和用户相关联
*/
conversationId?: string
/**
* @description 会话中的session
* @description 一般情况一个会话只有一个session,运行调试中可以有多个session
* @description session可以作为唯一会话标识
*/
sessionId?: string
/**
* @description 用户在调用Agent时设置的Agent中的变量
*/
agentInput?: Record<string, any>
/**
* @description 一个JSON数据,可以在Agent执行过程中调用betterAI.session.setMetaData设置/修改值
* @description 此字段可以作为Agent的持久化记忆
*/
metaData?: any
/**
* @description 调用此函数更新metaData的值
* @param data 需要存储的值,任意类型, ex: { step: 1 }
*/
setMetaData: (data: any) => Promise<void>
/**
* @description 在没有Agent调用Flow的情况下,此函数可以使用一个sessionId模拟Agent调用的效果
* @description 这个函数一般用于调试Agent调用flow做持久化记忆
*/
initSessionData: ({ sessionId: string }) => Promise<void>
/**
* @description 向Agent聊天中追加一条聊天记录
*/
addChatRecord: (params: {
session_id: string,
content: string
}) => Promise<void>
/**
* @description 获取当前聊天的上下文
* @param conversationId 会话 session id
* @param limit 限制查询多少条记录
* @returns { type: MessageRecord[] } 消息记录
*/
getChatRecord: (sessionId: string, limit: number) => any[]
},
/**
* @description workflow运行时全局变量模块,可以设置和获取运行时的全局变量
*/
store: {
/***
* @description 设置运行时全局变量
*/
set: (key: string, value: any) => void,
/**
* @description 根据key获取运行时设置的全局变量
*/
get: (key: string) => any
}
};
代码示例:
javascript
// 向调用当前flow的Agent会话session中插入一条Assistant身份的数据
await betterAI.session.addChatRecord({
"session_id": betterAI.session.sessionId,
"content": "冬日暖阳4"
})
// 获取调用当前flow的agnet会话session的聊天记录
const record = await betterAI.session. getChatRecord(betterAI.session.sessionId, 10)
/**
* 如果是在当前flow中调试Agent调用flow的情况,你可以使用一个真实的sessionId,通过initSessionData的方法先初始化session
* 初始化sessionData,仅在非Agent调用时模拟session调用以便调试
*/
const sessionId = ''; // 请使用你真实的sessionId,如果没有,可以先用Agent调用一次,从日志中获取
await betterAI.session.initSessionData({
sessionId,
})
await betterAI.session.setMetaData({name: 'xiaoli', age: 20})