Node接入ChatGPT 的最强对手Claude

news2024/12/28 20:51:41

由于个人的chatGPT免费版本即将到期, Claude 很火,在网上被说成是 ChatGPT 的最强对手,是 ChatGPT 的替代品。本文我将介绍下 Claude 是什么,以及如何免费使用 Claude.

什么是Claude

看一下它是如何自我介绍的

在这里插入图片描述

Slack

Slack 是一款流行的团队协作和通讯软件。
Claude 官方给我定义了很方便的 Slack 应用 Claude-in-Slack,我们直接把它添加到 Slack 中即可使用。添加的操作也很简单:

先注册 Slack
到 Claude 官网,点击 Add to Slack
在跳转的页面点击 添加到 Slack
在 Slack 中选择 Claude 应用,进入聊天窗口开始使用

接下来使用Slack的api来实现调用Claude, 虽然Claude也有接口申请, 但是一直没有通过, 不知道什么原因, 但是既然在Slack中可以使用Claude, 那就取巧, 通过Slack的api来实现调用Claude吧
Slack的api地址:

api.slack.com/methods

Slack 为我们提供了各个语言的 SDK,我们以 node-slack-sdk 来作为演示示例。

获取Slack Token

为了使用 Slack 的 SDK,我们需要新建一个 Slack APP。

在这里插入图片描述

选择Form scratch, 这里说一下, 我这里带翻译是使用了谷歌插件, 最近这个插件挺火的, 也很好用, 可以安利给大家, 插件的名字是沉浸式翻译, 大家直接去谷歌商店搜索就能找到了.

在这里插入图片描述
输入 app 名称并选择自己的 workspace。

在这里插入图片描述

创建后点击我们的 APP,然后点击左侧栏的 OAuth & Permissions。下拉找到 Scopes,为我们的 User Token 添加 Scope。

在这里插入图片描述

添加需要通过接口访问的权限

在这里插入图片描述

在这里插入图片描述
只有授权了才能够通过sdk调用这些接口哦

这些接口分别代表着不同的权限

在这里插入图片描述
然后我们把 APP 安装到我们的 workspace 中:
这个按钮在auth页面的上面

在这里插入图片描述

安装后,这里会生成我们需要的 User OAuth Token,我们复制这个 Token,后面需要用。

如果更改了权限, 就要重新下载到工作区才会出现效果哈

在这里插入图片描述

获取Claude Bot ID

进入Slack应用页面, 找到对应的Claude应用, 右击选择查看应用详情

在这里插入图片描述

复制Claude的成员ID和频道ID
在这里插入图片描述

Slack Claude Server

在服务端开始来获取应用里面的数据

我们需要安装的依赖有:
https://github.com/slackapi/node-slack-sdk

$ npm install @slack/web-api @slack/socket-mode

# Or, if you prefer yarn
$ yarn add @slack/web-api @slack/socket-mode

通过readme,我们可以看到如何像应用中发送一条数据


const { WebClient } = require('@slack/web-api');

// An access token (from your Slack app or custom integration - xoxp, xoxb)
const token = process.env.SLACK_TOKEN;

const web = new WebClient(token);

// This argument can be a channel ID, a DM ID, a MPDM ID, or a group ID
const conversationId = 'C1232456';

(async () => {
  // See: https://api.slack.com/methods/chat.postMessage
  const res = await web.chat.postMessage({ channel: conversationId, text: 'Hello there' });

  // `res` contains information about the posted message
  console.log('Message sent: ', res.ts);
})();

但是我们需要把这样的数据,做成一个接口的形式, 然后方便客户端调用, 我这里选择了express来创造路由接口, 很方便和快速.

拿到客户端输入的数据之后, 我们需要将Claude返回的数据返回给客户端, readme里面就没有提供例子了.

其实方法就是读取Claude这个应用窗口的历史数据, 拿到最新的这条回复, 通过conversations.history接口来拿取数据.

CALUDE_BOT_ID: 是频道ID
CALUDE_CHANNEL_ID: 是成员ID
CALUDE_TOKEN: 是上面拿到的User OAuth Token

import { WebClient } from '@slack/web-api'
import { Router } from "express";

const routes = Router();
// An access token (from your Slack app or custom integration - xoxp, xoxb)
const token = process.env.CALUDE_TOKEN;

const web = new WebClient(token);

// This argument can be a channel ID, a DM ID, a MPDM ID, or a group ID
const conversationId = process.env.CALUDE_CHANNEL_ID;

routes.all("*", function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
})

function sleep(ms: number) {
  return new Promise(resolve=>setTimeout(resolve, ms))
}

routes.post('/chat-process', async (req, res) => {
  
  res.setHeader('Content-type', 'application/octet-stream')
  try {
    const { prompt } = req.body
    const ans = await web.chat.postMessage({ channel: conversationId || '', text: prompt});
    let firstChunk = true
    for(let i = 0; i < 500; i++) {
      try {
        // Call the conversations.history method using WebClient
        const result = await web.conversations.history({
          channel: process.env.CALUDE_BOT_ID || '',
          oldest: ans.ts,
          limit: 2
        });
    
        const conversationHistory = result.messages;
        if (!conversationHistory) {
          sleep(1000)
          continue
        }
        else if(conversationHistory != undefined && Array.isArray(conversationHistory) && conversationHistory[0]?.text?.indexOf('_Typing…_') != -1) {

          res.write(firstChunk ? `${conversationHistory[0].text}` : `${conversationHistory[0].text}`)
          firstChunk = false
          sleep(1000)
          continue
        }
        res.write(`${conversationHistory[0].text}`)
        res.end()
        break;
      }
      catch (error) {
        console.error(error);
      }
    }
  }
  catch (error) {
    res.json({
      err: JSON.stringify(error)
    })
  }
  finally {
    res.end()
  }
})


export default routes;

将接口的content-Type设置成application/octet-stream, 是为了不用等到Claude完全解答完再返回给客户端, 可以先返回一些内容, 然后慢慢加载, 这样会增强用户体验感, 同时也能防止接口响应时间太长, 用户一直未得到答案

这里设置一个循环500次, 其实就是为了保证500次之后, 能够返回完整的数据, 当然如果提前结束了,就会break退出循环.

Claude Client

我这里是一个vue+vite项目, 核心请求接口代码如下:

async function onConversation() {
  let message = prompt.value

  if (loading.value)
    return

  if (!message || message.trim() === '')
    return

  controller = new AbortController()


  scrollToBottom()
  addMessage('', false)
  loading.value = true
  prompt.value = ''
  
  try {
    const fetchChatAPIOnce = async () => {
      await fetchCaludeAPIProcess({
        prompt: message,
        onDownloadProgress: ({ event }) => {
          const xhr = event.target
          const { responseText } = xhr
          // Always process the final line
          const lastIndex = responseText.lastIndexOf('⭐', responseText.length - 2)
          let chunk = responseText
          if (lastIndex !== -1) {
            chunk = responseText.substring(lastIndex)
          }
          list.value[list.value.length - 1].message = chunk
          scrollToBottom()
        },
      })
    }
    await fetchChatAPIOnce()
  }
  catch (error: any) {
    const errorMessage = error?.message ?? 'common.wrong'

    if (error.message === 'canceled') {

      scrollToBottomIfAtBottom()
      return
    }
    list.value[list.value.length - 1].message = errorMessage
    console.error(errorMessage)
    scrollToBottomIfAtBottom()
  }
  finally {
    loading.value = false
  }
}

每次都是以⭐开头, 所以我这边就是去取最后一个⭐开头的数据, 然后渲染到页面就可以了

在这里插入图片描述

最终的效果如下:

在这里插入图片描述
最后提供我的线上链接供大家体验一下:
Claude

好了, 今天的分享到这里就结束了, 感谢观看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/535101.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在 Transformers 中使用对比搜索生成可媲美人类水平的文本

1. 引言 自然语言生成 (即文本生成) 是自然语言处理 (NLP) 的核心任务之一。本文将介绍神经网络文本生成领域当前最先进的解码方法 对比搜索 (Contrastive Search)。提出该方法的论文 “A Contrastive Framework for Neural Text Generation” 最初发表于 NeurIPS 2022 ([论文]…

目标检测创新:一种基于区域的半监督方法,部分标签即可(附原论文下载)...

关注并星标 从此不迷路 计算机视觉研究院 公众号ID&#xff5c;ComputerVisionGzq 学习群&#xff5c;扫码在主页获取加入方式 论文地址&#xff1a;https://arxiv.org/pdf/2201.04620v1.pdf 计算机视觉研究院专栏 作者&#xff1a;Edison_G 研究表明&#xff0c;当训练数据缺少…

招募:AICG内容联合创作计划 | AIGC实践

AIGC&#xff08;AI Generated Content&#xff0c;人工智能自动生成内容&#xff09;必将成为小微创业团队进行低成本内容运营的最佳实践。 你同意这个观点吗&#xff1f; 如果我们恰好想法一致&#xff0c;或许可以一起搞点事情&#xff0c;探索一下商业场景下&#xff0c;应…

ChatGPT prompt指令大全

ChatGPT prompt指令大全 更多Prompt自动使用&#xff0c;可以在chrome插件中搜索 WebChatGPT&#xff0c;没有账号的&#xff0c;可以拉到文章最下面。 目录 担任雅思写作考官 写小说 充当 Linux 终端 充当英语翻译和改进者 充当论文润色者&#xff08;拿摘要部分举例&am…

企业实践 | 如何从VMWare ESXi Shell中挂载以及拷贝NTFS或者FAT32分区格式的USB闪存驱动器...

欢迎关注「WeiyiGeek」公众号 点击 &#x1f447; 下方卡片 即可关注我哟! 设为「星标⭐」每天带你 基础入门 到 进阶实践 再到 放弃学习&#xff01; 涉及 网络安全运维、应用开发、物联网IOT、学习路径 、个人感悟 等知识 “ 花开堪折直须折&#xff0c;莫待无花空折枝。 ”…

K_A39_004 基于STM32等单片机驱动AT24C02模块 串口+OLED0.96显示

K_A39_004 基于STM32等单片机驱动AT24C02模块 串口OLED0.96显示 所有资源导航一、资源说明二、基本参数参数引脚说明 三、驱动说明时序对应程序: 四、部分代码说明1、接线引脚定义1.1、STC89C52RCAT24C02模块1.2、STM32F103C8T6AT24C02模块 五、基础知识学习与相关资料下载六、…

〖技术人必学的职业规划白宝书 - 职业规划篇②〗- 进入职场前必须要考虑的问题

历时18个月&#xff0c;采访 850 得到的需求。 不管你是在校大学生、研究生、还是在职的小伙伴&#xff0c;该专栏有你想要的职业规划、简历、面试的答案。说明&#xff1a;该文属于 技术人必学的职业规划白宝书 专栏&#xff0c;购买任意白宝书体系化专栏可加入TFS-CLUB 私域社…

如何优雅的使用各类LLM

近几个月&#xff0c;随着ChatGPT的风靡&#xff0c;大型语言预训练模型也如雨后春笋般地涌现&#xff0c;虽然效果差强人意&#xff0c;好在不受限制。配置稍好的电脑也能跑个7B、13B参数的大语言模型。 虽然模型众多&#xff0c;但是如果给每一个模型都单独去配置环境&#x…

Go语言的条件判断和循环语句

目录 【if语句】 if语句的内部变量 if语句的优雅写法 【switch语句】 switch语句的特点 switch语句的表达式类型 switch获取变量类型 x.(type) 【for语句】 for语句的变体 for...range break 和 continue goto for 语句的常见“坑”与避坑方法 Go语言的条件判断有…

数组map用法以及特殊值的情况

数组map用法以及特殊值的情况 一、map用法的说明 map(callbackFn, thisArg); // callbackFn回调函数&#xff0c;thisArg可选 callbackFn是个回调函数&#xff0c;该回调函数的参数按照顺序为element&#xff08;当前正在处理的元素&#xff09;&#xff0c;index&#xff0…

深化企业数据智能应用 用友敢当“急先锋”

面对扑面而来的数字经济时代&#xff0c;一场轰轰烈烈的企业数智化转型正进行得如火如荼。 然而许多企业虽然明知道数智化转型势在必行&#xff0c;但是又担忧自己不具备相关能力。这些企业在数据和智能上面临哪些挑战&#xff1f;如何才能如何加速数智化创新&#xff1f;AIGC和…

人机融合智能与哲学

GPT系列的大型语言模型&#xff08;LLM&#xff09;在初步成功之后&#xff0c;需要人们重新审视图灵的计算理论&#xff0c;重新认识计算的本质和形式&#xff0c;重新思考计算机和计算机理论&#xff0c;以及深入思考计算的家族、广义的计算和计算的哲学等问题。这是因为GPT系…

从面对代码下不去的文章,到DBA群讨论

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…

小米加速技术突破,为充电生态赋能,领航未来

5月13日&#xff0c;中国电工技术学会电力电子专业委员会第十八届学术年会在上海召开。小米公司作为快充技术领域代表&#xff0c;手机部基带总监杨玉巍出席本次年会并发表以《小米下一个十年的“助推器”——硬件技术创新与应用》为主题的报告&#xff0c;介绍小米最新的充电技…

简单做一下 银川第九届数模A题

A题 随着三年新冠疫情结束后第一个五一假期的到来&#xff0c;许多人选择出门旅游&#xff0c;在有限的几天假期怎样玩好就是一件值得考虑的事。小明是一位旅游爱好者&#xff0c;想在五一期间到宁夏一些著名景点旅游。由于跟着旅游团会受到若干限制&#xff0c;所以他&#xf…

Google Bard 对战 ChatGPT4

话题之一&#xff1a;如何降低血压 我家老爷子血压有点高&#xff0c;所以我挑了这么个话题。 如果用中文来问 Bard, 有点欺负它&#xff0c;那么索性用英文 1. Bard 在速度上占有绝对优势 2. GPT4 在最后一条监测就医建议上&#xff0c;完胜。 很多老人得过且过&#xff0c;不…

OpenCV实战(24)——相机姿态估计

OpenCV实战&#xff08;24&#xff09;——相机姿态估计 0. 前言1. 相机姿态估计2. 3D 可视化模块 cv::Viz3. 完整代码小结系列链接 0. 前言 校准相机后&#xff0c;就可以将捕获的图像与物理世界联系起来。如果物体的 3D 结构是已知的&#xff0c;那么就可以预测物体如何投影…

【Shell脚本】Linux安装Nexus的两种方式以及开机自启

目录 一、Linux安装Nexus的两种方式1、直接把下载好的安装包上传到服务器①、打开Nexus页面后&#xff0c;登录时会出现以下提示&#xff0c;根据路径提示可找到初始密码②、找到初始登录Nexus的初始密码 2、通过wget安装Nexus①、修改Nexus端口号②、默认的端口号为8081&#…

华为OD机试真题 Java 实现【找数字】【2023Q2 100分】

一、题目描述 给一个二维数组nums&#xff0c;对于每一个元素nums[i]&#xff0c;找出距离最近的且值相等的元素&#xff0c;输出横纵坐标差值的绝对值之和&#xff0c;如果没有等值元素&#xff0c;则输出-1。 例如 输入数组nums为 0 3 5 4 2 2 5 7 8 3 2 5 4 2 4 对于 n…

Java每日一练(20230517) 重复元素、链表重复元素、旋转数组

目录 1. 存在重复元素 &#x1f31f; 2. 删除排序链表中的重复元素 &#x1f31f; 3. 旋转数组 &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 存在重…