ai.py 程式說明
Table of contents
背景
程式說明
重要函數
以下主要由chatGPT生成、斜線部分為本人意見增修
這段程式碼提供了一個名為 AI
的類別,用於將自然語言處理的能力整合到一個Python對象中。該類別使用了多種 API,包括 OpenAI、tiktoken 和 sklearn 中的 TfidfVectorizer 和 cosine_similarity。
以下是類別中一些重要函數的用途、參數和輸出:
__init__(self, cfg: Config)
:- 用途:建構函數,用於初始化 AI 類別。
- 參數:
cfg
- 一個包含配置資訊的Config
類別實例。
- 輸出:沒有返回值,但會初始化類別的屬性。
_chat_stream(self, messages: list[dict], use_stream: bool = None) -> str
:- 用途:進行與 OpenAI 交談模型的溝通,根據輸入訊息獲得回應。
- 參數:
messages
- 包含要傳遞給模型的消息的字典列表;use_stream
- 一個布林值,指示是否使用流模式。
- 輸出:一個字符串,代表 AI 的回應。
completion(self, query: str, context: list[str])
:- 用途:創建一個根據給定上下文和用戶查詢生成的完成文本、用以控制GTP產出的品質。
- 參數:
query
- 用戶的查詢文本;context
- 一個字符串列表,包含與查詢相關的上下文。
- 輸出:AI 根據上下文生成的回應。
get_keywords(self, query: str) -> str
:- 用途:從用戶的查詢中提取關鍵字。
- 參數:
query
- 用戶的查詢文本。 - 輸出:一個由逗號分隔的關鍵字字符串。
create_embedding(text: str) -> (str, list[float])
:- 用途:為提供的文本創建一個嵌入表示(embedding)。
- 參數:
text
- 要創建嵌入表示的文本。 - 輸出:一對值,第一個是原始文本,第二個是文本的嵌入表示列表。
generate_summary(self, embeddings, num_candidates=3, use_sif=False)
:- 用途:為提供的嵌入表示生成一個摘要。
- 參數:
embeddings
- 嵌入表示的列表;num_candidates
- 生成摘要的候選數量;use_sif
- 是否使用平滑逆文檔頻率(SIF)。
- 輸出:一個文本摘要。
這個類別使用了 OpenAI 的 GPT-3 模型進行語言生成,並通過其 ChatCompletion
和 Embedding
API 實現這一功能。此外,該類別還使用了一些 NLP 技術,如 TF-IDF 和余弦相似度,來分析文本並生成摘要。
其他函數
前述chatGPT忽略掉的函數,可能涉及重要設定及影響,補充如下
_num_tokens_from_string
這個 _num_tokens_from_string
方法的用途是計算給定文本字符串中的 tokens(代幣)數量。
用途:測量給定字符串的 token 數,這對於與基於 token 的系統(如 OpenAI API)交互時預測使用成本和限制很有用。
參數:
string
- 需要計算 token 數的文本字符串。輸出:返回一個整數,表示字符串中的 token 數量。
_cut_texts
token最大上限值將在此處設定。如果更換模型,需配合修改此值。
這個 _cut_texts
方法的用途是裁剪一個文本列表,使其總 token 數量不超過一個特定的最大限制。
用途:在發送到 token 數量有限制的 API(例如 OpenAI)之前,將文本列表修剪到可接受的 token 數量範圍內。
參數:
context
- 一個字符串列表,每個字符串代表一段文本。輸出:返回一個經過修剪的字符串列表,其中的總 token 數量不會超過所設定的最大限制(在此例中為 3072 tokens,計算方式為 4096 - 1024)。如果總數超出限制,則從列表中移除多餘的文本,只保留能夠符合最大 token 限制的文本片段。
create_embeddings
名稱跟create_embedding很像,但似乎在api.py/console.py/webui.py呼叫的是create_embeddings而不是create_embedding
這個 Python 函數
create_embeddings
屬於AI
類,用於為提供的文本輸入創建嵌入向量。用途:創建一系列文本的嵌入向量,這通常是為了在機器學習或自然語言處理任務中將文本轉化為數字表示,使其可以用於計算。
- 參數:
texts
: 一個包含字符串的列表,每個字符串都是要為其創建嵌入向量的文本。
- 輸出:
- 返回一個元組,包含兩個元素:
- 第一個元素是一個列表,其中每個項目都是一個元組,包含原始文本和相應的嵌入向量(浮點數列表)。
- 第二個元素是一個整數,表示創建這些嵌入向量時使用的總令牌數。
- 返回一個元組,包含兩個元素:
函數的工作流程如下:
- 初始化空列表
result
來保存結果,和變量query_len
、start_index
和tokens
來追蹤查詢長度和使用的令牌數。 - 定義一個內部函數
get_embedding
來調用 OpenAI 的 API,創建給定文本片段的嵌入向量。 - 遍歷
texts
中的每個文本,累加其令牌數到query_len
。 - 如果累加的令牌數超過限制(8192-1024),則調用
get_embedding
並重置query_len
,調整start_index
以便處理餘下的文本。 - 將每個創建的嵌入向量添加到
result
列表中。 - 如果
query_len
非零,則表示還有剩餘的文本需要處理,對其調用get_embedding
。 - 返回包含所有嵌入向量和總使用令牌數的結果。
此函數在處理大量文本或很長的文本時特別有用,因為它會在超過令牌限制時分批處理文本。这对于管理 API 使用和成本控制特别重要。
_calc_avg_embedding
此函數 _calc_avg_embedding
是 AI
類中的私有函數,其目的是計算一組嵌入向量的平均嵌入向量。
用途:給定一系列嵌入向量,計算它們的平均值,通常用於捕捉一組向量的中心傾向或整體特徵。
- 參數:
embeddings
:一個列表,其中每個元素都是一個元組,該元組的第二個元素是一個浮點數列表,代表一個嵌入向量。
- 輸出:
- 返回一個浮點數列表,這個列表是所有提供的嵌入向量的平均值。
函數的工作流程如下:
- 初始化一個長度與嵌入向量維度相同的零向量
avg_embedding
。 - 遍歷
embeddings
列表中的每個嵌入向量。 - 將每個嵌入向量加到
avg_embedding
上。 - 將累加的結果除以嵌入向量的數量,以得到平均嵌入向量。
- 返回這個平均嵌入向量的列表形式。
這種方法通常用於文檔或文本段落聚集,可以用於比較文本相似性或作為一組文本的代表性特徵。
_calc_paragraph_avg_embedding_with_sif
此函數 _calc_paragraph_avg_embedding_with_sif
是 AI
類中的靜態方法,用於計算使用平滑逆文檔頻率(Smooth Inverse Frequency, SIF)權重的段落列表的平均嵌入向量。
用途:給定一個段落列表,這個方法計算它們的加權平均嵌入,這種方法通常用於文本表示,能更好地捕捉句子的語義信息。
- 參數:
paragraph_list
:一個列表,其中每個元素都是包含文本(句子)及其嵌入向量的元組。
- 輸出:
- 返回一個浮點數列表,這個列表代表加權平均的嵌入向量。
函數的工作流程如下:
- 初始化
alpha
,這是 SIF 方法中的平滑參數。 - 獲取句子總數和嵌入維度。
- 使用
TfidfVectorizer
計算句子中每個單詞的逆文檔頻率(IDF)值。 - 為每個句子初始化權重向量
weights
。 - 遍歷句子列表,分割每個句子成單詞,並計算每個單詞的 SIF 權重,更新
weights
。 - 計算每個句子嵌入的加權平均,並從每個句子的嵌入中減去其對應的權重。
- 將所有句子的結果平均,得到整個文本的平均嵌入向量。
- 返回這個平均嵌入向量的列表形式。
這種方法的主要優點是能夠減少常見詞的影響並強調有意義的詞,這對於捕捉句子或文檔的語義信息特別有用。
重要設定
init中的模型名稱
def __init__(self, cfg: Config):
...
self._encoding = tiktoken.encoding_for_model('gpt-3.5-turbo')
complete 內文
此內文將會控制chatGPT的行為、人設為期刊助理。將就其表現進行必要的檢討修正。原文:
'content': f'You are a helpful AI article assistant. '
f'The following are the relevant article content fragments found from the article. '
f'The relevance is sorted from high to low. '
f'You can only answer according to the following content:\n```\n{text}\n```\n'
f'You need to carefully consider your answer to ensure that it is based on the context. '
f'If the context does not mention the content or it is uncertain whether it is correct, '
f'please answer "Current context cannot provide effective information."'
f'You must use {self._language} to respond.'},