接着第四篇文章,由于不知道写什么,刚好群里看到有人提到如何在其他地方进行 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 的内容为:
{
"message": "你好,你是什么大模型",
"mode": "chat"
}
最后点击执行
如图所示:
稍等片刻我们就能看到了回答内容
这里,我们都是在做测试这个 api 能否正常使用。
那么如何我们在别的地方进行调用呢?
假设,我们在某个网页里进行调用。
这个就需要用到了 node+html 了
由于是测试,所以我就直接给出我的 demo 代码
main.js
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
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AnythingLLM 聊天</title>
<style>
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;
}
</style>
</head>
<body>
<div class="chat-container">
<div class="settings-container">
<input type="text" id="auth-input" class="auth-input" placeholder="输入授权码..." value="E8HX1PF-BWT4ZZM-KW8VGRH-9W0QS1B" />
<button id="save-auth-button" class="save-auth-button">保存授权码</button>
</div>
<div class="chat-messages" id="chat-messages"></div>
<div class="input-container">
<input type="text" id="message-input" placeholder="输入消息..." />
<button id="send-button" class="action-button">发送</button>
<button id="stop-button" class="action-button" disabled>停止</button>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="main.js"></script>
</body>
</html>
这两个文件可以在 cs 下直接可以写入
目录结构如下:
之后在终端,运行,我简单的用 python 来提供 web 服务端口是 8089,回车,nginx nodejs 都可以。
python3 -m http.server 8089
点击打开浏览器
粘贴我们之前新建的 key 密钥,点击保存
在对话框输入我们的问题
看看回答如何
到这里,我们就已经调用了我们之前在 demo 工作空间里的私有知识库的数据调用。