Open leechiuhui opened 2 days ago
work on #12 加上AiView.vue和更改App.vue index.ts後,造成HomeView.vue的搜尋出不來關鍵字和相關文件了。
但是試了很多次,好像關掉 vursor ,重新從 github 開啟 desktop下載程式碼,重新 yarn dev,則首頁的搜尋產生關鍵字功能又可以出現了http://localhost:5174/ ⭕️
http://localhost:5175/ ⭕️ http://localhost:5176/ ❌
目前猜想是port的關係
猜想完全正確 因為在backend的部份的CORS頭只有寫
// CORS 頭
const allowedOrigins = [
'https://knowledge-base-frontend.pages.dev',
'https://knowledge-base-backend.leechiuhui.workers.dev',
'https://chihching.org',
'http://localhost:8787',
'http://localhost:5173',
'http://localhost:5174',
'http://localhost:5175'
];
如果要讓更多port可以跑,只要新增例如'http://localhost:5176'到串列中即可~
猜想完全正確 因為在backend的部份的CORS頭只有寫
// CORS 頭 const allowedOrigins = [ 'https://knowledge-base-frontend.pages.dev', 'https://knowledge-base-backend.leechiuhui.workers.dev', 'https://chihching.org', 'http://localhost:8787', 'http://localhost:5173', 'http://localhost:5174', 'http://localhost:5175' ];
如果要讓更多port可以跑,只要新增例如'http://localhost:5176'到串列中即可~
十分鐘前已經修改backend的部份的CORS頭,增加了
'http://localhost:5176',
'http://localhost:5177',
'http://localhost:5178',
'http://localhost:5179',
'http://localhost:5180',
'http://localhost:5181',
'http://localhost:5182',
'http://localhost:5183',
'http://localhost:5184',
https://knowledge-base-frontend.pages.dev/ai
@bestian Good Morning teacher,請問接下來我是不是要設定 worker的Vectorize索引?或是目前在我還沒有設定Vectorize索引前,上面截圖中的AI知識庫對話,請問它是在哪裡挖資料?
@leechiuhui 對,要先建立Vectorize的索引,
還要整批對R2的檔案建立對應的向量(可參考members-backend中的/vecortize/setup相關的邏輯)
再修改backend的279~289行的邏輯
目前的針對 /ai/{prompt} 的回應是直接把對話丟給 @cf/meta/llama-3.1-8b-instruct 去生成回答,這部份要改成去索引找最相關的資料來生成問答
// 如果路徑為 /ai/{prompt},則執行 AI 模型的邏輯
if (url.pathname === "/ai" || url.pathname.startsWith("/ai/")) {
const prompt = decodeURIComponent(url.pathname.slice(4)); // 提取並解碼 prompt
const response = await env.MY_AI_MODEL.run("@cf/meta/llama-3.1-8b-instruct", {
prompt: prompt || "What is the origin of the phrase Hello, World",
});
return new Response(JSON.stringify(response.response), {
headers: { "Content-Type": "application/json", ...responseHeaders },
});
}
可以參考members-backend專案, public_api.js中的相關邏輯(註解掉的部份請忽略)
// 如果路徑是/ai/{prompt}
if (path.match(/^\/ai\/.+$/)) {
// 從路徑中獲取 prompt
const prompt = decodeURIComponent(path.split('/')[2]);
console.log('收到的prompt:', prompt);
// 為了確保程式確實執行到這裡
console.log('=== 開始處理AI請求 ===');
// 使用 Workers AI 生成回答
//const response = await env.AI.run("@cf/meta/llama-3.1-8b-instruct", {
// prompt: prompt,
//});
const embeddings = await env.AI.run("@cf/baai/bge-base-en-v1.5", {
text: '問題:' + prompt,
});
console.log(embeddings.data[0]);
// 使用 Vectorize 索引進行回答
const responses = await env.VECTORIZE.query(embeddings.data[0]);
console.log(responses.matches.map(response => response.score));
var goodResponses = responses.matches.filter(response => response.score > 0.85);
console.log(goodResponses);
if (goodResponses.length === 0) {
console.log('使用字串比對');
// 對D1使用字串比對
const { results, success, error } = await env.DB.prepare("SELECT * FROM Faq").all();
// 計算兩個字串的重疊字數
function calculateOverlap(str1, str2) {
let count = 0;
for (let i = 0; i < str1.length; i++) {
if (str2.includes(str1[i])) {
count++;
}
}
return count;
}
// 根據重疊字數排序
goodResponses = results
.sort((a, b) => {
const overlapA = calculateOverlap(prompt, a.question);
const overlapB = calculateOverlap(prompt, b.question);
return overlapB - overlapA; // 降序排列
});
console.log(goodResponses);
return new Response(JSON.stringify(goodResponses[0].answer), {
headers: {
'Content-Type': 'application/json; charset=utf-8',
...corsHeaders,
},
});
}
var prompt_arr = [];
for (const response of goodResponses) {
// 從 DB 中獲取 response.id 的資料
const { results, success, error } = await env.DB.prepare("SELECT * FROM Faq WHERE id = ?").bind(response.id).all();
prompt_arr.push(results[0]);
}
console.log(prompt_arr);
// const category_order = ['起步', '計畫', '支持', '資源', '其他'];
// prompt_arr.sort((a, b) => category_order.indexOf(a.category) - category_order.indexOf(b.category));
if (prompt_arr.length === 1) {
let answer = prompt_arr[0].answer;
return new Response(answer, {
headers: {
'Content-Type': 'application/json; charset=utf-8',
...corsHeaders,
},
});
} else {
const prompt_new = prompt_arr.map(item => item.answer).join('\n');
console.log(prompt_new);
const response = await env.AI.run("@hf/thebloke/neural-chat-7b-v3-1-awq", {
messages: [
{
role: "system",
content: "請用正體中文把以下內容整理出來,重點整理,不要有廢話,如果有內容是關於時程、數字或流程的請一定要保留。"
},
{
role: "user",
content: prompt_new
}
]
});
// const response = responses.matches[0];
// 確保response.response的結尾是「。」,並移除最後一個句點後的所有內容
var arr = response.response.split('。');
if (arr.length > 2) {
arr.pop();
}
const formattedResponse = arr.join('。\n') + '。';
console.log(formattedResponse);
//console.log(response.id);
//console.log(response.score);
// 從 DB 中獲取 response.id 的資料
//const { results, success, error } = await env.DB.prepare("SELECT * FROM Faq WHERE id = ?").bind(response.id).all();
//if (!success) {
// throw new Error(error);
//}
//console.log(results);
//console.log(results[0].answer);
return new Response(formattedResponse, {
headers: {
'Content-Type': 'application/json; charset=utf-8',
...corsHeaders,
},
});
}
}
@bestian 感謝老師的指導!目前倫敦這邊已經是晚上了,先行告退,明天會繼續努力建立Vectorize的索引💪,並研讀 unischool/knowledge-base-backend#19 中各個任務的不同功能。
瞭解Vecortize向量索引資料庫的運作邏輯 https://developers.cloudflare.com/vectorize/ https://developers.cloudflare.com/vectorize/get-started/intro/ https://developers.cloudflare.com/vectorize/tutorials/
建立Vecortize向量索引資料庫 https://dash.cloudflare.com/54a327f11ec193522723b4cb437303e2/ai/vectorize
將R2上的檔案以AI解析,生成關鍵字並存入Vecortize向量索引資料庫 將所有關鍵字存入D1一般資料庫 將所有R2檔案和關鍵字的配對存入D1一般資料庫 建立/api/keywordsWithFiles 建立/vector_search/{keyword}的API 用於建立/vector_search/{keyword} 的 API
【模仿】https://github.com/3dw/start-learn/issues/10 和 https://members-frontend.pages.dev/ 【實驗】使用CloudFlare Vectorize來製作[創源工具資料]問答機器人