由于个人的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.postMessageconst res = await web.chat.postMessage({ channel: conversationId, text: 'Hello there' });// `res` contains information about the posted messageconsole.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.bodyconst ans = await web.chat.postMessage({ channel: conversationId || '', text: prompt});let firstChunk = truefor(let i = 0; i < 500; i++) {try {// Call the conversations.history method using WebClientconst 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 = falsesleep(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.valueif (loading.value)returnif (!message || message.trim() === '')returncontroller = new AbortController()scrollToBottom()addMessage('', false)loading.value = trueprompt.value = ''try {const fetchChatAPIOnce = async () => {await fetchCaludeAPIProcess({prompt: message,onDownloadProgress: ({ event }) => {const xhr = event.targetconst { responseText } = xhr// Always process the final lineconst lastIndex = responseText.lastIndexOf('⭐', responseText.length - 2)let chunk = responseTextif (lastIndex !== -1) {chunk = responseText.substring(lastIndex)}list.value[list.value.length - 1].message = chunkscrollToBottom()},})}await fetchChatAPIOnce()}catch (error: any) {const errorMessage = error?.message ?? 'common.wrong'if (error.message === 'canceled') {scrollToBottomIfAtBottom()return}list.value[list.value.length - 1].message = errorMessageconsole.error(errorMessage)scrollToBottomIfAtBottom()}finally {loading.value = false}
}
每次都是以⭐开头, 所以我这边就是去取最后一个⭐开头的数据, 然后渲染到页面就可以了
最终的效果如下:
最后提供我的线上链接供大家体验一下:
Claude
好了, 今天的分享到这里就结束了, 感谢观看!