来羊毛啦，腾讯云Cloud Studio大羊毛！！！五

接着第四篇文章，由于不知道写什么，刚好群里看到有人提到如何在其他地方进行 anythingllm 的 api 调用，故此才会出现本篇博文，只做为技术学习使用。更多的应用方式详看 anythingllm 的 api 文档。

现在我们用利用 cloud stduio 搭建的私人知识库搭建了知识库，我们该如何在其他地方进行调用呢，或者说能否提供一个 api 让让我们进行使用？
anythingllm 其实提供了 api，但是需要稍微懂一点编程能力，才能用到这个，毕竟如果有了 api，那就意味着我们可以早任意项目下进行使用，毕竟投喂的数据，是要用起来的，并且是想在哪里用就在哪里用，而不能仅仅是在 anythingllm 下使用。

好了，话不多，开始教程。

现在我们已经通过第四篇的文章已经给 deepseek 投喂了数据，那我们该如何通过 api 来使用呢？

打开 anythingllm 的设置界面【小扳手图标】。

左侧菜单划动，选择工具 --->api 密钥

点击生成新的 api 密钥，会出现新的弹框，我们 create apikey

之后依次点击 copy key 和 read the api doc，

在打开的 AnythingLLM Developer API 页面，我们点击Authorize, 粘贴我们刚刚 copy 的 apikey

关闭弹窗

下滑找到 Workspaces 分组下的 /v1/workspace/{slug}/stream-chat，并点击

点击 try out 按钮，并修改 slug 的值，slug 的值就是我们当初新建的工作区的名称，

看图：工作区

我这里的值是 demo

并修改 Request body 的内容为：

Copy
{
"message": "你好，你是什么大模型",
"mode": "chat"
}

最后点击执行
如图所示：

稍等片刻我们就能看到了回答内容

这里，我们都是在做测试这个 api 能否正常使用。
那么如何我们在别的地方进行调用呢？
假设，我们在某个网页里进行调用。

这个就需要用到了 node+html 了
由于是测试，所以我就直接给出我的 demo 代码
main.js

Copy
document.addEventListener('DOMContentLoaded', () => {
const messageInput = document.getElementById('message-input');
const sendButton = document.getElementById('send-button');
const stopButton = document.getElementById('stop-button');
const chatMessages = document.getElementById('chat-messages');
const authInput = document.getElementById('auth-input');
const saveAuthButton = document.getElementById('save-auth-button');

let currentController = null;

function addMessage(message, isUser = false) {
const messageElement = document.createElement('div');
messageElement.classList.add('message');
messageElement.classList.add(isUser ? 'user-message' : 'bot-message');
messageElement.textContent = message;
chatMessages.appendChild(messageElement);
chatMessages.scrollTop = chatMessages.scrollHeight;
}

function setLoading(isLoading) {
sendButton.disabled = isLoading;
messageInput.disabled = isLoading;
stopButton.disabled = !isLoading;
sendButton.textContent = isLoading ? '发送中...' : '发送';
}

async function typeText(element, text) {
const delay = 20; // 每个字符的延迟时间（毫秒）
for (let i = 0; i < text.length; i++) {
const char = text[i];
const span = document.createElement('span');
span.textContent = char;
span.classList.add('typing');
element.appendChild(span);
await new Promise(resolve => setTimeout(resolve, delay));
}
}

async function sendMessage(message) {
try {
setLoading(true);
currentController = new AbortController();
const response = await fetch('https://ottzkl-pkzulq-3001.app.cloudstudio.work/api/v1/workspace/demo/stream-chat', {
method: 'POST',
headers: {
'accept': 'text/event-stream',
'Authorization': `Bearer ${authInput.value}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
message: message,
mode: 'chat'
}),
signal: currentController.signal
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const reader = response.body.getReader();
const decoder = new TextDecoder();
let currentMessageElement = null;
let buffer = '';

while (true) {
const {value, done} = await reader.read();
if (done) break;

const chunk = decoder.decode(value, {stream: true});
buffer += chunk;

let startIndex = 0;
while (true) {
const endIndex = buffer.indexOf('\n', startIndex);
if (endIndex === -1) break;

const line = buffer.slice(startIndex, endIndex).trim();
startIndex = endIndex + 1;

if (line.startsWith('data:')) {
try {
const jsonStr = line.substring(5).trim();
if (!jsonStr) continue;

const data = JSON.parse(jsonStr);
if (data.textResponse !== undefined) {
if (!currentMessageElement) {
currentMessageElement = document.createElement('div');
currentMessageElement.classList.add('message', 'bot-message');
chatMessages.appendChild(currentMessageElement);
}

await typeText(currentMessageElement, data.textResponse);
chatMessages.scrollTop = chatMessages.scrollHeight;
} else if (data.error) {
throw new Error(data.error);
}
} catch (e) {
console.error('解析响应数据时出错:', e);
}
}
}
buffer = buffer.slice(startIndex);
}
} catch (error) {
if (error.name === 'AbortError') {
addMessage('对话已停止', false);
} else {
console.error('Error:', error);
let errorMessage = '抱歉，发生了错误';
if (error.response) {
errorMessage += `（HTTP ${error.response.status}）`;
} else if (error.request) {
errorMessage += '（网络连接失败）';
} else {
errorMessage += `（${error.message}）`;
}
addMessage(errorMessage, false);
}
} finally {
currentController = null;
setLoading(false);
}
}

stopButton.addEventListener('click', () => {
if (currentController) {
currentController.abort();
}
});

saveAuthButton.addEventListener('click', () => {
const authValue = authInput.value.trim();
if (authValue) {
addMessage('授权码已更新', false);
} else {
addMessage('请输入有效的授权码', false);
}
});

sendButton.addEventListener('click', () => {
const message = messageInput.value.trim();
if (message) {
addMessage(message, true);
messageInput.value = '';
sendMessage(message);
}
});

messageInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendButton.click();
}
});

// 添加欢迎消息
addMessage('你好！我是AI助手，请问有什么可以帮你？', false);
});

index.html

Copy





AnythingLLM 聊天

body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
}
.chat-container {
max-width: 800px;
margin: 0 auto;
background-color: white;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
display: flex;
flex-direction: column;
height: 90vh;
}
.settings-container {
padding: 10px 20px;
border-bottom: 1px solid #dee2e6;
display: flex;
gap: 10px;
align-items: center;
}
.auth-input {
flex-grow: 1;
padding: 8px;
border: 1px solid #dee2e6;
border-radius: 5px;
font-size: 14px;
}
.save-auth-button {
padding: 8px 15px;
background-color: #28a745;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
}
.save-auth-button:hover {
background-color: #218838;
}
.chat-messages {
flex-grow: 1;
overflow-y: auto;
padding: 20px;
}
.message {
margin-bottom: 15px;
padding: 10px 15px;
border-radius: 15px;
max-width: 70%;
animation: fadeIn 0.3s ease-in-out;
word-wrap: break-word;
}
.user-message {
background-color: #007bff;
color: white;
margin-left: auto;
}
.bot-message {
background-color: #e9ecef;
color: black;
margin-right: auto;
}
.typing {
display: inline-block;
overflow: hidden;
white-space: pre-wrap;
animation: typing 0.05s steps(1, end);
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes typing {
from { width: 0; }
to { width: 100%; }
}
.input-container {
padding: 20px;
border-top: 1px solid #dee2e6;
display: flex;
gap: 10px;
}
#message-input {
flex-grow: 1;
padding: 10px;
border: 1px solid #dee2e6;
border-radius: 5px;
font-size: 16px;
}
.action-button {
padding: 10px 20px;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
#send-button {
background-color: #007bff;
}
#stop-button {
background-color: #dc3545;
}
#send-button:hover {
background-color: #0056b3;
}
#stop-button:hover {
background-color: #c82333;
}
#stop-button:disabled {
background-color: #6c757d;
cursor: not-allowed;
}






保存授权码




发送
停止







这两个文件可以在 cs 下直接可以写入
目录结构如下：

之后在终端，运行，我简单的用 python 来提供 web 服务端口是 8089，回车，nginx nodejs 都可以。

Copy
python3 -m http.server 8089

点击打开浏览器

粘贴我们之前新建的 key 密钥，点击保存

在对话框输入我们的问题
看看回答如何

到这里，我们就已经调用了我们之前在 demo 工作空间里的私有知识库的数据调用。