큰 언어 모델의 응답의 신뢰성을 측정하는 방법

큰 언어 모델의 응답의 신뢰성을 측정하는 방법

대형 언어 모델 (LLMS)의 기본 원리는 매우 간단합니다. 교육 데이터의 통계적 패턴을 기반으로 한 단어 순서로 다음 단어 (또는 토큰)를 예측합니다. 그러나이 간단한 기능은 텍스트 요약, 아이디어 생성, 브레인 스토밍, 코드 생성, 정보 처리 및 컨텐츠 작성과 같은 여러 가지 놀라운 작업을 수행 할 수있을 때 엄청나게 정교한 것으로 나타났습니다. 즉, LLM은 기본 기능을 고수하는 것 외에는 실제로 “이해”하는 메모리가 없습니다. 다음 단어를 예측합니다.

차세대 예측 과정은 확률 론적입니다. LLM은 확률 분포에서 각 단어를 선택해야합니다. 이 과정에서 그들은 종종 일관된 응답을 생성하고 그럴듯하지만 잘못된 정보로 간격을 메우기 위해 허위, 제작 또는 일관성없는 내용을 생성합니다. 이 현상을 환각이라고합니다.이 현상은 LLM의 피할 수없는 잘 알려진 특징 인 환각이라고합니다.

LLM이 외부 지식 소스와 함께 작동하게하는 검색 증강 생성 (RAG) 방법은 어느 정도 환각을 최소화하지만 완전히 근절 할 수는 없습니다. 고급 래그는 텍스트 내 인용 및 URL을 제공 할 수 있지만 이러한 참조를 확인하는 것은 바쁜 시간이 걸릴 수 있습니다. 따라서 LLM의 응답의 신뢰성 또는 신뢰성을 평가하기위한 객관적인 기준이 필요합니다. 자체 지식 또는 외부 지식 기반 (RAG)에서 생성되는지 여부에 관계없이.

이 기사에서는 LLM의 출력에 점수를 할당하는 신뢰할 수있는 언어 모델로 LLM의 출력을 신뢰할 수있는 방법에 대해 논의 할 것입니다. 우리는 먼저 신뢰할 수있는 언어 모델을 사용하여 LLM의 답변에 점수를 할당하고 신뢰성을 설명하는 방법에 대해 논의 할 것입니다. 그 후, 우리는 Llamaparse와 Llamaindex가있는 예제 Rag를 개발하여 신뢰성에 대한 Rag의 답변을 평가할 것입니다.

이 기사의 전체 코드는 Github의 Jupyter Notebook에서 제공됩니다.

LLM의 답변에 신뢰 점수를 할당합니다

LLM의 응답에 신뢰성 점수를 할당하는 방법을 보여주기 위해 CleanLab의 신뢰할 수있는 언어 모델 (TLM)을 사용합니다. 이러한 TLM은 조합을 사용합니다 불확실성 정량화 그리고 일관성 분석 LLM 응답에 대한 신뢰도 및 설명을 계산합니다.

CleanLab은 웹 사이트에서 계정을 만들어 얻을 수있는 무료 평가판 API를 제공합니다. 먼저 CleanLab의 Python 클라이언트를 설치해야합니다.

pip install --upgrade cleanlab-studio

Cleanlab은 ”와 같은 몇 가지 독점 모델을 지원합니다.GPT-4O‘,’ ‘GPT-4O- 미니‘,’ ‘O1- 예정‘,’ ‘Claude-3-sonnet‘,’ ‘Claude-3.5-sonnet‘,’ ‘Claude-3.5-Sonnet-V2‘그리고 다른 사람들. TLM이 GPT-4O의 답변에 신뢰도 점수를 부여하는 방법은 다음과 같습니다. 신뢰도 점수는 0에서 1까지이며, 여기서 더 높은 값은 더 큰 신뢰성을 나타냅니다.

from cleanlab_studio import Studio
studio = Studio("")  # Get your API key from above
tlm = studio.TLM(options={"log": ["explanation"], "model": "gpt-4o"}) # GPT, Claude, etc
#set the prompt
out = tlm.prompt("How many vowels are there in the word 'Abracadabra'.?")
#the TLM response contains the actual output 'response', trustworthiness score and explanation
print(f"Model's response = {out['response']}")
print(f"Trustworthiness score = {out['trustworthiness_score']}")
print(f"Explanation = {out['log']['explanation']}")

위의 코드는 질문에 대해 GPT-4O의 응답을 테스트했습니다.‘Abracadabra’라는 단어에는 몇 개의 모음이 있습니다.?“.”. TLM의 출력에는 모델의 답변 (응답), 신뢰성 점수 및 설명이 포함되어 있습니다. 이 코드의 출력은 다음과 같습니다.

Model's response = The word "Abracadabra" contains 6 vowels. The vowels are: A, a, a, a, a, and a.
Trustworthiness score = 0.6842228802750124
Explanation = This response is untrustworthy due to a lack of consistency in possible responses from the model. Here's one inconsistent alternate response that the model considered (which may not be accurate either):
5.

가장 진보 된 언어 모델이 그러한 간단한 작업에 대해 환각을 느끼고 잘못된 출력을 생성하는 방법을 알 수 있습니다. 다음은 같은 질문에 대한 응답과 신뢰도 점수입니다. Claude-3.5-Sonnet-V2.

Model's response = Let me count the vowels in 'Abracadabra':
A-b-r-a-c-a-d-a-b-r-a

The vowels are: A, a, a, a, a

There are 5 vowels in the word 'Abracadabra'.
Trustworthiness score = 0.9378276048845285
Explanation = Did not find a reason to doubt trustworthiness.

Claude-3.5-Sonnet-V2 올바른 출력을 생성합니다. 두 모델의 응답을 다른 질문과 비교해 봅시다.

from cleanlab_studio import Studio
import markdown
from IPython.core.display import display, Markdown

# Initialize the Cleanlab Studio with API key
studio = Studio("")  # Replace with your actual API key

# List of models to evaluate
models = ["gpt-4o", "claude-3.5-sonnet-v2"]

# Define the prompt
prompt_text = "Which one of 9.11 and 9.9 is bigger?"

# Loop through each model and evaluate
for model in models:
   tlm = studio.TLM(options={"log": ["explanation"], "model": model})
   out = tlm.prompt(prompt_text)
  
   md_content = f"""
## Model: {model}

**Response:** {out['response']}

**Trustworthiness Score:** {out['trustworthiness_score']}

**Explanation:** {out['log']['explanation']}

---
"""
   display(Markdown(md_content))

다음은 두 모델의 응답입니다.

GPT-4O 및 Claude-3.5-Sonnet-V2에 의해 생성 된 잘못된 출력, 낮은 신뢰성 점수로 표시

Open-Source LLMS에 대한 신뢰도 점수도 생성 할 수 있습니다. 최근에 많은 과장된 오픈 소스 LLM : DeepSeek-R1을 확인해 봅시다. 나는 사용할 것이다 Deepseek-R1-Distill-Llama-70b메타를 기반으로합니다 LLAMA-3.3–70B 강조 모델 전문가 (MOE) 모델의 DeepSeek의 더 큰 671 억 파라미터 혼합물에서 증류했습니다. 지식 증류는 미리 훈련 된 대형 모델 인 “교사 모델”의 학습을 더 작은 “학생 모델”으로 전송하는 것을 목표로하는 기계 학습 기술입니다.

import streamlit as st
from langchain_groq.chat_models import ChatGroq
import os
os.environ["GROQ_API_KEY"]=st.secrets["GROQ_API_KEY"]
# Initialize the Groq Llama Instant model
groq_llm = ChatGroq(model="deepseek-r1-distill-llama-70b", temperature=0.5)
prompt = "Which one of 9.11 and 9.9 is bigger?"
# Get the response from the model
response = groq_llm.invoke(prompt)
#Initialize Cleanlab's studio
studio = Studio("226eeab91e944b23bd817a46dbe3c8ae") 
cleanlab_tlm = studio.TLM(options={"log": ["explanation"]})  #for explanations
#Get the output containing trustworthiness score and explanation
output = cleanlab_tlm.get_trustworthiness_score(prompt, response=response.content.strip())
md_content = f"""
## Model: {model}
**Response:** {response.content.strip()}
**Trustworthiness Score:** {output['trustworthiness_score']}
**Explanation:** {output['log']['explanation']}
---
"""
display(Markdown(md_content))

다음은 출력입니다 Deepseek-R1-Distill-Llama-70b 모델.

신뢰도 높은 점수가 높은 DeepSeek-R1-Distill-Llama-70B 모델의 올바른 출력

신뢰할 수있는 걸레를 개발합니다

우리는 이제 Rag에서 LLM 응답의 신뢰성을 측정 할 수있는 방법을 보여주기 위해 Rag를 개발할 것입니다. 이 래그는 주어진 링크에서 데이터를 긁어 내고 Markdown 형식으로 구문 분석하고 벡터 저장소를 만들어 개발됩니다.

다음 코드에는 다음 라이브러리를 설치해야합니다.

pip install llama-parse llama-index-core llama-index-embeddings-huggingface 
llama-index-llms-cleanlab requests beautifulsoup4 pdfkit nest-asyncio

HTML을 PDF 형식으로 렌더링하려면 설치해야합니다. wkhtmltopdf 웹 사이트에서 명령 줄 도구.

다음 라이브러리가 수입됩니다.

from llama_parse import LlamaParse
from llama_index.core import VectorStoreIndex
import requests
from bs4 import BeautifulSoup
import pdfkit
from llama_index.readers.docling import DoclingReader
from llama_index.core import Settings
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.llms.cleanlab import CleanlabTLM
from typing import Dict, List, ClassVar
from llama_index.core.instrumentation.events import BaseEvent
from llama_index.core.instrumentation.event_handlers import BaseEventHandler
from llama_index.core.instrumentation import get_dispatcher
from llama_index.core.instrumentation.events.llm import LLMCompletionEndEvent
import nest_asyncio
import os

다음 단계에는 Python의 주어진 URL에서 데이터를 긁어내는 것이 포함됩니다. BeautifulSoup 라이브러리, PDF 파일로 스크래프 데이터를 저장합니다 pdfkitPDF (S)에서 Markdown 파일로의 데이터를 사용하여 부름 LLM 및 LLM 사용 사례로 구축 된 Genai Native 문서 구문 분석 플랫폼입니다.

먼저 fleanlabtlm 및 임베딩 모델에서 사용할 LLM을 구성합니다 (포옹 페이스 임베딩 모델 BAAI/BGE-SMALL-EN-V1.5) 이는 스크랩 된 데이터의 임베딩을 계산하여 벡터 저장소를 생성하는 데 사용됩니다.

options = {
   "model": "gpt-4o",
   "max_tokens": 512,
   "log": ["explanation"]
}
llm = CleanlabTLM(api_key="", options=options)#Get your free API from 
Settings.llm = llm
Settings.embed_model = HuggingFaceEmbedding(
   model_name="BAAI/bge-small-en-v1.5"
)

이제 사용자 정의 이벤트 핸들러를 정의 할 것입니다. GetTrustworthinessScore기본 이벤트 처리기 클래스에서 파생됩니다. 이 핸들러는 LLM 완료가 끝나면 트리거되고 응답 메타 데이터에서 신뢰도 점수를 추출합니다. 도우미 기능, Display_ResponseLLM의 응답과 함께 신뢰도 점수를 표시합니다.

# Event Handler for Trustworthiness Score
class GetTrustworthinessScore(BaseEventHandler):
   events: ClassVar[List[BaseEvent]] = []
   trustworthiness_score: float = 0.0
   @classmethod
   def class_name(cls) -> str:
       return "GetTrustworthinessScore"
   def handle(self, event: BaseEvent) -> Dict:
       if isinstance(event, LLMCompletionEndEvent):
           self.trustworthiness_score = event.response.additional_kwargs.get("trustworthiness_score", 0.0)
           self.events.append(event)
       return {}
# Helper function to display LLM's response
def display_response(response):
   response_str = response.response
   trustworthiness_score = event_handler.trustworthiness_score
   print(f"Response: {response_str}")
   print(f"Trustworthiness score: {round(trustworthiness_score, 2)}")

이제 주어진 URL에서 데이터를 긁어 PDF를 생성합니다. 데모를 위해, 우리는 큰 언어 모델에 대한이 Wikipedia 기사에서만 데이터를 폐기합니다 (Creative Commons Attribution-Sharealike 4.0 라이센스).

메모: 독자는 항상 긁어 낼 컨텐츠/데이터의 상태를 두 번 확인하고 그렇게 할 수 있도록하는 것이 좋습니다.

다음 코드 조각은 HTTP 요청을하고 사용하여 주어진 URL의 데이터를 긁어냅니다. BeautifulSoup HTML 컨텐츠를 구문 분석하는 파이썬 라이브러리. HTML 컨텐츠는 프로토콜 관련 URL을 절대적으로 변환하여 정리됩니다. 그 후, 스크랩 된 컨텐츠는 PDF 파일로 변환됩니다. pdfkit.

##########################################
# PDF Generation from Multiple URLs
##########################################
# Configure wkhtmltopdf path
wkhtml_path = r'C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe'
config = pdfkit.configuration(wkhtmltopdf=wkhtml_path)
# Define URLs and assign document names
urls = {
   "LLMs": "
}
# Directory to save PDFs
pdf_directory = "PDFs"
os.makedirs(pdf_directory, exist_ok=True)
pdf_paths = {}
for doc_name, url in urls.items():
   try:
       print(f"Processing {doc_name} from {url} ...")
       response = requests.get(url)
       soup = BeautifulSoup(response.text, "html.parser")
       main_content = soup.find("div", {"id": "mw-content-text"})
       if main_content is None:
           raise ValueError("Main content not found")
       # Replace protocol-relative URLs with absolute URLs
       html_string = str(main_content).replace('src=" 'src=".replace('href=" 'href="
       pdf_file_path = os.path.join(pdf_directory, f"{doc_name}.pdf")
       pdfkit.from_string(
           html_string,
           pdf_file_path,
           options={'encoding': 'UTF-8', 'quiet': ''},
           configuration=config
       )
       pdf_paths[doc_name] = pdf_file_path
       print(f"Saved PDF for {doc_name} at {pdf_file_path}")
   except Exception as e:
       print(f"Error processing {doc_name}: {e}")

스크랩 된 데이터로부터 PDF를 생성 한 후, 우리는이 PDF를 사용하여 구문 분석합니다. 부름. 마크 다운 형식으로 내용을 추출하고 문서 이름 및 페이지 번호와 함께 문서를 페이지에서 구문 분석하기 위해 구문 분석 지침을 설정했습니다. 이 추출 된 엔티티 (페이지)를 사용합니다 노드. 파서는 추출 된 노드를 반복하고 나중에 참조를 용이하게하는 인용 헤더를 추가하여 각 노드의 메타 데이터를 업데이트합니다.

##########################################
# Parse PDFs with LlamaParse and Inject Metadata
##########################################

# Define parsing instructions (if your parser supports it)
parsing_instructions = """Extract the document content in markdown.
Split the document into nodes (for example, by page).
Ensure each node has metadata for document name and page number."""
      
# Create a LlamaParse instance
parser = LlamaParse(
   api_key="",  #Replace with your actual key
   parsing_instructions=parsing_instructions,
   result_type="markdown",
   premium_mode=True,
   max_timeout=600
)
# Directory to save combined Markdown files (one per PDF)
output_md_dir = os.path.join(pdf_directory, "markdown_docs")
os.makedirs(output_md_dir, exist_ok=True)
# List to hold all updated nodes for indexing
all_nodes = []
for doc_name, pdf_path in pdf_paths.items():
   try:
       print(f"Parsing PDF for {doc_name} from {pdf_path} ...")
       nodes = parser.load_data(pdf_path)  # Returns a list of nodes
       updated_nodes = []
       # Process each node: update metadata and inject citation header into the text.
       for i, node in enumerate(nodes, start=1):
           # Copy existing metadata (if any) and add our own keys.
           new_metadata = dict(node.metadata) if node.metadata else {}
           new_metadata["document_name"] = doc_name
           if "page_number" not in new_metadata:
               new_metadata["page_number"] = str(i)
           # Build the citation header.
           citation_header = f"[{new_metadata['document_name']}, page {new_metadata['page_number']}]\n\n"
           # Prepend the citation header to the node's text.
           updated_text = citation_header + node.text
           new_node = node.__class__(text=updated_text, metadata=new_metadata)
           updated_nodes.append(new_node)
       # Save a single combined Markdown file for the document using the updated node texts.
       combined_texts = [node.text for node in updated_nodes]
       combined_md = "\n\n---\n\n".join(combined_texts)
       md_filename = f"{doc_name}.md"
       md_filepath = os.path.join(output_md_dir, md_filename)
       with open(md_filepath, "w", encoding="utf-8") as f:
           f.write(combined_md)
       print(f"Saved combined markdown for {doc_name} to {md_filepath}")
       # Add the updated nodes to the global list for indexing.
       all_nodes.extend(updated_nodes)
       print(f"Parsed {len(updated_nodes)} nodes from {doc_name}.")
   except Exception as e:
       print(f"Error parsing {doc_name}: {e}")

이제 벡터 스토어와 쿼리 엔진을 만듭니다. 우리는 질문에 답할 때 LLM의 행동을 안내하기 위해 고객 프롬프트 템플릿을 정의합니다. 마지막으로, 생성 된 인덱스가있는 쿼리 엔진을 만듭니다. 각 쿼리에 대해 쿼리와 의미 론적 유사성을 기반으로 벡터 저장소에서 상위 3 개의 노드를 검색합니다. LLM은이 검색된 노드를 사용하여 최종 답변을 생성합니다.

##########################################
# Create Index and Query Engine
##########################################
# Create an index from all nodes.
index = VectorStoreIndex.from_documents(documents=all_nodes)
# Define a custom prompt template that forces the inclusion of citations.
prompt_template = """
You are an AI assistant with expertise in the subject matter.
Answer the question using ONLY the provided context.
Answer in well-formatted Markdown with bullets and sections wherever necessary.
If the provided context does not support an answer, respond with "I don't know."
Context:
{context_str}
Question:
{query_str}
Answer:
"""
# Create a query engine with the custom prompt.
query_engine = index.as_query_engine(similarity_top_k=3, llm=llm, prompt_template = prompt_template)
print("Combined index and query engine created successfully!")

이제 래그를 테스트하여 일부 쿼리와 해당 신뢰도 점수를 테스트 해 봅시다.

query = "When is mixture of experts approach used?"
response = query_engine.query(query)
display_response(response)
쿼리에 대한 응답 ‘전문가 혼합 접근법은 언제 사용됩니까?’ (저자에 의한 이미지)
query = "How do you compare Deepseek model with OpenAI's models?"
response = query_engine.query(query)
display_response(response)
쿼리에 대한 응답 ‘DeepSeek 모델과 OpenAI 모델을 어떻게 비교합니까?’ (저자에 의한 이미지)

직접적인 추론 또는 래그를 통해 생성 된 LLM의 응답에 신뢰도 점수를 지정하면 AI의 출력의 신뢰성을 정의하고 필요한 경우 인간 검증 우선 순위를 정합니다. 이것은 잘못되거나 신뢰할 수없는 반응이 심각한 결과를 초래할 수있는 중요한 영역에 특히 중요합니다.

그게 다 사람들이야! 기사가 마음에 드시면 나를 따르십시오 중간 그리고 LinkedIn.



출처 참조

Post Comment

당신은 놓쳤을 수도 있습니다