文章目錄 原理 忠實度(Faithfulness) 答案相關性(Answer Relevance) 上下文相關性(Context Relevance) 上下文召回率(Context Recall) 答案正確性(Answer Correctness) 答案完整性(Answer Integrity)
原理
忠實度(Faithfulness)
def faithfulness_test ( ) : """ 忠實度 1 """ question = "愛因斯坦出生于何時何地?" answer = "愛因斯坦于1879年3月14日出生于德國。" f_1_prompt = f"""給定一個問題和答案,請你從給定答案的每個句子中創建一個或多個陳述。并按如下格式編號輸出:陳述1:[陳述1]陳述2:[陳述2]...問題: { question} 答案: { answer} """ """ 忠實度 2 """ relevant_context = [ "阿爾伯特·愛因斯坦(Albert Einstein,1879 年 3 月 14 日出生)是一位出生于德國的理論物理學家,被廣泛認為是有史以來最偉大、最有影響力的科學家之一。" , ] statements = '陳述1:愛因斯坦出生于德國。\n陳述2:愛因斯坦的出生日期是1879年3月14日。' f_2_prompt = f"""你的任務是根據給定的上下文判斷以下陳述的可信度。具體要求如下:1. 對于每個陳述,請你判斷它是否可以從給定的上下文信息中推斷。2. 如果上下文支持該陳述,請返回 1;如果不支持該陳述,請返回 0。3. 請按照以下格式返回結果:陳述1:1或0陳述2:1或0...上下文: { relevant_context} 陳述: { statements} """ response = client. chat. completions. create( model= OPENAI_MODEL, messages= [ { "role" : "user" , "content" : f_2_prompt} ] , ) print ( response. choices[ 0 ] . message) answer = response. choices[ 0 ] . message. contentprint ( answer)
答案相關性(Answer Relevance)
def answer_relevance_test ( ) : gt_question = "法國在哪里,首都是哪里?" """ 答案相關性 """ answer = "中國的首都是北京,中國位于亞洲,中國萬歲!" prompt = f"""請你為給定的答案生成一個或多個不重復的問題。答案: { answer} 結果請以JSON形式返回:{{"生成問題1": 問題1, "生成問題2": 問題2, ...}}""" response = client. chat. completions. create( model= OPENAI_MODEL, messages= [ { "role" : "user" , "content" : prompt} ] , ) print ( response. choices[ 0 ] . message) answer = response. choices[ 0 ] . message. contentprint ( "[DEBUG] answer: " , answer) print ( "[DEBUG] type(answer): " , type ( answer) ) answer = list ( json. loads( answer) . values( ) ) questions = answerprint ( "[DEBUG] questions: " , questions) sim_sum = np. array( [ cosine_similarity( get_text_embedding( client, gt_question) , get_text_embedding( client, q) ) for q in questions] ) ar = np. average( sim_sum) print ( "[DEBUG] sim_sum: " , sim_sum) print ( "[DEBUG] AR: " , ar)
上下文相關性(Context Relevance)
def context_relevance_test ( ) : """上下文相關性""" question = "法國的首都是哪里?" context = [ "法國位于西歐,擁有中世紀城市、高山村莊和地中海海灘。其首都巴黎以其時裝屋、盧浮宮等古典藝術博物館和埃菲爾鐵塔等古跡而聞名。" , "法國首都巴黎位于法國東部,是法國第二大城市。該國還以其葡萄酒和精致的美食而聞名。" ] prompt = f"""請你從提供的上下文中提取所有可能有助于回答以下問題的相關句子。具體要求如下:1.提取所有不重復的相關句子。2.如果找不到相關句子,或者你認為無法從給定的上下文中回答該問題,請返回“信息不足”。3.在提取相關句子時,請勿修改上下文中的任何句子。4.需要再次強調的是,請勿直接回答問題,只提取相關句子。上下文: { context} 問題: { question} """ response = client. chat. completions. create( model= OPENAI_MODEL, messages= [ { "role" : "user" , "content" : prompt} ] , ) answer = response. choices[ 0 ] . message. contentprint ( "[DEBUG] answer: " , answer)
上下文召回率(Context Recall)
def context_recall_test ( ) : """上下文召回率""" gt = "法國位于西歐,巴黎是其首都。我想吃火鍋。" context = "法國位于西歐,擁有中世紀城市、高山村莊和地中海海灘。其首都巴黎以其時裝屋、盧浮宮等古典藝術博物館和埃菲爾鐵塔等古跡而聞名。" prompt = f"""請你根據給定的真實答案,將其分解成1條或多條不重復的陳述。真實答案: { gt} 請以JSON形式返回結果:{{"陳述1": 陳述1, "陳述2": 陳述2,...}}。""" response = client. chat. completions. create( model= OPENAI_MODEL, messages= [ { "role" : "user" , "content" : prompt} ] , ) statements = response. choices[ 0 ] . message. contentstatements = list ( json. loads( statements) . values( ) ) print ( "[DEBUG] statements: " , statements) prompt = f"""請你根據給定的上下文和一些陳述,分析每條陳述,判斷該陳述是否可以由上下文驗證。具體要求如下:1. 如果該陳述可以由上下文驗證,請返回 1,否則返回 0。2. 判斷過程中,請勿修改陳述和上下文的內容。3. 結果以 JSON 形式返回:{{"陳述1": 1/0, "陳述2": 1/0, ...}}。4. 僅分析每條陳述,結果中不包含上下文的信息。上下文: { context} 陳述: { statements} """ response = client. chat. completions. create( model= OPENAI_MODEL, messages= [ { "role" : "user" , "content" : prompt} ] , ) response = response. choices[ 0 ] . message. contentprint ( "[DEBUG] response: " , response)
答案正確性(Answer Correctness)
def answer_correctness_test ( ) : """答案正確性事實正確性 + 語義相似性""" gt = """這個文檔主要討論了在“互聯網+”背景下,永順縣塔臥鎮紅色旅游產品開發的現狀、存在的問題以及相應的對策。文檔分為三個部分:1. **紅色旅游產品開發現狀**:介紹了塔臥鎮紅色旅游產品的主要類型,包括游覽路線參觀、紅色講堂和紀念品。指出了核心產品開發建設不足、旅游體驗產品經濟效益低和產品價值定位不準確等問題。2. **存在的不足**:分析了塔臥鎮紅色旅游產品開發中的問題,如旅游景點整合程度低、產品開發程度小、基礎設施配套不完善、旅游產品缺乏體驗特點等。3. **開發對策**:提出了針對上述問題的對策,包括整合旅游景點、明確產品目標市場、打造塔臥式旅游產品、增強旅游體驗、注重互聯網與產品開發結合以及提升紅色旅游產品知名度等。文檔還強調了互聯網在紅色旅游產品開發中的重要作用,提出了利用互聯網技術進行市場調研、產品設計、宣傳推廣和提升游客體驗的建議。""" answer = "這個文檔的主要內容是關于永順縣塔臥鎮紅色旅游產品開發現狀和存在的問題的分析。" prompt = f"""給你一個真實答案和一個回答,請你分析回答中的每個陳述,并將其分類到以下類別之一:- TP(真正例):在回答和真實答案中都存在的陳述。- FP(假正例):在回答中存在但在真實答案中未找到的陳述。- FN(假負例):在真實答案中存在但在回答中遺漏的相關陳述。需要強調的是:1. 首先你需要根據給定的回答,將其分解成1條或多條不重復的陳述,請勿改動回答的內容。2. 然后分析每條陳述,將該陳述分類到上述所提到的三個類別當中。3. 每個陳述必須準確地分類到一個類別中,不要試圖解釋真實答案和回答的含義,只需要比較它們中陳述的存在情況。4. 在你的返回結果中,請勿改動回答以及真實答案的內容。真實答案: { gt} 回答: { answer} 結果請以JSON形式返回:{{"TP": [數量、陳述], "FP": [數量、陳述], "FN": [數量、陳述], "陳述": [所有的陳述]}}""" response = client. chat. completions. create( model= OPENAI_MODEL, messages= [ { "role" : "user" , "content" : prompt} ] , ) response = response. choices[ 0 ] . message. contentresponse = json. loads( response) print ( "[DEBUG] response: " , response) tp, fp, fn = response[ "TP" ] [ 0 ] , response[ "FP" ] [ 0 ] , response[ "FN" ] [ 0 ] print ( "[DEBUG] TP: {}, FP: {}, FN: {}" . format ( tp, fp, fn) ) ac_1 = tp / ( tp + 0.5 * ( fp + fn) ) print ( "[DEBUG] ac_1: " , ac_1) g_emb = get_text_embedding( client, gt) a_emb = get_text_embedding( client, answer) ac_2 = cosine_similarity( g_emb, a_emb) print ( "[DEBUG] ac_2: " , ac_2) ac_weight = [ 0.5 , 0.5 ] ac = np. average( [ ac_1, ac_2] , weights= ac_weight) print ( "[DEBUG] ac: " , ac) print ( "----------" , np. linalg. norm( g_emb - a_emb) )
答案完整性(Answer Integrity)
def content_integrity_test ( ) : """內容完整性""" gt = """這個文檔主要討論了在“互聯網+”背景下,永順縣塔臥鎮紅色旅游產品開發的現狀、存在的問題以及相應的對策。文檔分為三個部分:1. **紅色旅游產品開發現狀**:介紹了塔臥鎮紅色旅游產品的主要類型,包括游覽路線參觀、紅色講堂和紀念品。指出了核心產品開發建設不足、旅游體驗產品經濟效益低和產品價值定位不準確等問題。2. **存在的不足**:分析了塔臥鎮紅色旅游產品開發中的問題,如旅游景點整合程度低、產品開發程度小、基礎設施配套不完善、旅游產品缺乏體驗特點等。3. **開發對策**:提出了針對上述問題的對策,包括整合旅游景點、明確產品目標市場、打造塔臥式旅游產品、增強旅游體驗、注重互聯網與產品開發結合以及提升紅色旅游產品知名度等。文檔還強調了互聯網在紅色旅游產品開發中的重要作用,提出了利用互聯網技術進行市場調研、產品設計、宣傳推廣和提升游客體驗的建議。""" answer = "這個文檔的主要內容是關于永順縣塔臥鎮紅色旅游產品開發現狀和存在的問題的分析。" prompt = f"""請分析以下段落,并提取出涵蓋其主要內容的所有關鍵詞。具體要求如下:1. 關鍵詞應全面覆蓋段落的主要信息。2. 關鍵詞應不重復,并盡可能簡潔明確。3. 請勿包含標點符號或多余的修飾詞。段落: { gt} 結果請以Python列表的形式返回,列表中的每個元素為你提取的關鍵詞,關鍵詞為字符串類型,格式為:[關鍵詞1, 關鍵詞2, ...]""" response = client. chat. completions. create( model= OPENAI_MODEL, messages= [ { "role" : "user" , "content" : prompt} ] , ) response = response. choices[ 0 ] . message. contentkeypoints = ast. literal_eval( response) print ( "[DEBUG] 關鍵詞: " , keypoints) print ( "[DEBUG] 關鍵詞數量: " , len ( keypoints) ) matched_keypoints = [ k for k in keypoints if k in answer] print ( "[DEBUG] 匹配的關鍵詞: " , matched_keypoints) coverage = len ( matched_keypoints) / len ( keypoints) print ( "[DEBUG] 關鍵詞覆蓋率: " , coverage) answer_sentences = cut_sent( answer) gt_sentences = cut_sent( gt) print ( "[DEBUG] answer_sentences: " , answer_sentences, len ( answer_sentences) ) print ( "[DEBUG] gt_sentences: " , gt_sentences, len ( gt_sentences) ) punctuation_list = " 。?!,、;:“”‘’『』()[]〔〕〈〉《》「」【】……——-—―·.?!,;:'\"()[]{}<>@#$%^&*_+-=~`|\\/" with PynlpirContextManager( ) : answer_words = [ s for s in pynlpir. segment( answer. strip( ) . replace( "\n" , "。" ) , pos_tagging= False ) if s not in punctuation_list] gt_words = [ s for s in pynlpir. segment( gt. strip( ) . replace( "\n" , "。" ) , pos_tagging= False ) if s not in punctuation_list] print ( "[DEBUG] answer_words: " , answer_words, len ( answer_words) ) print ( "[DEBUG] gt_words: " , gt_words, len ( gt_words) ) info_density = len ( set ( answer_words) & set ( gt_words) ) / len ( set ( answer_words) | set ( gt_words) ) info_density2 = ( len ( answer_sentences) / len ( gt_sentences) + len ( answer_words) / len ( gt_words) ) / 2 info_density3 = ( len ( answer_sentences) / len ( gt_sentences) + len ( answer_words) / len ( gt_words) + info_density) / 3 print ( "[DEBUG] 信息密度: " , info_density, info_density2, info_density3)