为了账号安全,请及时绑定邮箱和手机立即绑定

如何在本地使用预构建界面调用Bee Agent框架?

标签:
Python Docker API

介绍

这篇文章说明了如何使用来自DSCE(IBM 数字自助创作平台环境中的)已有源代码来构建自己的解决方案。

DSCE平台是什么呢?

DSCE 是 IBM 的为企业准备的 AI 和数据平台,旨在利用基础模型和机器学习技术。换句话说,DSCE 是一个用户可以挑选用例来体验使用 watsonx 构建的应用程序的平台。开发人员可以访问提示选择和构建指导,同时也可以得到示例应用程序代码,从而加快他们在 watsonx.ai 上的项目进度。

AI代理的使用场景

平台提供的用例之一是一个演示应用程序,用于展示基于大型语言模型(LLM)的代理方法;“使用IBM的人工智能增强您的产品”。要了解这种方法和用例,可以在DSCE网站上运行这个代理程序,或者您也可以在本地环境中运行应用程序的代码进行即时修改,本文将详细介绍这一过程。

为了制作一个本地应用,我们可以直接点击“获取代码按钮”,这将直接带用户到此GitHub仓库。

基于本地构建应用程序

第一步是用应用的这两部分建立一个项目;一个后端部分和一个前端部分。这两部分都用“node.js”(一种JavaScript运行环境)编写,因此很容易使用。最终,该应用程序将采用以下架构。

本地运行时,没有无服务器代码运行部分

重要的是安装正确版本的node.js,可以通过包管理器下载(https://nodejs.org/en/download/package-manager)或者通过运行命令行来完成。

    #!/bin/sh  
    # 下载并安装 nvm 脚本:  
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash  

    # 下载并安装 Node.js 版本:  
    nvm install 22  

    # 验证 Node.js 版本:  
    node -v # 应该显示 "v22.12.0"。结果应为 "v22.12.0"。  
    nvm current # 应该显示 "v22.12.0"。结果应为 "v22.12.0"。  

    # 验证 npm 版本:  
    npm -v # 应该显示 "10.9.0"。结果应为 "10.9.0"。

我本地这个项目的结构是这样的。

后端程序和特定设置
/**

* Copyright 2024 IBM Corp.
 *

*  

* 一个软件按以下许可协议授权:

*  

* 本软件按以下许可协议授权;除非遵守许可协议,否则不得使用此文件。

* 您可以在以下网址获取许可协议副本:

* 

*     http://www.apache.org/licenses/LICENSE-2.0

* 

* 除非适用法律要求或书面协议规定,否则软件按许可协议分发,均按"现状"提供,不附带任何形式的明示或暗示保证。

* 请参阅许可协议获取有关权限和许可限制的特定语言规定。

* 
 */

import { PromptTemplate } from "bee-agent-framework";
import { BaseMessage } from "bee-agent-framework/llms/primitives/message";
import { ValueError } from "bee-agent-framework/errors";
import { isDefined, mapToObj, pickBy } from "remeda";
import { z } from "zod";
import { toBoundedFunction } from "bee-agent-framework/serializer/utils";

export type LLMChatPromptTemplate = PromptTemplate.infer<{ messages: Record<string, string[]>[] }>;

export interface LLMChatTemplate {
  template: LLMChatPromptTemplate;
  messagesToPrompt: (template: LLMChatPromptTemplate) => (messages: BaseMessage[]) => string;
  parameters: {
    stop_sequence: string[];
  };
}

export function messagesToPromptFactory(rolesOverride: Record<string, string | undefined> = {}) {
  const roles: Record<string, string> = pickBy(
    {
      system: "system",
      user: "user",
      assistant: "assistant",
      ...rolesOverride,
    },
    isDefined,
  );

  return (template: LLMChatPromptTemplate) => {
    return toBoundedFunction(
      (messages: BaseMessage[]) => {
        return template.render({
          messages: messages.map((message) =>
            Object.fromEntries(
              Object.entries(roles).map(([key, role]) =>
                message.role === role ? [key, [message.text]] : [key, []],
              ),
            ),
          ),
        });
      },
      [
        {
          name: "template",
          value: template,
        },
        {
          name: "roles",
          value: roles,
        },
      ],
    );
  };
}

export function templateSchemaFactory(roles: readonly string[]) {
  return z.object({
    messages: z.array(z.object(mapToObj(roles, (role) => [role, z.array(z.string())] as const))),
  });
}

const llama31: LLMChatTemplate = {
  template: new PromptTemplate({
    schema: templateSchemaFactory(["system", "user", "assistant", "ipython"] as const),
    template: `{{#messages}}{{#system}}<|begin_of_text|><|start_header_id|>system<|end_header_id|>

    {{system}}<|eot_id|>{{/system}}{{#user}}<|start_header_id|>user<|end_header_id|>

    {{user}}<|eot_id|>{{/user}}{{#assistant}}<|start_header_id|>assistant<|end_header_id|>

    {{assistant}}<|eot_id|>{{/assistant}}{{#ipython}}<|start_header_id|>ipython<|end_header_id|>

    {{ipython}}<|eot_id|>{{/ipython}}{{/messages}}<|start_header_id|>assistant<|end_header_id|>

    `,
  }),
  messagesToPrompt: messagesToPromptFactory({ ipython: "ipython" }),
  parameters: {
    stop_sequence: ["<|eot_id|>"],
  },
};

const llama33: LLMChatTemplate = llama31;

const llama3: LLMChatTemplate = {
  template: new PromptTemplate({
    schema: templateSchemaFactory(["system", "user", "assistant"] as const),
    template: `{{#messages}}{{#system}}<|begin_of_text|><|start_header_id|>system<|end_header_id|>

    {{system}}<|eot_id|>{{/system}}{{#user}}<|start_header_id|>user<|end_header_id|>

    {{user}}<|eot_id|>{{/user}}{{#assistant}}<|start_header_id|>assistant<|end_header_id|>

    {{assistant}}<|eot_id|>{{/assistant}}{{/messages}}<|start_header_id|>assistant<|end_header_id|>
    `,
  }),
  messagesToPrompt: messagesToPromptFactory(),
  parameters: {
    stop_sequence: ["<|eot_id|>"],
  },
};

const granite3Instruct: LLMChatTemplate = {
  template: new PromptTemplate({
    schema: templateSchemaFactory([
      "system",
      "user",
      "assistant",
      "available_tools",
      "tool_call",
      "tool_response",
    ] as const),
    template: `{{#messages}}{{#system}}<|start_of_role|>system<|end_of_role|>
    {{system}}<|end_of_text|>
    {{ end }}{{/system}}{{#available_tools}}<|start_of_role|>available_tools<|end_of_role|>
    {{available_tools}}<|end_of_text|>
    {{ end }}{{/available_tools}}{{#user}}<|start_of_role|>user<|end_of_role|>
    {{user}}<|end_of_text|>
    {{ end }}{{/user}}{{#assistant}}<|start_of_role|>assistant<|end_of_role|>
    {{assistant}}<|end_of_text|>
    {{ end }}{{/assistant}}{{#tool_call}}<|start_of_role|>assistant<|end_of_role|><|tool_call|>
    {{tool_call}}<|end_of_text|>
    {{ end }}{{/tool_call}}{{#tool_response}}<|start_of_role|>tool_response<|end_of_role|>
    {{tool_response}}<|end_of_text|>
    {{ end }}{{/tool_response}}{{/messages}}<|start_of_role|>assistant<|end_of_role|>
    `,
  }),
  messagesToPrompt: messagesToPromptFactory({
    available_tools: "available_tools",
    tool_response: "tool_response",
    tool_call: "tool_call",
  }),
  parameters: {
    stop_sequence: ["<|end_of_text|>"],
  },
};

export class LLMChatTemplates {
  protected static readonly registry = {
    "llama3.3": llama33,
    "llama3.1": llama31,
    "llama3": llama3,
    "granite3Instruct": granite3Instruct,
  };

  static register(model: string, template: LLMChatTemplate, override = false) {
    if (model in this.registry && !override) {
      throw new ValueError(`模型模板 '${model}' 已存在!`);
    }
    this.registry[model as keyof typeof this.registry] = template;
  }

  static has(model: string): boolean {
    return Boolean(model && model in this.registry);
  }

  static get(model: keyof typeof LLMChatTemplates.registry): LLMChatTemplate;
  // eslint-disable-next-line @typescript-eslint/unified-signatures
  static get(model: string): LLMChatTemplate;
  static get(model: string): LLMChatTemplate {
    if (!this.has(model)) {
      throw new ValueError(`模型模板 '${model}' 未找到!`, [], {
        context: {
          validModels: Object.keys(this.registry),
        },
      });
    }
    return this.registry[model as keyof typeof this.registry];
  }
}
...

在 node-backend 中,需要一个名为 .env 的文件来提供 watsonx.ai 所需的信息。

IBM_CLOUD_API_KEY="your-ibm-cloud-api-key"  # IBM云API密钥  
WX_PROJECT_ID="your-watsonx-project-id"  # Watsonx项目ID  
WX_ENDPOINT=https://us-south.ml.cloud.ibm.com  # IBM Cloud服务的美国南部区域机器学习端点

运行下面的命令,我通常在 bash 文件中运行,或者直接在命令行中输入。

    #!/bin/sh  
    # 设置环境变量,忽略以#开头的行
    export $(grep -v '^#' .env | xargs)

并且必要的安装。

npm install``(安装依赖包)

同时还需要修改“package.json”文件以及所有相关的“type”。
{ "type": "模块" }

你也得安装用于前端的“saas”包。
# 全局(全局性地)安装,  
npm 安装 sass -g  
# 或者本地(本地化地)安装,  
npm 安装 sass --save-dev  

整个 `package.json` 文件可能看起来像这样:

{
"name": "node-backend",
"version": "1.0.0",
"main": "main.js",
"license": "MIT",
"scripts": {
"start": "exec tsx main.js"
},
"dependencies": {
"@ibm-generative-ai/node-sdk": "^3.2.3",
"bee-agent-framework": "^0.0.53",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"markdown": "^0.5.0",
"openai": "^4.76.3",
"openai-chat-tokens": "^0.2.8",
"react-markdown": "^9.0.1",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.1",
"tsx": "^4.19.2"
},
"type": "module",
"devDependencies": {
"sass": "^1.83.1"
}
}


## 前端特有的配置
...
import React, { useState, useEffect } from "react";
import { TextArea, Button, ExpandableTile, TileAboveTheFoldContent, TileBelowTheFoldContent, Loading } from "@carbon/react";
import Markdown from 'markdown-to-jsx';
import './App.css';

function CustomAgentFlow({customFrameworkselected}) {

  const [isLoading, setLoading] = useState(false);
  const [inputPrompt, setInputPrompt] = useState('');
  const [agentOutput, setAgentOutput] = useState('');
  const [execution_time, setexecution_time] = useState('');
  const [agentreasondata, setagentreasondata] = useState('');
  const [llmOutput, setllmOutput] = useState('');

  const fetchAgentresponse = async () => {
    setLoading(true);

    try {
      const reqOpts = {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'X-API-Key': 'test' },
        body: JSON.stringify({"input_data": inputPrompt}),
      };

      let response;

      if(customFrameworkselected === "Langchain"){
        response = await fetch(`${process.env.REACT_APP_LANGCHAIN_BACKEND}/langchain/generate`, reqOpts);
      }

      else{ // 选择了蜂代理框架
        response = await fetch(`${process.env.REACT_APP_BEE_BACKEND}/bee-agent-framework/generate`, reqOpts);
      }
...

在前端创建一个“.env”文件,如下面所示。
REACT_APP_BEE_BACKEND=http://127.0.0.1:3001/api/v1  

REACT_APP_LANGCHAIN_BACKEND=http://127.0.0.1:8000/api/v1 # 请勿忘记/api/v1

请运行以下命令(要么像我习惯做的那样,将命令写入一个 bash 脚本中,要么在命令行中运行)。
#!/bin/sh  
# 设置环境变量,忽略以#开头的行
export $(grep -v '^#' .env | xargs)

还需要安装。
npm install
在命令行中运行此命令以安装npm包。

## 打开应用程序

前后端模块都是通过npm命令来启动的。
npm start
运行 Node.js 应用程序的命令 (`npm start`)

# 应用界面

以下是应用程序为代理及其他配置输出的内容。

![](https://imgapi.imooc.com/31cd326709b7e9f014000693.jpg)

如果我们例如这样向代理人提问;

巴黎现在的温度是多少?


答案如下。

截至2025-01-06 10:44:51,现在的气温是10.4°C。


代理的推理过程。
思考 : 用户想知道巴黎当前的温度,所以我将使用OpenMeteo函数来获取巴黎的实时温度。  

行动 : 调用工具 - OpenMeteo,输入参数为巴黎,日期为2025年1月6日,单位为摄氏度。  

观察 : 工具返回了巴黎的实时温度信息。  

思考 : 我已经得到了巴黎的实时温度,现在可以告诉用户了。  

最终答案 : 截至2025年1月6日10点44分51秒,巴黎当前的温度是10.4°C。

单独的大语言模型输出用于比较。
') assert response == '巴黎当前的温度是15度摄氏度。'  

def test_weather_api(): weather_api = WeatherAPI() response = weather_api.get_weather('Paris') assert isinstance(response, str) assert '巴黎当前的温度是' in response  

def test_weather_api_invalid_city(): weather_api = WeatherAPI() response = weather_api.get_weather('Invalid City') assert response == '找不到城市。'  

def test_weather_api_api_key_error(): weather_api = WeatherAPI(api_key='invalid_api_key') response = weather_api.get_weather('Paris') assert response == '无效的API密钥。'  

def test_weather_api_connection_error(): weather_api = WeatherAPI() with mock.patch('requests.get', side_effect=ConnectionError): response = weather_api.get_weather('Paris') assert response == '无法连接到天气API服务。'  

def test_weather_api_json_error(): weather_api = WeatherAPI() with mock.patch('requests.get', return_value=mock.Mock(json=lambda: {'error': 'Invalid JSON'})): response = weather_api.get_weather('Paris') assert response == '无法解析天气API响应数据。'  

def test_weather_api_weather_data_error(): weather_api = WeatherAPI() with mock.patch('requests.get', return_value=mock.Mock(json=lambda: {'main': {}})): response = weather_api.get_weather('Paris') assert response == '无法获取天气信息。'  

def test_weather_api_temperature_error(): weather_api = WeatherAPI() with mock.patch('requests.get', return_value=mock.Mock(json=lambda: {'main': {'temp': None}})): response = weather_api.get_weather('Paris') assert response == '无法获取当前温度。'  

def test_weather_api_unit_conversion(): weather_api = WeatherAPI(unit='imperial') response = weather_api.get_weather('Paris') assert 'F' in response  

def test_weather_api_language(): weather_api = WeatherAPI(language='fr') response = weather_api.get_weather('Paris') assert 'Le' in response assert 'température' in response assert 'C' in response  

def test_weather_api_cache(): weather_api = WeatherAPI() response1 = weather_api.get_weather('Paris') response2 = weather_api.get_weather('Paris') assert response1 == response2


![](https://imgapi.imooc.com/b614e26709b7e9f414001525.jpg)

# 结论:

DSCE,一个数字共创空间,邀请您一起踏上共创的旅程。这个独特的平台汇集了前沿的人工智能、大语言模型和代理技术,这些技术都是为特定行业量身定制的。在这里,创新与可访问性之间的界限变得越来越模糊。客户和合作伙伴都可以探索、适应并利用这些开源应用来推动工业化进程。DSCE倡导协作精神,培养了一个由创作者组成的社区,在这里大家可以利用人工智能的力量塑造各自领域的未来。

通过这个例子,我们展示了如何使用一个带有UI的代理来调用或访问“**Bee Agent框架**”,该框架可以适应用户的具体需求,从而满足不同用户的需求。

一些有用的链接.

* DSCI 网站: <https://dsce.ibm.com/watsonx>
* DSCE 公开代码库: <https://github.com/IBM/dsce-sample-apps/tree/main/explore-industry-specific-agents>
* Bee 代理框架(一种代理工具集): <https://github.com/i-am-bee/bee-agent-framework>
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消