akasha使用手冊

akasha manual

ask_agent

如果你想詢問較複雜的問題,使用ask_agent,語言模型會將你的問題拆解來提供較好的回答。

example

1
2
3
4
5
6
7
8
9
10
ak = akasha.Doc_QA(
verbose=True,
chunk_size=500,
model="openai:gpt-3.5-turbo",
)
res = ak.ask_agent(
"./docs/mic/",
"LPWAN和5G的區別是什麼?",
)

1
2
3
4
5
6
7
8
LPWAN和5G的主要區別在於他們的頻寬、延遲、成本和應用場景。

LPWAN的頻寬相對較低(0.3 KBps – 50KBps),延遲較高(秒 - 分),且成本較低。它的主要優點是低耗能、支援長距離傳輸,並且可以連接大量的設備。然而,由於其頻寬和延遲的限制,LPWAN在製造業中的
應用主要適用於非即時、非關鍵性的應用,例如環境污染偵測、照明、人員移動等,且須長時間穩定使用的應用情境。

相較之下,5G提供的頻寬範圍在1-10 Gbps,而延遲則在1-10 ms之間,成本較高。這使得5G非常適合需要高時序精密度的應用,例如異質設備協作、遠端操控、混合現實(MR)巡檢維修等。此外,5G網路在大型
廠區中,相較於Wi-Fi,無移交控制(Handover)中斷問題,因此更適合如低延遲、快速移動型的自主移動機器人(AMR)或無人機(Drone)廣域應用。然而,5G私網的建置成本相對昂貴,可能會影響企業的導
入意願。
self.model_obj的詳細資訊可參考語言模型
self.embeddings_obj的詳細資訊可參考[文件搜尋]嵌入模型

自動產生問題

如果您不想自己創建問題集來評估當前參數的性能,您可以使用 eval.auto_create_questionset 功能自動生成一個包含參考答案的問題集。隨後,您可以使用 eval.auto_evaluation 獲取評估指標,如 Bert_score、Rouge 和 LLM_score(對於問答問題集),以及單選問題集的正確率。這些分數範圍從 0 到 1,較高的值表示生成的回答與參考答案更接近。

如範例,以下創建了一個名為 ‘mic_essay.txt’ 的問題集文本文件,其中包含十個問題和參考答案。每個問題都是從 ‘doc/mic/‘ 目錄中給定文檔的內容段落中隨機生成的。然後,您可以使用該問題集文本文件來評估要測試的參數的性能。

1
2
3
4
5
6
7
8
9
import akasha.eval as eval

eva = eval.Model_Eval(question_style="essay", search_type='merge',\
model="openai:gpt-3.5-turbo", embeddings="openai:text-embedding-ada-002",record_exp="exp_mic_auto_questionset")

eva.auto_create_questionset(doc_path="doc/mic/", question_num=10, output_file_path="questionset/mic_essay.txt")

bert_score, rouge, llm_score, tol_tokens = eva.auto_evaluation(questionset_file="questionset/mic_essay.txt", doc_path="doc/mic/", question_style = "essay", record_exp="exp_mic_auto_evaluation",topK=3,search_type="svm")
print("bert_score: ", bert_score, "\nrouge: ", rouge, "\nllm_score: ", llm_score)
1
2
3
bert_score: 0.782
rouge: 0.81
llm_score: 0.393


使用question_type測試不同方面的能力

question_type 参数提供了四種問題類型:factsummaryirrelevantcompared,預設是 fact。

  1. fact測試回答一般事實的能力
  2. summary測試模型做摘要的能力
  3. irrelevant測試模型能否分辨文件中不存在答案的問題
  4. compared測試模型比較不同事物的能力

範例

1
2
3
4
5
6
7
import akasha.eval as eval

eva = eval.Model_Eval(search_type='merge', question_type = "irrelevant", model="openai:gpt-3.5-turbo", record_exp="exp_mic_auto_questionset")

eva.auto_create_questionset(doc_path="doc/mic/", question_num=10, output_file_path="questionset/mic_irre.txt")

bert_score, rouge, llm_score, tol_tokens = eva.auto_evaluation(questionset_file="questionset/mic_irre.txt", doc_path="doc/mic/", question_style = "essay", record_exp="exp_mic_auto_evaluation",search_type="svm")


指定問題集主題

如果你想生成特定主題的問題,你可以使用 create_topic_questionset 函數,它會使用輸入的主題在文檔中找到相關的文件段落並生成問題集。

範例

1
2
3
4
5
6
7
import akasha.eval as eval

eva = eval.Model_Eval(search_type='merge',question_type = "irrelevant", model="openai:gpt-3.5-turbo", record_exp="exp_mic_auto_questionset")

eva.create_topic_questionset(doc_path="doc/mic/", topic= "工業4.0", question_num=3, output_file_path="questionset/mic_topic_irre.txt")

bert_score, rouge, llm_score, tol_tokens = eva.auto_evaluation(questionset_file="questionset/mic_topic_irre.txt", doc_path="doc/mic/", question_style = "essay", record_exp="exp_mic_auto_evaluation",search_type="svm")
self.db的詳細資訊可參考向量資料庫
self.model_obj的詳細資訊可參考語言模型

Auto Evaluation

若要測試各種參數對語言模型回答的好壞,可以使用auto_evalution函數。首先,您需要基於您要使用的文檔構建一個問題集(.txt)。
您可以生成單選題文件或問答題文件。

  1. 對於單選題文件,每個選項和正確答案之間用制表符(\t)分隔,每行是一個問題,如範例:
    1
    2
    3
    應回收廢塑膠容器材質種類不包含哪種?	1.聚丙烯(PP)	2.聚苯乙烯(PS)	3.聚氯乙烯(PVC)	4.低密度聚乙烯(LDPE)	4
    庫存盤點包括庫存全盤作業及不定期抽盤作業,盤點計畫應包括下列項目不包含哪項? 1.盤點差異之處理 2.盤點清冊 3.各項物品存放區域配置圖 4.庫存全盤日期及參加盤點人員名單 1
    以下何者不是環保署指定之公民營地磅機構? 1.中森加油站企業有限公司 2.台益地磅站 3.大眾地磅站 4.新福行 4
    函式將返回問題集的正確率和使用的token量,每個問題的詳細內容儲存在logs中。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import akasha.eval as eval
    import os
    import akasha
    dir_path = "doc/pvc/"
    exp_name = "exp_akasha_auto_evaluation"

    eva = eval.Model_Eval(question_style="single_choice", search_type='merge',\
    model="openai:gpt-3.5-turbo", embeddings="openai:text-embedding-ada-002",record_exp=exp_name)
    print(eva.auto_evaluation("question_pvc.txt", dir_path ))
    ## correct rate: 0.9, tokens: 3228 ##
  2. 對於問答題文件,每個問題之前有 “問題:”,每個參考答案之前有 “答案:”。每個問題之間用兩個換行符 (\n\n) 分隔。
    問答題類的問題文件,會回傳bert的平均分數, rouge的平均分數, llm_score的平均分數, 文件使用的總token數量
    1
    2
    3
    4
    5
    6
    問題:根據文件中的訊息,智慧製造的複雜性已超越系統整合商的負荷程度,未來產業鏈中的角色將傾向朝共和共榮共創智慧製造商機,而非過往的單打獨鬥模式發展。請問為什麼  供  應商、電信商、軟體開發商、平台商、雲端服務供應商、系統整合商等角色會傾向朝共和共榮共創智慧製造商機的方向發展?
    答案:因為智慧製造的複雜性已超越系統整合商的負荷程度,單一角色難以完成整個智慧製造的需求,而共和共榮共創的模式可以整合各方的優勢,共同創造智慧製造的商機。

    問題:根據文件中提到的資訊技術商(IT)和營運技術商(OT),請列舉至少兩個邊緣運算產品或解決方案。
    答案:根據文件中的資訊,NVIDIA的邊緣運算產品包括Jetson系列和EGX系列,而IBM的邊緣運算產品包括IBM Edge Application Manager和IBM Watson Anywhere。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import akasha.eval as eval
    import os
    import akasha
    dir_path = "doc/pvc/"
    exp_name = "exp_akasha_auto_evaluation"

    eva = eval.Model_Eval(question_style="essay", search_type='merge',\
    model="openai:gpt-3.5-turbo")
    print(eva.auto_evaluation("question_pvc_essay.txt", dir_path ))
    ## correct rate: 0.9, tokens: 3228 ##

Scores

對於問答題文件,因為無法準確判別語言模型的回答是否正確,我們使用bert_score, rouge_score, llm_score,藉由比較語言模型的回答與問答題文件中的參考答案,來得出0~1之間的分數

bert-score

使用bert-score套件計算回答與參考答案的每個token之間的contextual embeddings similarity.

1
2
3
4
5
6
7
8
9
10
import akasha
from akasha.eval.scores import get_bert_score


llm_output = "「五軸」指的是在機械加工或製造過程中使用的五軸數控(CNC)機床。這些機床可以在五個不同的軸上同時移動和旋轉工件或刀具,讓加工變得更靈活與精確。五軸機床一般包含三個直線軸(X、Y、Z)和兩個旋轉軸(A、B),這樣設計的目的是讓機床能從多個角度對工件進行加工,而不必在不同的角度之間反覆夾持和移動工件。"

ref_ans = "根據文件中提到的內容,5軸工具機相較於3軸工具機能夠進行複雜形狀加工,並在加工精密度、自動化方面佔據優勢。"


score = get_bert_score(llm_output, ref_ans)

ROUGE-score

將語言模型的回答與問答題文件中的參考答案進行分詞後,藉由ROUGE 評估生成相似度分數

1
2
3
4
5
6
7
8
9
10
import akasha
from akasha.eval.scores import get_rouge_score


llm_output = "「五軸」指的是在機械加工或製造過程中使用的五軸數控(CNC)機床。這些機床可以在五個不同的軸上同時移動和旋轉工件或刀具,讓加工變得更靈活與精確。五軸機床一般包含三個直線軸(X、Y、Z)和兩個旋轉軸(A、B),這樣設計的目的是讓機床能從多個角度對工件進行加工,而不必在不同的角度之間反覆夾持和移動工件。"

ref_ans = "根據文件中提到的內容,5軸工具機相較於3軸工具機能夠進行複雜形狀加工,並在加工精密度、自動化方面佔據優勢。"


score = get_rouge_score(llm_output, ref_ans)

llm-score

利用另一種語言模型,將語言模型的回答與問答題文件中的參考答案進行比較,生成相似度分數

1
2
3
4
5
6
7
8
9
10
11
import akasha
from akasha.eval.scores import get_llm_score


llm_output = "「五軸」指的是在機械加工或製造過程中使用的五軸數控(CNC)機床。這些機床可以在五個不同的軸上同時移動和旋轉工件或刀具,讓加工變得更靈活與精確。五軸機床一般包含三個直線軸(X、Y、Z)和兩個旋轉軸(A、B),這樣設計的目的是讓機床能從多個角度對工件進行加工,而不必在不同的角度之間反覆夾持和移動工件。"

ref_ans = "根據文件中提到的內容,5軸工具機相較於3軸工具機能夠進行複雜形狀加工,並在加工精密度、自動化方面佔據優勢。"

model = "openai:gpt-4o"
score = get_llm_score(llm_output, ref_ans, model=model)

Find Optimum Combination

若要測試所有可用的組合並找到最佳參數,您可以使用 optimum_combination 函數。您可以提供不同的嵌入模型、文件段落大小、語言模型、文件搜索方法以及最相關文檔的數量(topK),該函數將測試所有組合以找到根據給定的問題集和文檔的最佳組合。請注意,最佳得分組合是最高正確率組合,而最佳性價比組合是需要最少token以獲得正確答案的組合。

範例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import akasha.eval as eval
import os
from dotenv import load_dotenv
load_dotenv()

os.environ["OPENAI_API_KEY"] = "your openAI key"
os.environ["HF_TOKEN"] = "your huggingface key"
dir_path = "doc/pvc/"
exp_name = "exp_akasha_optimum_combination"
embeddings_list = ["hf:shibing624/text2vec-base-chinese", "openai:text-embedding-ada-002"]
model_list = ["openai:gpt-3.5-turbo","hf:FlagAlpha/Llama2-Chinese-13b-Chat-4bit","hf:meta-llama/Llama-2-7b-chat-hf",\
"llama-gpu:model/llama-2-7b-chat.Q5_K_S.gguf", "llama-gpu:model/llama-2-13b-chat.Q5_K_S.gguf"]

eva = eval.Model_Eval(question_style="single_choice")
eva.optimum_combination("question_pvc.txt", dir_path, embeddings_list = embeddings_list, model_list = model_list,
chunk_size_list=[200, 400, 600], search_type_list=["merge","tfidf",],record_exp=exp_name)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Best correct rate:  1.000
Best score combination:

embeddings: openai:text-embedding-ada-002, chunk size: 400, model: openai:gpt-3.5-turbo, search type: merge



embeddings: openai:text-embedding-ada-002, chunk size: 400, model: openai:gpt-3.5-turbo, search type: tfidf





Best cost-effective:

embeddings: hf:shibing624/text2vec-base-chinese, chunk size: 400, model: openai:gpt-3.5-turbo, search type: tfidf

文件摘要

若要創建文本文件的摘要(.pdf、.txt.、docx),您可以使用 summary.summarize_file 函數。如範例,以下使用 map_reduce 摘要方法指示語言模型生成大約 500 字的摘要。有兩種摘要類型,map_reducerefinemap_reduce 將對每個文本段落進行摘要,然後使用所有摘要的文本段落生成最終摘要;refine 將逐個摘要每個文本段落,並使用前一個摘要作為摘要下一段的提示,以獲得更高水平的摘要一致性。

範例

1
2
3
4
import akasha
sum = akasha.Summary( chunk_size=1000, chunk_overlap=100)
sum.summarize_file(file_path="doc/mic/5軸工具機因應市場訴求改變的發展態勢.pdf",summary_type="map_reduce", summary_len=500\
, chunk_overlap=40)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

### Arguments of Summary class ###
Args:
**chunk_size (int, optional)**: chunk size of texts from documents. Defaults to 1000.
**chunk_overlap (int, optional)**: chunk overlap of texts from documents. Defaults to 40.
**model (str, optional)**: llm model to use. Defaults to "gpt-3.5-turbo".
**verbose (bool, optional)**: show log texts or not. Defaults to False.
**language (str, optional)**: the language of documents and prompt, use to make sure docs won't exceed
max token size of llm input.
**record_exp (str, optional)**: use aiido to save running params and metrics to the remote mlflow or not if record_exp not empty, and setrecord_exp as experiment name. default "".
**system_prompt (str, optional)**: the system prompt that you assign special instruction to llm model, so will not be used
in searching relevant documents. Defaults to "".
**max_input_tokens(int, optional)**: max token length of llm input. Defaults to 3000.
**temperature (float, optional)**: temperature of llm model from 0.0 to 1.0 . Defaults to 0.0.
**auto_translate (bool, optional)**: translate summary into language or not.
**max_output_tokens (int, optional)**: max output tokens of llm model. Defaults to 1024.
**max_input_tokens (int, optional)**: max input tokens of llm model. Defaults to 3000.
**env_file (str, optional)**: the path of env file. Defaults to "".

選擇不同語言模型

使用參數model便可以選擇不同的語言模型,預設是openai:gpt-3.5-turbo.

範例

1. openai

(請先完成設定 API Key)

1
2
3
4
5
6
7
import akasha

akasha.Doc_QA()
ak.get_response(dir_path,
prompt,
embeddings="openai:text-embedding-ada-002",
model="openai:gpt-3.5-turbo")


2. huggingface

1
2
3
4
5
6
7
import akasha

ak = akasha.Doc_QA()
ak.get_response(dir_path,
prompt,
embeddings="huggingface:all-MiniLM-L6-v2",
model="hf:meta-llama/Llama-2-13b-chat-hf")


3. llama-cpp

安裝llama-cpp-python可以使用cpu推論.gguf格式的模型,或是安裝akasha時選擇llama-cpp

1
2
pip install llama-cpp-python
#pip install akasha-terminal[llama-cpp]

llama-cpp允許使用quantized模型並執行在cpu上,你可以從huggingface上下載.gguf llama-cpp 模型,如範例,如果你的模型下載到”model/“路徑下,可以使用以下方法加載模型

1
2
3
4
5
6
7
import akasha

ak = akasha.Doc_QA()
ak.get_response(dir_path,
prompt,
embeddings="huggingface:all-MiniLM-L6-v2",
model="llama-cpu:model/llama-2-13b-chat.Q5_K_S.gguf")


llama-cpp同樣允許使用gpu運算模型,但安裝套件時需要使用cmake安裝,並確認已安裝g++, gcc和nvidia driver & toolkit,詳細請見llama-cpp-python

1
CMAKE_ARGS="-DGGML_CUDA=on" FORCE_CMAKE=1 python -m pip install --upgrade --force-reinstall llama-cpp-python>=0.3.1 --no-cache-dir


4. 遠端api

如果你使用別人的api或者透過支援openAI api框架的部署自己的模型(例如vllm, TGI, litellm…),你可以使用 remote:{your LLM api url} 來加載模型,若須指定模型名稱,使用 remote:{your LLM api url}@{your model name}

若遠端api需要api金鑰,請先完成設定環境變數 REMOTE_API_KEY ,參考設定 API Key

1
2
3
4
5
6
import akasha

ak = akasha.Doc_QA()
ak.get_response(dir_path,
prompt,
model="remote:http://140.92.60.189:8081@llama-3.2-11B")


5. gemini

(請先完成設定 API Key)

1
2
3
4
5
6
7
import akasha

ak = akasha.Doc_QA()
ak.get_response(dir_path,
prompt,
embeddings="gemini:models/text-embedding-004",
model="gemini:gemini-1.5-flash")


6. anthropic

(請先完成設定 API Key)

1
2
3
4
5
6
import akasha

ak = akasha.Doc_QA()
ak.get_response(dir_path,
prompt,
model="anthropic:claude-3-5-sonnet-20241022")


可使用的模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
openai_model = "openai:gpt-3.5-turbo"  # need environment variable "OPENAI_API_KEY"
gemini_model="gemini:gemini-1.5-flash" # need environment variable "GEMINI_API_KEY"
anthropic_model = "anthropic:claude-3-5-sonnet-20241022" # need environment variable "ANTHROPIC_API_KEY"
huggingface_model = "hf:meta-llama/Llama-2-7b-chat-hf" #need environment variable "HUGGINGFACEHUB_API_TOKEN" to download meta-llama model
quantized_ch_llama_model = "hf:FlagAlpha/Llama2-Chinese-13b-Chat-4bit"
taiwan_llama_gptq = "hf:weiren119/Taiwan-LLaMa-v1.0-4bits-GPTQ"
mistral = "hf:Mistral-7B-Instruct-v0.2"
mediatek_Breeze = "hf:MediaTek-Research/Breeze-7B-Instruct-64k-v0.1"
### If you want to use llama-cpp to run model on cpu, you can download gguf version of models
### from https://huggingface.co/TheBloke/Llama-2-7b-Chat-GGUF and the name behind "llama-gpu:" or "llama-cpu:"
### from https://huggingface.co/TheBloke/CodeUp-Llama-2-13B-Chat-HF-GGUF
### is the path of the downloaded .gguf file
llama_cpp_model = "llama-gpu:model/llama-2-13b-chat-hf.Q5_K_S.gguf"
llama_cpp_model = "llama-cpu:model/llama-2-7b-chat.Q5_K_S.gguf"
llama_cpp_chinese_alpaca = "llama-gpu:model/chinese-alpaca-2-7b.Q5_K_S.gguf"
llama_cpp_chinese_alpaca = "llama-cpu:model/chinese-alpaca-2-13b.Q5_K_M.gguf"
chatglm_model = "chatglm:THUDM/chatglm2-6b"




自訂語言模型

如果你想使用其他模型,可以建立一個輸入是prompt的函數並回傳語言模型的回答,並將此函數作為model參數

example

我們建立一個test_model函數,並可以將它作為參數輸入進get_response回答問題

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import akasha

def test_model(prompt:str):

import openai
from langchain.chat_models import ChatOpenAI
openai.api_type = "open_ai"
model = ChatOpenAI(model="gpt-3.5-turbo", temperature = 0)
ret = model.predict(prompt)

return ret

doc_path = "./mic/"
prompt = "五軸是什麼?"

qa = akasha.Doc_QA(verbose=True, search_type = "svm", model = test_model)
qa.get_response(doc_path= doc_path, prompt = prompt)




建立LLM物件

以上使用model參數選擇模型後,便會在Doc_QA物件內建立模型的物件model_obj(LLM)

1
2
3
4
5
6
import akasha

AK = akasha.Doc_QA(model="openai:gpt-3.5-turbo")

print(type(AK.model_obj))



也可以使用輔助函數建立LLM物件

1
2
3
4
5
6
import akasha

model_obj = akasha.handle_model("openai:gpt-3.5-turbo",verbose=False,temperature=0.0)

print(type(model_obj))



此LLM物件也可直接傳入Doc_QA,避免重複宣告

1
2
3
4
5
6
import akasha

model_obj = akasha.handle_model("openai:gpt-3.5-turbo",verbose=False,temperature=0.0)

AK = Doc_QA(model=model_obj)

直接使用LLM物件

取得模型類別

使用_llm_type()可取得語言模型的類別

1
2
3
4
5
6
import akasha

model_obj = akasha.handle_model("gemini:gemini-1.5-flash",verbose=False,temperature=0.0)

print(model_obj._llm_type()) ## "gemini:gemini-1.5-flash"

模型推論

若要使用語言模型進行推論,可以使用函式call_model

1
2
3
4
5
6
7
8
9
import akasha
system_prompt = "用中文回答"
prompt = "五軸是什麼?"
model_obj = akasha.handle_model("openai:gpt-e3.5-turbo", False, 0.0)
input_text = akasha.prompts.format_sys_prompt(system_prompt, prompt, "gpt")

response = akasha.call_model(model_obj, input_text)




流輸出

若要呼叫語言模型即時回答,可以使用函式call_stream_model

1
2
3
4
5
6
7
8
9
10
11
12
import akasha

system_prompt = "用中文回答"
prompt = "五軸是什麼?"
model_obj = akasha.handle_model("openai:gpt-e3.5-turbo", False, 0.0)
input_text = akasha.prompts.format_sys_prompt(system_prompt, prompt, "gpt")

streaming = akasha.call_stream_model(model_obj, input_text)

for s in streaming:
print(s)



批量推論

如果你有大量不需要連貫的推理需求,可以使用akasha.helper.call_batch_model 來進行批量推理來提升速度。

1
2
def call_batch_model(model: LLM, prompt: List[str], 
system_prompt: Union[List[str], str] = "") -> List[str]:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import akasha

model_obj = akasha.helper.handle_model("openai:gpt-3.5-turbo", False, 0.0)
# this prompt ask LLM to response 'yes' or 'no' if the document segment is relevant to the user question or not.
SYSTEM_PROMPT = akasha.prompts.default_doc_grader_prompt()
documents = ["Doc1...", "Doc2...", "Doc3...", "Doc4..."]
question = "五軸是什麼?"

prompts = ["document: " + doc +"\n\n" + "User Question: "+ question for doc in documents]

response_list = call_batch_model(model_obj, prompt, SYSTEM_PROMPT)

## ["yes", "no", "yes", "yes"]



選擇不同嵌入模型

使用參數embeddings便可以選擇不同的嵌入模型,預設是openai:text-embedding-ada-002.

範例

1. openai

(請先完成設定 API Key)

1
2
3
4
import akasha

akasha.Doc_QA()
ak.get_response(dir_path, prompt, embeddings="openai:text-embedding-ada-002",)


2. huggingface

1
2
3
4
import akasha

ak = akasha.Doc_QA(embeddings="huggingface:all-MiniLM-L6-v2")
resposne = ak.get_response(dir_path, prompt)


3. gemini

(請先完成設定 API Key)

1
2
3
4
5
6
7
import akasha

akasha.Doc_QA()
ak.get_response(dir_path,
prompt,
embeddings="gemini:models/text-embedding-004",
model="gemini:gemini-1.5-flash")


可使用的模型

每個嵌入模型都有max sequence length,超過的話後面的文字就會被截斷,不會拿進去做嵌入。

1
2
3
4
5
6
7
8
9
openai_emb = "openai:text-embedding-ada-002"  # need environment variable "OPENAI_API_KEY"  # 8192 max seq length
openai_3l_emb = "openai:text-embedding-3-large"
openai_3s_emb = "openai:text-embedding-3-small"
gemini_emb = "gemini:models/text-embedding-004"
huggingface_emb = "hf:all-MiniLM-L6-v2"
alibaba_bge_emb = "hf:Alibaba-NLP/gte-multilingual-base" #8192 max seq length
bge_en_emb = "hf:BAAI/bge-base-en-v1.5" # 512 max seq length
bge_ch_emb = "hf:BAAI/bge-base-zh-v1.5" # 512 max seq length





自訂嵌入模型

如果你想使用其他模型,可以建立一個輸入是texts:list的函數,代表的是文件庫中所有分割好的文字段落,此函數需回傳embedding之後每段文字的向量,並將此函數作為embeddings參數

example

我們建立一個test_embed函數,並可以將它作為參數輸入進get_response回答問題

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import akasha

def test_embed(texts:list)->list:

from sentence_transformers import SentenceTransformer
mdl = SentenceTransformer('BAAI/bge-large-zh-v1.5')
embeds = mdl.encode(texts,normalize_embeddings=True)


return embeds

doc_path = "./mic/"
prompt = "五軸是什麼?"

qa = akasha.Doc_QA(verbose=True, search_type = "svm", embeddings = test_embed)
qa.get_response(doc_path= doc_path, prompt = prompt)

建立Embeddings物件

以上使用embeddings參數選擇模型後,便會在Doc_QA物件內建立模型的物件embeddings_obj(Embeddings)

1
2
3
4
5
6
import akasha

AK = akasha.Doc_QA(embeddings="openai:text-embedding-ada-002")

print(type(AK.embeddings_obj))



也可以使用輔助函數建立Embeddings物件

1
2
3
4
5
6
import akasha

embeddings_obj = akasha.handle_embeddings("openai:text-embedding-ada-002",verbose=False)

print(type(embeddings_obj))



此Embeddings物件也可直接傳入Doc_QA,避免重複宣告

1
2
3
4
5
6
7

import akasha

model_obj = akasha.handle_model("openai:gpt-3.5-turbo",verbose=False,temperature=0.0)
embeddings_obj = akasha.handle_embeddings("openai:text-embedding-ada-002",verbose=False)
AK = Doc_QA(model=model_obj, embeddings=embeddings_obj)



直接使用Embeddings物件

embed_documents

創建完Embeddings物件後,可以直接使用來得到文件片段的向量資料(list[list[float]])

1
2
3
4
5
6
7
8
9
10

import akasha

text_list = ["範例文件內容1", "範例文件內容2", "範例文件內容3"]
embeddings_obj = akasha.handle_embeddings("openai:text-embedding-ada-002",verbose=False)
vectors = embeddings_obj.embed_documents(text_list)

print(vectors) # [[-0.004720511846244335, -2.9706923214689596e-06, -0.013798418454825878,...], [-0.004720511846244335, -2.9706923214689596e-06, -0.013798418454825878,...], [-0.004720511846244335, -2.9706923214689596e-06, -0.013798418454825878,...]]




取出特定文件db

當你想從大量文檔db中取出特定的文件db,以縮小搜尋範圍時,可以使用 extract_db_by_file (by file source name) 或 extract_db_by_keyword (by id)

example

1
2
3
4
5
6
7
8
9
10
11
import akasha
emb_name = "openai:text-embedding-ada-002"
emb_obj = akasha.handle_embeddings(emb_name, False)
doc_path = ["文檔資料夾1","文檔資料夾2"]
db, _ = akasha.db.processMultiDB(doc_path, True, emb_obj,
chunk_size=1000, ignore_check=True)

## extract from db ##
file_name_list = ["f1.txt", "g2.docx", "h3.pdf"]
ex_db = akasha.extract_db_by_file(db, file_name_list)

提示格式

根據使用的語言模型不同,使用不同的格式來下指令可以得到更好的結果,akasha目前提供 gpt, llama, chat_gpt, chat_mistral, chat_gemini, auto 等格式
若選擇 auto會根據模型類別來決定提示格式

gpt

1
2
3
4


prompt_format = System: {system_prompt} \n\n {history_messages} \n\n Human: {prompt}

llama

1
2
3
4


prompt_format = [INST] <<SYS>> {system_prompt} \n\n <<SYS>> {history_messages} \n\n {prompt} [\INST]

chat_gpt

1
2
3
4
5
6
7
8
9
10


prompt_format = [{"role":"system", "content": {system_prompt} },
{"role":"user", "content": {history msg1}},
{"role":"assistant", "content": {history msg2}},
.
.
.
{"role":"user", "content": {prompt}}]

chat_mistral

1
2
3
4
5
6
7
8
9
10
11


prompt_format = [{"role":"user", "content": "start conversation" },
{"role":"assistant", "content": {system_prompt}},
{"role":"user", "content": {history msg1}},
{"role":"assistant", "content": {history msg2}},
.
.
.
{"role":"user", "content": {prompt}}]

chat_gemini

1
2
3
4
5
6
7
8
9

prompt_format =[{"role":"model", "parts": [{system_prompt}]},
{"role":"user", "parts": [{history msg1}]},
{"role":"model", "parts": [{history msg2}]},
.
.
.
{"role":"user", "parts": [{prompt}]}]

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import akasha
sys_prompt = "請用中文回答"
prompt = "五軸是甚麼?"
qa = akasha.Doc_QA(
verbose=False,
search_type="svm",
model="openai:gpt-3.5-turbo")

response = qa.get_response(
doc_path="docs/mic/",
prompt=prompt,
prompt_format_type="chat_gpt",
system_prompt=sys_prompt,
)

Example2

1
2
3
4
5
6
7
8
import akasha
sys_prompt = "請用中文回答"
prompt = "五軸是甚麼?"
input_text = akasha.prompts.format_sys_prompt(sys_prompt,prompt,"chat_gpt")
model_obj = akasha.handle_model("openai:gpt-3.5-turbo",False,0.0)

response = akasha.call_model(model_obj, input_text)

選擇不同的文件搜尋方法

使用search_type參數可選擇不同的文件搜尋方法去找出與問題相關的文件段落,可使用svm, mmr, tfidf, knn。另可使用merge,為前三者的合併。

  1. 支持向量機(svm) 使用輸入提示和文件向量來訓練svm模型,訓練後,svm可用於基於其與訓練數據的相似性對新向量進行評分。

  2. Max Marginal Relevance(mmr) 通過余弦相似度選擇相似的文件,但它也考慮多樣性,因此它還會懲罰與已選擇文件的接近。

  3. 詞頻-逆文檔頻率(tfidf) 是信息檢索和文本挖掘中常用的權重技術。TF-IDF是一種統計方法,用於評估詞語在一個文檔集合或語料庫中相對於該集合中的一個特定文檔的重要性。

  4. K-最近鄰居(KNN) 是一種機器學習算法,用於分類和回歸問題。對於新數據點,它計算其與已知數據點的距離,然後基於最近的 k 個鄰居來預測類別或數值。在分類中,以多數票決定類別,而在回歸中則計算鄰居的平均值。

  5. ***Okapi BM25(bm25)***(BM 是最佳匹配的縮寫)是一種基於查詢詞出現在每個文檔中的檢索功能,而不考慮它們在文檔中的相鄰關系的排名一組文檔的方法。它是一系列具有略有不同組件和參數的評分函數。

  6. rerank 使用bge-reranker模型對文檔進行相似度排序,速度較慢。 (rerank/rerank:bge-reranker-large)



自動選擇搜尋方法

auto/ audo_rerank 是另一種可以選擇的文件搜尋策略,使用 bm25 來搜尋相同詞語的文件,並用 svm 搜尋近似詞意的文件,若為 audo_rerank 且兩者皆沒有找到,則使用rerank模型去遍歷文件,但會相當緩慢。

自訂搜尋方法

如果你希望設計自己的方法找尋最相似的文檔,可以建立search_type函數,並將此函數作為search_type參數

此函數輸入包含:

1.query_embeds: 查詢的嵌入。(numpy array)
2.docs_embeds: 所有文檔的嵌入。(表示文檔嵌入的 numpy 數組的list)
3.k: 所要選擇的最相關文檔的數量。(integer)
4.log: 一個字典,可用於記錄任何您希望記錄的其他信息。(dictionary)


此函數須回傳相似文檔的index順序(list)



example

如範例,我們使用歐幾里得距離度量來識別最相關的文檔。它返回一個表示距離小於指定閾值的查詢和文檔嵌入之間的前 k 個文檔的索引列表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import akasha

def cust(query_embeds, docs_embeds, k:int, relevancy_threshold:float, log:dict):

from scipy.spatial.distance import euclidean
import numpy as np
distance = [[euclidean(query_embeds, docs_embeds[idx]),idx] for idx in range(len(docs_embeds))]
distance = sorted(distance, key=lambda x: x[0])


## change dist if embeddings not between 0~1
max_dist = 1
while max_dist < distance[-1][0]:
max_dist *= 10
relevancy_threshold *= 10


## add log para
log['dd'] = "miao"


return [idx for dist,idx in distance[:k] if (max_dist - dist) >= relevancy_threshold]

doc_path = "./mic/"
prompt = "五軸是什麼?"

qa = akasha.Doc_QA(verbose=True, search_type = cust, embeddings="hf:shibing624/text2vec-base-chinese")
qa.get_response(doc_path= doc_path, prompt = prompt)


Document 物件

在akasha中,文件搜尋的結果會以list of Document的形式回傳,Docuement為一個儲存文件內容(page_content)和後設資料(metadata)的物件,可以以此進行宣告和取用。

1
2
3
4
5
6
7
8
9
10
from langchain.schema import Document

text = "這是一個測試文件段落,這是一個測試文件段落,這是一個測試文件段落。"
metadata = {'page':0, 'source':'docs/test1/f1.txt'}

doc1 = Document(page_content=text, metadata=metadata)

print(doc1.page_content)
print(doc1.metadata)



Retriver

若您想自行進行文件搜尋,在akasha中,文件搜尋是以以下流程進行:

  1. 從文件資料夾中建立chromadb,讀取為dbs物件
  2. 根據搜尋方法取得retriever物件
  3. 利用retriever進行文件搜尋,並根據語言模型和設定的文件token上限回傳不超過token上限的文件內容,與文件的排序(list of Document)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import akasha

emb_name = "openai:text-embedding-ada-002"
emb_obj = akasha.handle_embeddings(emb_name)
search_type = "auto"
query = "五軸是甚麼?"
model_name = "openai:gpt-3.5-turbo"
max_input_tokens = 3000
# 1. get dbs object
db, _ = akasha.db.processMultiDB(doc_path_list="docs/mic", verbose=False, embeddings=emb_obj,
chunk_size=1000, ignore_check=True)

# 2. get retriver list
retriver_list = akasha.search.get_retrivers(db=db, embeddings=emb_obj,
search_type=search_type, log={})


# 3. get sorted list of Documents by similarity
docs, doc_length, doc_tokens = akasha.search.get_docs(
db,
retrivers_list,
query,
language="ch",
search_type=search_type,
verbose=False,
model=model_name,
max_input_tokens=max_input_tokens
)

print(docs[0].page_content) # docs is list of Documents
print(doc_length) # integer
print(doc_tokens) # integer

get_relevant_documents_and_scores

若您只想使用單一的搜尋方法(如 mmr, svm, knn, tfidf, bm25),且不想限制文件的總token數量,可以使用 get_relevant_documents_and_scores取得文件排序結果(list of Documents)與相似度的分數(list of float)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import akasha

emb_name = "openai:text-embedding-ada-002"
emb_obj = akasha.handle_embeddings(emb_name)
search_type = "svm"
query = "五軸是甚麼?"
model_name = "openai:gpt-3.5-turbo"


# 1. get dbs object
db, _ = akasha.db.processMultiDB(doc_path_list="docs/mic", verbose=False, embeddings=emb_obj,
chunk_size=1000, ignore_check=True)

# 2. get retriver list
single_retriver = akasha.search.get_retrivers(db=db, embeddings=emb_obj,
search_type=search_type, log={})[0]


# 3. get sorted list of Documents and scores by similarity
### this method is only for single search method, not for 'merge' and 'auto' ###
docs, scores = single_retriver.get_relevant_documents_and_scores(query)


print(docs[0].page_content) # docs is list of Document
print(scores[0]) # float
print(len(docs), len(scores))

retri_docs

若您不想限制文件的總token數量,可以使用 retri_docs取得文件排序結果(list of Documents)
可根據參數 topK指定回傳的文件片段數量上限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import akasha

emb_name = "openai:text-embedding-ada-002"
emb_obj = akasha.handle_embeddings(emb_name)
search_type = "auto"
query = "五軸是甚麼?"
topK = 100
# 1. get dbs object
db, _ = akasha.db.processMultiDB(doc_path_list="docs/mic", verbose=False, embeddings=emb_obj,
chunk_size=1000, ignore_check=True)

# 2. get retriver list
retriver_list = akasha.search.get_retrivers(db=db, embeddings=emb_obj,
search_type=search_type, log={})


# 3. get sorted list of Documents by similarity
docs = akasha.search.retri_docs(
db,
retrivers_list,
query,
search_type=search_type,
topK=topK
verbose=False,
)

print(docs[0].page_content) # docs is list of Document


dbs物件

在akasha中,chromadb建立完之後,會被儲存成dbs物件,會儲存chromadb中的文件內容、metadata、向量資料、unique id,並被使用於後續的vector similarity search。

該物件可以添加多個chromadb資料,也可與其他dbs物件互相結合,也可根據filter抽取出需要的向量資料。

建立向量資料

processMultiDB

processMultiDB可對多個文件集(list of directory)建立chromadb,並回傳dbs物件與建立不成功的檔案list,若文件內容、使用嵌入模型、chunk size相等的chromadb已存在,則不會重新創建而直接讀取。

文件內容改變也會建立新的chromadb,設定參數ignore_check=True則不進行文件內容更改與否的確認,可更快的進行chromadb的讀取。

1
2
3
4
5
6
7
8
9
10
11
import akasha
doc_paths = ["docs/pns_query", "docs/mic"]
emb_name = "openai:text-embedding-ada-002"
emb_obj = akasha.handle_embeddings(emb_name)
db, ignore_files = akasha.processMultiDB(doc_path_list=doc_paths,
verbose=False,
embeddings=emb_obj,
chunk_size=1000,
ignore_check=False)


createDB_file & createDB_directory

使用多個文字檔案創建chromadb可使用 createDB_file,使用資料夾創建chromadb則使用 createDB_directory
創建完的dbs物件(db_files, db_directory)可以直接輸入進 get_response中,減少重複讀取。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import akasha
db_files = akasha.createDB_file(file_path = ["f1.txt","f2.docs"], embeddings="openai:text-embedding-ada-002",chunk_size=500, ignore_check=True)
db_directory = akasha.createDB_directory(doc_path= "./docs/mic/",
embeddings="openai:text-embedding-ada-002", ignore_check=True)
qa = akasha.Doc_QA(
verbose=True,
search_type="svm",
model="openai:gpt-3.5-turbo",
)

qa.get_response(
doc_path=db_directory,
prompt="五軸是甚麼?",
system_prompt="請用中文回答",
)




根據關鍵字建立向量資料

在建立向量資料時,若您不想根據整個文件片段進行embedding,可以使用 akasha.db.create_keyword_chromadb,可自訂義函式來輸出想進行embedding的關鍵字,如以下範例
我們定義了一個函式 generate_llm_keyword 請語言模型根據文件段落產生3~5個關鍵字並回傳。

當我們使用 akasha.db.create_keyword_chromadb,建立向量資料(chromadb),每個文件片段便會根據自訂義函式 generate_llm_keyword的輸出來進行embedding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import akasha

md_obj = akasha.handle_model("openai:gpt-4o", temperature=1)
emb_obj = akasha.handle_embeddings("openai:text-embedding-ada-002")
def generate_llm_keyword(text, keyword_num):

prompt = f"Generate 3~{keyword_num} keywords for the following text: \n\n" + text + "\n\n use \, to separate each keyword"

res = akasha.call_model(md_obj, prompt)
return [res]


db, _ = akasha.db.create_keyword_chromadb(
"docs/mic", emb_obj, 1000,
keyword_function=generate_llm_keyword)

注意

若不使用自訂義函式,預設的函式 akasha.generate_keyword需安裝keybert套件

1
pip install keybert


使用dbs物件

init

您可以直接宣告akasha.dbs()建立空的dbs物件,也可以利用已建立的chromadb建立dbs物件。

dbs物件包含ids(每個文字段落的unique id), embeds(每個文字段落的向量), metadatas(每個文字段落的後設資料), docs(每個文字段落的內容) 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import akasha
from langchain_chroma import Chroma


db1 = akasha.dbs()

### use chromadb to initialize dbs object ###
storage_directory = "chromadb/12345"
emb_obj = akasha.handle_embeddings()
docsearch = Chroma(persist_directory=storage_directory,
embedding_function=emb_obj)
db2 = akasha.dbs(docsearch)

print(len(db2.get_ids())) # list[str]
print(len(db2.get_embeds())) # list[list[float]]
print(len(db2.get_metadatas())) #list[dict]
print(len(db2.get_docs())) #list[dict]

merge

dbs物件之間可以使用.merge相互結合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import akasha
from langchain_chroma import Chroma

emb_obj = akasha.handle_embeddings()

docsearch1 = Chroma(persist_directory="chromadb/123",
embedding_function=emb_obj)
db1 = akasha.dbs(docsearch1)

docsearch2 = Chroma(persist_directory="chromadb/456",
embedding_function=emb_obj)
db2 = akasha.dbs(docsearch2)

db2.merge(db1)

print(len(db2.get_ids())) # list[str]
print(len(db2.get_embeds())) # list[list[float]]
print(len(db2.get_metadatas())) #list[dict]
print(len(db2.get_docs())) #list[dict]

add_chromadb

dbs物件可以添加新的chromadb資料

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import akasha
from langchain_chroma import Chroma

emb_obj = akasha.handle_embeddings()

docsearch1 = Chroma(persist_directory="chromadb/123",
embedding_function=emb_obj)

docsearch2 = Chroma(persist_directory="chromadb/456",
embedding_function=emb_obj)

db = akasha.dbs(docsearch1)

db.add_chromadb(docsearch2)

print(len(db.get_ids())) # list[str]
print(len(db.get_embeds())) # list[list[float]]
print(len(db.get_metadatas())) #list[dict]
print(len(db.get_docs())) #list[dict]

get_Documents

使用get_Docuemnts可以得到當前dbs物件中儲存的Documents list (包含page_contents文件內容和metadata後設資料)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import akasha
from langchain_chroma import Chroma

emb_obj = akasha.handle_embeddings()

docsearch1 = Chroma(persist_directory="chromadb/123",
embedding_function=emb_obj)

db = akasha.dbs(docsearch1)

docs = db.get_Documents()



print([doc.page_contents for doc in docs]) # list[str]
print([docs.metadata for doc in docs]) # list[dict]



提取dbs物件

extract_db_by_file

extract_db_by_file可以將檔名符合file_name_list中的所有資料提取出來生成新的dbs物件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import akasha
from langchain_chroma import Chroma

emb_obj = akasha.handle_embeddings()

docsearch1 = Chroma(persist_directory="chromadb/123",
embedding_function=emb_obj)

db = akasha.dbs(docsearch1)
file_name_list = ['f1.txt', 'f2.docx']

extracted_db = akasha.extract_db_by_file(db=db, file_name_list=file_name_list)

print(len(extracted_db.get_ids())) # list[str]
print(len(extracted_db.get_embeds())) # list[list[float]]
print(len(extracted_db.get_metadatas())) #list[dict]
print(len(extracted_db.get_docs())) #list[dict]

extract_db_by_keyword

extract_db_by_keyword可以將文字段落中存在任何keyword_list中keyword的所有資料提取出來生成新的dbs物件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import akasha
from langchain_chroma import Chroma

emb_obj = akasha.handle_embeddings()

docsearch1 = Chroma(persist_directory="chromadb/123",
embedding_function=emb_obj)

db = akasha.dbs(docsearch1)
keyword_list = ["資訊產業策進會", "AI人工智慧"]

extracted_db = akasha.extract_db_by_keyword(db=db, keyword_list=keyword_list)

print(len(extracted_db.get_ids())) # list[str]
print(len(extracted_db.get_embeds())) # list[list[float]]
print(len(extracted_db.get_metadatas())) #list[dict]
print(len(extracted_db.get_docs())) #list[dict]

extract_db_by_ids

extract_db_by_ids可以將存在id_list中的的所有資料提取出來生成新的dbs物件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import akasha
from langchain_chroma import Chroma

emb_obj = akasha.handle_embeddings()

docsearch1 = Chroma(persist_directory="chromadb/123",
embedding_function=emb_obj)

db = akasha.dbs(docsearch1)
id_list = ['2024-10-21-17_45_21_963065_0', '2024-10-21-17_45_23_601845_0']

extracted_db = akasha.extract_db_by_ids(db=db, id_list=id_list)

print(len(extracted_db.get_ids())) # list[str]
print(len(extracted_db.get_embeds())) # list[list[float]]
print(len(extracted_db.get_metadatas())) #list[dict]
print(len(extracted_db.get_docs())) #list[dict]

pop_db_by_ids

pop_db_by_ids會將所選id_list中的的所有資料從dbs物件中移除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import akasha
from langchain_chroma import Chroma

emb_obj = akasha.handle_embeddings()

docsearch1 = Chroma(persist_directory="chromadb/123",
embedding_function=emb_obj)

db = akasha.dbs(docsearch1)
id_list = ['2024-10-21-17_45_21_963065_0', '2024-10-21-17_45_23_601845_0']

akasha.pop_db_by_ids(db=db, id_list=id_list)

print(len(db.get_ids())) # list[str]
print(len(db.get_embeds())) # list[list[float]]
print(len(db.get_metadatas())) #list[dict]
print(len(db.get_docs())) #list[dict]



其他輔助函式

get_docs_from_doc

若不需要向量資料,只需要Documents(page_content, metadata),可使用get_docs_from_doc從文件資料夾中讀取文件內容並切割成chunk_size文件段落,此函式會回傳docs(list of Documents)和不成功的檔案名稱list。

1
2
3
4
5
6
7
8
9
10
11
12
13
import akasha


docs, ignore_files = akasha.get_docs_from_doc(doc_path="docs/mic", chunk_size=1000, ignore_check=True)

db = akasha.dbs(docsearch1)
id_list = ['2024-10-21-17_45_21_963065_0', '2024-10-21-17_45_23_601845_0']

extracted_db = akasha.extract_db_by_ids(db=db, id_list=id_list)

print([doc.page_contents for doc in docs]) # list[str]
print([docs.metadata for doc in docs]) # list[dict]

get_db_metadata

根據文件資料夾、嵌入模型、chunk size輸出所有文件段落的後設資料list,用於自查詢

update_db_metadta

將更新完的metadata list存回chromadb,用於自查詢

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

import akasha



def add_metadata(metadata_list: list):

import json
for metadata in metadata_list:
metadata['testing']= '後設資料新增測試'


### set parameter ###
dir_path = "docs/pns_query"
embed_name = "openai:text-embedding-ada-002"
chunk_size = 99999 # make sure 1 file 1 chunk
emb_obj = akasha.handle_embeddings("openai:text-embedding-ada-002")
####################

# create chromadb from docs
db, _ = akasha.db.processMultiDB(dir_path, False, emb_obj, chunk_size, True)


### add metadata to chromadb ###
metadata_list = akasha.db.get_db_metadata(dir_path, embed_name, chunk_size) # get original metada from chromadb, list of dictionary
metadata_list = add_metadata(metadata_list) # update/add metadata, you can build your own function to update metadata
akasha.db.update_db_metadata(metadata_list, dir_path, embed_name, chunk_size) # update and save new metadatas to chromadb
print(akasha.db.get_db_metadata(dir_path, embed_name, chunk_size)[0])
0%