接著第四篇文章,由於不知道寫什麼,剛好群裡看到有人提到如何在其他地方進行 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 工作空間裡的私有知識庫的數據調用。