[LLM] Utilisation de Langchain [3] (question et réponse basées sur des documents)

1. Questions-réponses basées sur des documents

1. Créer un magasin de vecteurs

  • CSVLoader charge les données csv et le chargeur est utilisé conjointement avec le modèle
  • Utilisez le stockage vectoriel de recherche de mémoire Dock Array, comme stockage vectoriel de mémoire, pas besoin de vous connecter à une base de données externe
  • Créer un magasin de vecteurs : importez un index, le créateur d'index de magasin de vecteurs
from langchain.chains import RetrievalQA #检索QA链,在文档上进行检索
from langchain.chat_models import ChatOpenAI #openai模型
from langchain.document_loaders import CSVLoader #文档加载器,采用csv格式存储
from langchain.vectorstores import DocArrayInMemorySearch #向量存储
from IPython.display import display, Markdown #在jupyter显示信息的工具

file = 'OutdoorClothingCatalog_1000.csv'
loader = CSVLoader(file_path=file)
#查看数据
import pandas as pd
data = pd.read_csv(file,header=None)

Les données sont des données texte avec des champs comme nameet :description
insérez la description de l'image ici

# 创建向量存储
from langchain.indexes import VectorstoreIndexCreator #导入向量存储索引创建器
'''
将指定向量存储类,创建完成后,我们将从加载器中调用,通过文档记载器列表加载
'''
index = VectorstoreIndexCreator(
    vectorstore_cls=DocArrayInMemorySearch
).from_loaders([loader])
query ="Please list all your shirts with sun protection \
in a table in markdown and summarize each one."
response = index.query(query)#使用索引查询创建一个响应,并传入这个查询
display(Markdown(response))#查看查询返回的内容

insérez la description de l'image ici
Vous avez un tableau Markdown avec les noms et descriptions de toutes les chemises avec protection solaire, les descriptions sont résumées.

'''
为刚才的文本创建embedding,准备将它们存储在向量存储中,使用向量存储上的from documents方法来实现。
该方法接受文档列表、嵌入对象,然后我们将创建一个总体向量存储
'''
db = DocArrayInMemorySearch.from_documents(
    docs, 
    embeddings
)
query = "Please suggest a shirt with sunblocking"
docs = db.similarity_search(query)#使用这个向量存储来查找与传入查询类似的文本,如果我们在向量存储中使用相似性搜索方法并传入一个查询,我们将得到一个文档列表
len(docs)# 我们可以看到它返回了四个文档

# 回答文档的相关问题
retriever = db.as_retriever() #创建检索器通用接口
llm = ChatOpenAI(temperature = 0.0,max_tokens=1024) #导入语言模型
qdocs = "".join([docs[i].page_content for i in range(len(docs))])  # 将合并文档中的所有页面内容到一个变量中
response = llm.call_as_llm(f"{
    
    qdocs} Question: Please list all your \
shirts with sun protection in a table in markdown and summarize each one.") #列出所有具有防晒功能的衬衫并在Markdown表格中总结每个衬衫的语言模型

La base de données vectorielle utilisée est chromadb. Encapsulé par la chaîne LangChain, créez une chaîne d'AQ de récupération pour répondre aux questions sur les documents récupérés. Pour créer une telle chaîne, nous allons passer quelques éléments différents

  • 1. Modèle de langage, génération de texte à la fin
  • 2. Le type de chaîne entrante, utilisé ici stuff, place tous les documents dans le contexte et appelle le modèle de langage
  • 3. Passer un retriever
qa_stuff = RetrievalQA.from_chain_type(
    llm=llm, 
    chain_type="stuff", 
    retriever=retriever, 
    verbose=True
)
query =  "Please list all your shirts with sun protection in a table \
in markdown and summarize each one."#创建一个查询并在此查询上运行链
response = qa_stuff.run(query)
display(Markdown(response))#使用 display 和 markdown 显示它

RetrievalQALa chaîne encapsule en fait les deux étapes de fusion des fragments de texte et d'appel du modèle de langage. S'il n'y a pas de chaîne RetrievalQA, nous devons l'implémenter comme ceci :

# 将检索出来的文本片段合并成一段文本
qdocs = "".join([docs[i].page_content for i in range(len(docs))])
# 将合并后的文本和问题一起传给LLM
response = llm.call_as_llm(f"{
    
    qdocs} Question: Please list all your \
shirts with sun protection in a table in markdown and summarize each one.") 

2. Différents types de chaînes

Que se passe-t-il si vous souhaitez effectuer le même type de réponse à une question sur plusieurs types de blocs différents ? L'expérience ci-dessus n'a renvoyé que 4 documents, s'il y a plusieurs documents, nous pouvons utiliser quelques méthodes différentes

  • Map Reduce
    transmet tous les morceaux au modèle de langage avec la question, obtient les réponses, utilise un autre appel de modèle de langage pour résumer toutes les réponses individuelles en une réponse finale, et il peut fonctionner sur n'importe quel nombre de documents. Un seul problème peut être traité en parallèle, nécessitant également plus d'appels. Il traite tous les documents comme indépendants
  • Affiner
    est utilisé pour boucler sur de nombreux documents, de manière itérative en fait, en s'appuyant sur les réponses des documents précédents, idéal pour les informations causales en avant et en arrière et en construisant progressivement des réponses au fil du temps, en fonction des résultats des appels précédents. Cela prend généralement plus de temps et nécessite essentiellement autant d'appels que Map Reduce
  • Map Re-rank
    fait un seul appel de modèle de langage par document, lui demande de renvoyer un score, choisit le score le plus élevé, cela repose sur le modèle de langage sachant quel devrait être le score, doit le dire, s'il est pertinent pour le document, ce devrait être le score élevé et les instructions de réglage fin là-bas, elles peuvent être traitées par lots relativement rapidement, mais plus chères
  • Stuff
    combine tout dans un seul document

2. Questions et réponses sur la base de connaissances locales

1.1 Cadre général

insérez la description de l'image ici

  • Points améliorés (directions):
    • Changer de modèle LLM
    • modèle d'intégration
    • méthode de segmentation de texte
    • Déploiement accéléré du modèle multi-cartes
    • Améliorer la qualité du rappel de récupération des top-k
  • Basé sur la confidentialité des données et le déploiement de la privatisation, il est pratique d'utiliser le grand modèle Langchain + pour le raisonnement

2. Segmentation du texte

Code source Langchain : https://github.com/hwchase17/langchain/blob/master/langchain/text_splitter.py

Paramètres communs du module de fractionnement de texte intégré de Langchain :

  • chunk_size : la taille du bloc de texte, c'est-à-dire la taille maximale du bloc de texte ;
  • chunk_overlap : indique le degré de chevauchement entre deux textes segmentés, la quantité maximale de chevauchement entre les blocs de texte, le maintien d'un certain chevauchement peut maintenir la continuité entre les blocs de texte et peut être construit à l'aide d'une fenêtre coulissante, ce qui est plus important.
  • length_function : la méthode utilisée pour calculer la longueur du bloc de texte, la valeur par défaut est de simplement calculer le nombre de caractères ;

Autres séparateurs de texte :
 Text Splitter LatexTextSplitter divise le texte en titres, titres, énumérations, etc. MarkdownTextSplitter divise le texte le long des en-têtes Markdown, des blocs de code ou des règles horizontales. NLTKTextSplitter utilise le séparateur PythonCodeTextSplitter de NLTK pour diviser le texte le long des définitions de classe et de méthode Python. RecursiveCharacterTextSplitter Séparateur de texte générique. Il prend en argument une liste de caractères et essaie de convertir tous les paragraphes (puis les phrases, Puis mots) assemblés SpacyTextSplitter Utilisez le séparateur TokenTextSplitter de Spacy pour diviser en fonction du nombre de jetons de openAl \begin{array}{|c|c|} \hline \text { text splitter} & \\ \hline \text { LatexTextSplitter } & \text { Fractionner le texte le long des en-têtes Latex, des titres, des énumérations, etc. } \\ \hline \text { MarkdownTextSplitter } & \begin{array}{l} \text { Diviser le long des en-têtes Markdown, des blocs de code ou des règles horizontales} \\ \text { Diviser le texte. } \end{array} \\ \hline \text { NLTKTextSplitter } & \text { Utiliser le séparateur de NLTK} \\ \hline \text { PythonCodeTextSplitter } & \text { Diviser le texte selon les définitions de classes et de méthodes Python. } \\ \hline \text { RecursiveCharacterTextSplitter } & \begin{array}{l} \text { Splitter pour le texte générique. Il prend une liste de caractères comme } \\ \text { argument, met tous les paragraphes (puis phrases, } \\ \text { puis mots) ensemble autant que possible} \end{array} \\ \hline \ text { SpacyTextSplitter } & \text { Utiliser le séparateur de Spacy} \\ \hline \text { TokenTextSplitter } & \text { Séparer selon le numéro de jeton de openAl} \\ \hline \end{array} séparateur de texte  LatexTextSplitter  MarkdownTextSplitter  NLTKTextSplitter  PythonCodeTextSplitter  RécursiveCharacterTextSplitterRecursiveCharacterTextSplitter  SpacyTextSplitter TokenTextSplitter  Fractionner le texte le long des en-têtes Latex , des en-têtes, des énumérations, etc.  Diviser le long des en-têtes Markdown , des blocs de code ou des règles horizontales  couper le texte.   Séparateur utilisant NLTK  Divisez le texte selon les définitions de classes et de méthodes Python .  Un séparateur pour le texte générique. Il prend une liste de caractères comme  paramètres essayez de mettre tous les paragraphes  ( puis les phrases  puis les mots mis  ensemble Utilisation du séparateur de Spacy   Fractionner selon le nombre de jetons d' openAl
Prenons directement une châtaigne, comme la segmentation du texte chinois et l'héritage des classes dans CharacterTextSplitterlangchain ChineseTextSplitter. Expression régulière sent_sep_patternpour faire correspondre les délimiteurs de phrases chinois (tels que point, point d'exclamation, bonjour, point-virgule, etc.) :

# 中文文本切分类
class ChineseTextSplitter(CharacterTextSplitter):
    def __init__(self, pdf: bool = False, **kwargs):
        super().__init__(**kwargs)
        self.pdf = pdf

    def split_text(self, text: str) -> List[str]:
        if self.pdf:
            text = re.sub(r"\n{3,}", "\n", text)
            text = re.sub('\s', ' ', text)
            text = text.replace("\n\n", "")
        sent_sep_pattern = re.compile('([﹒﹔﹖﹗.。!?]["’”」』]{0,2}|(?=["‘“「『]{1,2}|$))')  # del :;
        sent_list = []
        for ele in sent_sep_pattern.split(text):
            if sent_sep_pattern.match(ele) and sent_list:
                sent_list[-1] += ele
            elif ele:
                sent_list.append(ele)
        return sent_list

3. Processus graphique

insérez la description de l'image ici

Référence

[1] MedicalGPT: Training Medical GPT Model
[2] Comment gérer les limites de taux.openai
[3] Parler des composants de base du système de réponse aux questions de la base de connaissances du plug-in de grand modèle langchain: comment mieux analyser et segmenter un texte complexe non structuré
[ 4] Tout ce que vous devez savoir pour créer votre première application LLM vers la science des données
[5] Série LLM | 15 : Comment utiliser LangChain pour faire de longs documents question et réponse
[6] Grand modèle de système de dialogue de base de connaissances locales. tx ingénierie technique

Je suppose que tu aimes

Origine blog.csdn.net/qq_35812205/article/details/131741245
conseillé
Classement