akasha使用手冊

akasha manual

儲存紀錄

每次執行akasha 的任何函數時,如果使用參數keep_logs=True,它都會保存此次運行的參數和結果到logs。每個運行都有一個timestamp,您可以使用 {obj_name}.timestamp_list 來查看它們,並使用它來找到您想要查看的logs。
您還可以將logs保存為 .txt 文件或 .json 文件。

範例

執行完get_response後,可以利用timestamp獲取log,也可以使用save_logs來保存log

1
2
3
4
5
6
7
8
9
10
11
12
13
qa = akasha.Doc_QA(verbose=False, keep_logs=True, search_type="merge", max_input_tokens=3000,model="llama-gpu:model/chinese-alpaca-2-7b.Q5_K_S.gguf")
query1 = "五軸是什麼"
qa.get_response(doc_path="./doc/mic/", prompt = query1)

tp = qa.timestamp_list
print(tp)
## ["2023/09/26, 10:52:36", "2023/09/26, 10:59:49", "2023/09/26, 11:09:23"]

print(qa.logs[tp[-1]])
## {"fn_type":"get_response","search_type":"merge", "max_input_tokens":3000,....."response":....}


qa.save_logs(file_name="logs.json",file_type="json")

logs



AiiDO

akasha也可以利用AiiDO來保存執行紀錄,您需要在 AiiDO 平台上創建一個項目。完成後,您將收到自動上傳實驗所需的所有參數。
在程序的同一目錄下創建一個 .env 文件,並貼上所有參數。

1
2
3
4
5
##.env file
MINIO_URL= YOUR_MINIO_URL
MINIO_USER= YOUR_MINIO_USER
MINIO_PASSWORD= YOUR_MINIO_PASSWORD
TRACKING_SERVER_URI= YOUR_TRACKING_SERVER_URI

在創建了 .env 文件之後,您可以使用 record_exp 來設置實驗名稱,它將自動記錄實驗指標和結果到 mlflow 服務器。

1
2
3
4
5
6
7
8
9
10
11
12
import akasha
import os
from dotenv import load_dotenv
load_dotenv()

os.environ["OPENAI_API_KEY"] = "your openAI key"

dir_path = "doc/"
prompt = "「塞西莉亞花」的花語是什麼? 「失之交臂的感情」 「赤誠的心」 「浪子的真情」 「無法挽回的愛」"
exp_name = "exp_akasha_get_response"
ak = akasha.Doc_QA(record_exp=exp_name)
response = ak.get_response(dir_path, prompt)


在你指定的實驗名稱中,可以看到不同次實驗的紀錄,每個紀錄的名稱是embedding, search type and model name的組合

upload_experiments



你也可以直接比較不同次實驗的結果

response_comparison



翻譯器

helper模組中提供寫好的函數call_translator讓LLM協助翻譯回答,如以下的範例使用語言模型將中文的回答翻譯成英文。

1
2
3
4
5
6
ak = akasha.Doc_QA(verbose=False, search_type="auto")

response = ak.get_response(doc_path="docs/mic/", prompt="五軸是什麼?")

translated_response = akasha.helper.call_translator(ak.model_obj, response, language="en")



JSON 格式輸出器

helper模組中提供寫好的函數call_JSON_formatter讓LLM協助將回答轉成JSON格式。

1
2
3
4
5
6
ak = akasha.Doc_QA(verbose=True,)
response = ak.ask_whole_file(file_path="docs/resume_pool/A.docx", prompt=f'''以上是受試者的履歷,請回答該受試者的學歷、經驗、專長、年資''')
formatted_response = akasha.helper.call_JSON_formatter(ak.model_obj, response, keys=["學歷", "經驗", "專長", "年資"])

print(formatted_response, type(formatted_response))

1
{'學歷': 'xxx大學電資學士班四技', '經驗': '帶班導師xx文理補習班擔任補習班導師/管理人員', '專長': '計算機網路(協定)、資料庫系統、物件導向程式設計、C語言、Python、C++、Gitlab、Jenkins、Git、Linux(Bash shell、Ubuntu), '年資': '0-1年'} <class 'dict'>


call_model

若要呼叫語言模型,可以使用輔助函數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

若要呼叫語言模型即時回答,可以使用輔助函數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)



call_batch_model

如果你有大量不需要連貫的推理需求,可以使用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"]





self-rag

實作self-rag,利用語言模型來找出與問題相關的文件片段。

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
question = "LPWAN和5G的區別是什麼?"

model_name = "openai:gpt-3.5-turbo"
model_obj = akasha.handle_model(model_name, False, 0.0)
emb_obj = akasha.handle_embeddings()


db = akasha.createDB_directory("./docs/mic/", emb_obj, ignore_check=True)


retrivers_list = akasha.search.get_retrivers(db2, emb_obj, 0.0,
"auto", {})

### max_input_tokens is the max length of tokens, so get_docs function will return top relevant docs that their total legnth do not exceed 6000 tokens ###
docs, doc_length, doc_tokens = akasha.search.get_docs(
db2,
retrivers_list,
question,
"ch",
"auto",
False,
model_name,
max_input_tokens=6000,
compression=False,
)

### we use self-RAG to sort those docs and using llm to determine the order of relevant docs ###
RAGed_docs = akasha.self_RAG(model_obj,
question,
docs,)


計算token數量

Tokenizer.compute_tokens,此函數回傳該語言模型輸入的文字所需要的token數量

1
2
3
4
5
6
7
8

text = "你是一個歷史學家詳細介紹札幌的歷史"
model = "openai:gpt-3.5-turbo"
num_tokens = akasha.myTokenizer.compute_tokens(
text=text, model_id=model)

print(num_tokens)

根據文件產生關鍵句子

generate_keyword使用keybert,根據輸入的文件來產生相關的關鍵字,可用於建立embeddings

注意

akasha.generate_keyword需安裝keybert套件

1
pip install keybert
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

text = """五軸工具機是一種比三軸工具機更先進的加工裝置。它透過兩個軸控制工具的旋轉方向,再透過長寬高三個軸移動進行切削加工,能
進行更複雜形狀的加工,確保加工精密度並符合自動化的訴求。 五軸加工的優勢在於首次手動調整後就能無人運作,節省人力物力,尤其在電動車等
領域的生產中,因應零件種類和產量變動頻繁的需求。 然而,五軸加工也面臨加工誤差穩定性的挑戰,例如溫度變動可能導致加工差距。 因此,廠
商也致力於開發相關技術,例如大隈的「熱親和理念」和「5軸微調」,以確保加工精密度在自動化環境下保持穩定。"""

keyword_num = 3 #產生的關鍵字數量

keyword_model = "paraphrase-multilingual-MiniLM-L12-v2" #default


keywords = akasha.generate_keyword(text=text, keyword_num=keyword_num, keyword_model=keyword_model)

print(keywords)

### ['五軸工具機是一種比三軸工具機更先進的加工裝置', '五軸加工的優勢在於首次手動調整後就能無人運作', '五軸加工也面臨加工誤差穩定性的挑戰']

代理

使用代理(agent)可以賦予語言模型其他能力,以便完成你下的指令,例如提供文件编辑、google搜尋的工具,便可以使語言模型提供更準確地回答,也可以請他幫忙儲存或刪除文件。

範例

在範例1中,創建了一個可以讓使用者輸入文字的工具,也提供給代理一個將文字儲存成json檔案的工具。創建代理後,我們指示它詢問用戶問題,並將結果儲存到default.json中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

def input_func(question: str):
response = input(question)
return str({"question": question, "answer": response})



input_tool = akasha.create_tool(
"user_question_tool",
"This is the tool to ask user question, the only one param question is the question string that has not been answered and we want to ask user.",
func=input_func)

ao = akasha.test_agent(verbose=True,
tools=[
input_tool,
akasha.get_saveJSON_tool(),
],
model="openai:gpt-3.5-turbo")
print(
ao("逐個詢問使用者以下問題,若所有問題都回答了,則將所有問題和回答儲存成default.json並結束。問題為:1.房間燈關了嗎? \n2. 有沒有人在家? \n3.有哪些電器開啟?\n"
))

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

I have successfully saved all the questions and answers into the "default.json" file. The conversation is now complete.

### default.json ###
[
{
"question": "房間燈關了嗎?",
"answer": "no"
},
{
"question": "有沒有人在家?",
"answer": "no"
},
{
"question": "有哪些電器開啟?",
"answer": "phone, shower"
}
]



在範例二中,我們添加了wikipedia工具,讓語言模型能透過Wikipedia API查詢必要的資訊來幫助回答。由於wiki的回答中可能包含不必要的資訊,我們可以使用retri_observation來擷取與問題有關的回答。

1
2
3
4
5
6
7
8
9
10

ao = akasha.test_agent(
verbose=True,
tools=[input_tool,
akasha.get_saveJSON_tool(),
akasha.get_wiki_tool()],
retri_observation=True,
model="openai:gpt-3.5-turbo")
print(ao("請用中文回答李遠哲跟黃仁勳誰比較老?將查到的資訊和答案儲存成json檔案,檔名為AGE.json"))

1
2
3
4
5
6
7
8
9
根據查到的資訊,李遠哲(Yuan T. Lee)比黃仁勳(Jensen Huang)更老。李遠哲於1936年11月19日出生,而黃仁勳的出生日期是1963年2月17日。我已將這些資訊儲存成名為"AGE.json"的
JSON檔案。

### AGE.json ###
{
"李遠哲": "1936-11-19",
"黃仁勳": "1963-02-17",
"答案": "李遠哲比黃仁勳更老"
}


stream

若你想及時得到每輪agent的回應,可以使用stream function,此函式將每輪agent的回應回傳為generator

1
2
3
4
5
6
7
8
9
10
11

ao = akasha.test_agent(
verbose=True,
tools=[input_tool,
akasha.get_saveJSON_tool(),
akasha.get_wiki_tool()],
retri_observation=True,
model="openai:gpt-3.5-turbo")
st = ao.stream("請用中文回答李遠哲跟黃仁勳誰比較老?將查到的資訊和答案儲存成json檔案,檔名為AGE.json")
for s in st:
print(s)




test_agent 中的所有參數:

1
2
3
4
5
6
7
8
9
10
11
12
Args:
model (str, optional): 使用的大語言模型. Defaults to "gpt-3.5-turbo".\n
verbose (bool, optional): 是否顯示log文字. Defaults to False.\n
language (str, optional): 用來計算文字長度(max_doc_len)的語言. Defaults to "zh"
temperature (float, optional): 大語言模型的temperature(0.0 ~ 1.0) . Defaults to 0.0.\n
keep_logs (bool, optional)**: 是否紀錄執行的log. Defaults to False.\n
max_round (int, optional)**: agent最多執行次數,超過即跳出,避免無線迴圈. Defaults to 20.\n
max_input_tokens (int, optional): agent保留的之前做過的思考與動作的文字最大長度. Defaults to 3200.\n
max_past_observation (int, optional)**: agent保留的之前做過的思考與動作的最多次數. Defaults to 10.\n
retri_observation (bool, optional)**: 若設為True, agent會利用大語言模型去擷取tool回傳內容,避免多餘文字輸入. Defaults to False.\n


call_stream_model

在輔助函數中,若LLM模型為若為openai, huggingface, remote, gemini, anthropic類模型,可以使用akasha.call_stream_model()來得到流輸出

1
2
3
4
5
6
7
8
9

import akasha
prompt = "say something."
model_obj = akasha.handle_model("openai:gpt-3.5-turbo", False, 0.0)
streaming = akasha.call_stream_model(model_obj, prompt)

for s in streaming:
print(s)

Doc_QA stream

Doc_QA class的函式皆可使用參數stream=True來得到流輸出

1
2
3
4
5
6
7
8
import akasha

ak = akasha.Doc_QA(stream=True)

streaming = ak.get_response("docs/mic", "say something")

for s in streaming:
print(s)

Stream Output

要在網頁上或API中使用流輸出(及時一個字一個字輸出語言模型回答)時,若為openai, huggingface, remote, gemini, anthropic 類模型,可以使用model_obj.stream(prompt),以下為streamlit write_stream在網頁上即時輸出回答為範例

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
34
35
36
import streamlit as st
import akasha
import gc, torch

if "pre" not in st.session_state:
st.session_state.pre = ""
if "model_obj" not in st.session_state:
st.session_state.model_obj = None

def clean():
try:
gc.collect()
torch.cuda.ipc_collect()
torch.cuda.empty_cache()
except:
pass



def stream_response(prompt:str, model_name:str="openai:gpt-3.5-turbo"):
# Mistral-7B-Instruct-v0.3 Llama3-8B-Chinese-Chat
streaming = akasha.call_stream_model(st.session_state.model_obj, prompt)
yield from streaming

model = st.selectbox("select model", ["openai:gpt-3.5-turbo","hf:model/Mistral-7B-Instruct-v0.3"])
prompt = st.chat_input("Say something")
if st.session_state.pre != model:
st.session_state.model_obj = None
clean()
st.session_state.model_obj = akasha.helper.handle_model(model, False, 0.0)
st.session_state.pre = model

if prompt:
st.write("question: " + prompt)
st.write_stream(stream_response(prompt, model))

使用model_obj = akasha.helper.handle_model(model, False, 0.0)建立模型物件,當要使用推論時,使用akasha.call_stream_model(model_obj, prompt)進行推論,可使用yield讓stream_response函式回傳generator, 便可即時輸出回答。

批量推理

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

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"]



FAST API

akasha 提供get_response, ask_self, ask_whole_file, get_summary的api server

啟動

1
2
akasha api (–port {port} –host {host} –workers {num_of_workers})

Example

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import requests
import os

HOST = os.getenv("API_HOST", "http://127.0.0.1")
PORT = os.getenv("API_PORT", "8000")
urls = {
"summary": f"{HOST}:{PORT}/get_summary",
"qa": f"{HOST}:{PORT}/get_response",
"self": f"{HOST}:{PORT}/ask_self",
"file": f"{HOST}:{PORT}/ask_whole_file",
}

openai_config = {
"azure_key": {your api key},
"azure_base": {your api base},
}

self_data = {
"prompt": "太陽電池技術?",
"info": "太陽能電池技術5塊錢",
"model": "openai:gpt-3.5-turbo",
"system_prompt": "",
"max_input_tokens": 3000,
"temperature": 0.0,
"openai_config": openai_config
}

file_data = {
"doc_path": "docs/mic/20230317_5軸工具機因應市場訴求改變的發展態勢.pdf",
"prompt": "五軸是什麼?",
"chunk_size": 1000,
"model": "openai:gpt-3.5-turbo",
"embedding_model": "openai:text-embedding-ada-002",
"system_prompt": "",
"max_input_tokens": 3000,
"temperature": 0.0,
"openai_config": openai_config
}

chat_data = {
"doc_path": "docs/pns/",
"prompt": "太陽電池技術?",
"chunk_size": 1000,
"model": "openai:gpt-3.5-turbo",
"embedding_model": "openai:text-embedding-ada-002",
"search_type": 'auto',
"system_prompt": "",
"max_input_tokens": 3000,
"temperature": 0.0,
"openai_config": openai_config
}
summary_data = {
"file_path": "docs/pns/2484.txt",
"model": "openai:gpt-3.5-turbo",
"summary_type": "reduce_map",
"summary_len": 500,
"system_prompt": "",
"openai_config": openai_config
}

# chat_response = requests.post(urls["qa"], json=chat_data).json()
# print(chat_response)

# sum_response = requests.post(
# urls["summary"],
# json=summary_data,
# ).json()

# print(sum_response)

self_response = requests.post(urls["self"], json=self_data).json()
print(self_response)
file_response = requests.post(urls["file"], json=file_data).json()
print(file_response)


自查詢(Self Query)

自查詢是指能夠自我查詢的檢索問題方法。透過結構化、包含metadata的文件集,能將使用者的問題先透過metadata進行篩選,再藉由向量來查詢語意相似的文檔,比起直接做向量查詢能更精確的找到需要的文件。

流程

自查詢的流程為

0. create metadata

添加結構化資料到文件集與向量資料庫中

1. query constructor

將使用者問題轉換成 query(用來做向量查詢的字串)與filter(用來篩選文件集的metatada keywords)
例如,使用者問題為: A公司在2024年對電動車的銷售量為多少?

透過語言模型 將其轉換為

1
2
3
4
{
"query": "電動車的銷售量",
"filter": "and(eq(\"公司名稱\", \"A公司\"), eq(\"日期年\", \"2024\"))"
}

2. filter translator

將filter處理為程式可執行的dictionary

3. filter docs

根據filter篩選需要的文件集

1
2
3
{'filter': {'$and': [{'拜訪年': {'$eq': '2024'}}, {'公司名稱': {'$eq': 'A公司'}}]}}


從篩選出來的文件集做向量相似度搜尋



範例

1. create chromadb & add metadatas

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47

import akasha



def add_metadata(metadata_list: list):

import json
from pathlib import Path
for metadata in metadata_list:
file_path = metadata['source'] # file path
try:
with Path(file_path).open('r', encoding='utf-8') as file:
dictionary = json.load(file)


metadata['課別'] = dictionary['課別']
metadata['業務擔當'] = dictionary['業務擔當']
ddate = dictionary['拜訪日期']
metadata['拜訪年'] = int(ddate.split('-')[0])
metadata['拜訪月'] = int(ddate.split('-')[1])
metadata['產品'] = dictionary['產品']
metadata['公司名稱'] = dictionary['公司名稱']
metadata['大分類'] = dictionary['大分類']
metadata['中分類'] = dictionary['中分類']
except Exception as e:
print(f"JSONDecodeError: {e}")
return metadata_list


### set parameter ###
dir = "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, False, emb_obj, chunk_size,
True)


### add metadata to chromadb ###
metadata_list = akasha.db.get_db_metadata(dir, 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, embed_name, chunk_size) # update and save new metadatas to chromadb
print(akasha.db.get_db_metadata(dir, embed_name, chunk_size)[0])


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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

from akasha.self_query import query_filter
### set parameter ###

db, _ = akasha.db.processMultiDB(dir, False, emb_obj, chunk_size,
True)
prompt = "A公司在2024年對電動車的銷售量為多少?"
search_type = "bm25"
model_obj = akasha.helper.handle_model("openai:gpt-4o", True)

## each metadata attribute should include name, description and type(integer, float, string) ##
metadata_field_info = [
{
"name": "拜訪年",
"description": "此訪談紀錄的拜訪年份",
"type": "integer"
},
{
"name": "拜訪月",
"description": "此訪談紀錄的拜訪月份",
"type": "integer"
},
{
"name": "業務擔當",
"description": "業務的名稱",
"type": "string"
},
{
"name": "中分類",
"description": "訪談產品的中等分類",
"type": "string"
},
{
"name": "公司名稱",
"description": "訪談對象的公司名稱",
"type": "string"
},
{
"name": "大分類",
"description": "訪談產品的大分類",
"type": "string"
},
{
"name": "產品",
"description": "訪談的產品名稱/型號",
"type": "string"
},
{
"name": "課別",
"description": "公司部門的課別名稱或代號",
"type": "string"
},
]

document_content_description = "業務與客戶的訪談紀錄"

####################




### use self-query to filter docs
new_dbs, query, matched_fields = query_filter(
prompt, model_obj, db, metadata_field_info,
document_content_description)

### option1 use svm similarity search to sort docs from filtered docs
retriver = akasha.search.get_retrivers(new_dbs, emb_obj, 0.0,
search_type)[0]
retri_docs, retri_scores = retriver._gs(query)


### option2 use new_dbs(filtered docs) to run other akasha functions
ak = akasha.Doc_QA(embeddings=emb_obj, model=model_obj)
ak.get_response(doc_path=new_dbs,prompt=prompt)




自訂parser函式

若您使用的語言模型回答無法使用預設的parser找出query與filter,可以自訂一個parser函式,輸入為語言模型的回答(string),輸出為[query(string), filter(dictionary)]。

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

import json
def just_an_example(input_text: str):
# input_text :
#```json
#{
# "query": "產品疑慮",
# "filter": "and(eq(\"公司名稱\", \"a公司\"), eq(\"拜訪年\", \"2024\"))"
#}
#```

jstr = '{"$and": [{"公司名稱": {"$eq": "a公司"}}, {"拜訪年": {"$eq": "2024"}}]}'
dic = json.loads(jstr)
return "產品疑慮", dic

### use self-query to filter docs
new_dbs, query, matched_fields = query_filter(
prompt, model_obj, db, metadata_field_info,
document_content_description, just_an_example)



loose filter

使用參數 loose_filter=True會將filter中的$and替換成$or,只要文件有符合任意attribute便會選取

1
2
3
4
5
6
7

### use self-query to filter docs
## filter become '{"$or": [{"公司名稱": {"$eq": "a公司"}}, {"拜訪年": {"$eq": "2024"}}]}'
new_dbs, query, matched_fields = query_filter(
prompt, model_obj, db, metadata_field_info,
document_content_description, loose_filter = True)

JSON Formatter

如果你想讓語言模型的回答為JSON格式,可以使用JSONformatter

範例

如以下範例,首先先定義你想要回傳的key值的名稱、說明和型別,並利用JSON_formatter轉換成json格式的prompt,並在問問題時把JSON_prompt丟入system_prompt中。

如formatter2和formatter3,你也可以直接使用JSON_formatter_list或JSON_formatter_dict將list或dictionary轉換成json格式的prompt。

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
34
import akasha.prompts as prompts
import akasha
import akasha.eval as eval

formatter = [
prompts.OutputSchema(name="學歷", description="受試者的就讀大學", type="str"),
prompts.OutputSchema(name="經驗", description="受試者的工作經驗", type="str"),
prompts.OutputSchema(name="專長", description="受試者的專長能力", type="list"),
prompts.OutputSchema(name="年資", description="受試者的總工作年數", type="int")
]

formatter2 = prompts.JSON_formatter_list(names=["學歷","經驗","專長","年資"], types=["str","str","list","int"],\
descriptions=["受試者的就讀大學","受試者的工作經驗","受試者的專長能力","受試者的總工作年數"])

formatter3 = prompts.JSON_formatter_dict([{ "name": "學歷", "description": "受試者的就讀大學", "type": "str" },\
{ "name": "經驗", "description": "受試者的工作經驗", "type": "str" },\
{ "name": "專長", "description": "受試者的專長能力", "type": "list" },\
{ "name": "年資", "description": "受試者的總工作年數", "type": "int" }])


JSON_prompt = prompts.JSON_formatter(formatter)
# JSON_prompt = prompts.JSON_formatter(formatter2)
# JSON_prompt = prompts.JSON_formatter(formatter3)


ak = akasha.Doc_QA()

response = ak.ask_whole_file(file_path="docs/resume_pool/A.docx",
system_prompt=JSON_prompt, prompt=f'''以上是受試者的履歷,請回答該受試者的學歷、經驗、專長、年資''')

parse_json = akasha.helper.extract_json(resposne)

print(parse_json)
print(type(parse_json))
1
2
3
{'學歷': '國立臺北科技大學電資學士班 四技', '經驗': '總年資0-1年年工作經歷', '專長': ['計算機網路(協定)', '資料庫系統', '物件導向程式設計', 'C語言', 'python', 'C++', 'Gitlab', 'Jenkins', 'Git', 'linux', 'Google表單'], '年資': 1} 

<class 'dict'>

XML Formatter

如果你想讓語言模型的回答為XML格式,可以使用XMLformatter

範例

如以下範例,首先先定義你想要回傳的key值的名稱、說明和型別,並利用XML_formatter轉換成xml格式的prompt,並在問問題時把xml_prompt丟入system_prompt中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import akasha.prompts as prompts
import akasha
import akasha.eval as eval

formatter = [
prompts.OutputSchema(name="學歷", description="受試者的就讀大學", type="str"),
prompts.OutputSchema(name="經驗", description="受試者的工作經驗", type="str"),
prompts.OutputSchema(name="專長", description="受試者的專長能力", type="list"),
prompts.OutputSchema(name="年資", description="受試者的總工作年數", type="int")
]
xml_prompt = prompts.XML_formatter(formatter)


ak = akasha.Doc_QA()

response = ak.ask_whole_file(file_path="docs/resume_pool/A.docx",
system_prompt=xml_prompt, prompt=f'''以上是受試者的履歷,請回答該受試者的學歷、經驗、專長、年資''')

print(response)
1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<resume>
<學歷>國立臺北科技大學電資學士班 四技 就學中</學歷>
<經驗>英文短期文理補習班補習班導師/管理人員</經驗>
<專長>
<能力>語言能力</能力>
<英文>聽-中等, 說-中等, 讀-中等, 寫-中等</英文>
<證照>TOEIC </證照>
</專長>
<年資>0-1</年資>
</resume>

安裝

只要你安裝了akasha,便可以直接使用akasha_ui,在terminal執行:

1
$ akasha ui

便可以在瀏覽器上開啟,開始使用akasha ui



Docker安裝

若要使用docker安裝,可以直接下載image

1
$ docker pull ccchang0518/akasha-ui:1.0

如要使用gpu來推論llama-cpp模型(.gguf)

1
$ docker pull ccchang0518/akasha-ui:llamacpp

執行image

1
$ docker run --gpus all -v ./model:/app/model  -v ./docs:/app/docs -v ./chromadb:/app/chromadb -p 8501:8501 akasha-llamacpp-ui:0.1


上傳文件檔

上傳你需要的文件檔案,並取資料夾名稱,創立知識庫。

請注意文件檔只允許(.docx, .txt, .pdf)

ui_upload



設定

在設定頁面,可以選擇要詢問的知識庫和調整各種參數、選擇不同語言模型。

若使用openAI模型,請在左側輸入 openAI的key,azure openAI則需要額外輸入url。

ui_setting

手動增加模型

如果你想使用不同的語言模型,可以至huggingface下載模型到”/model”資料夾,模型便會加至設定中

ui_model

設定完成後,便可開始使用akasha ui

get_response

確認設定中有選擇正確的知識庫後,在system_prompt中填入希望回答的格式,在prompt中填入問題,按下submit便可以執行文檔問答。
ui_5



可以使用clear 按鈕清空對話欄,也可以使用左側Download Log按鈕下載紀錄
image



chain_of_thought

使用Add Prompt 按鈕增加子問題,便可以使用chain of thought先提問小問題並利用小問題的答案回答較為複雜的問題。
image



summary

選擇summary方法與長度後,上傳單一文件檔便可得到該文檔的摘要。
image

0%