投稿者

インターシステムズジャパン
記事 Toshihiko Minamoto · 11月 21, 2024 6m read

IRIS-RAG-Gen_ IRIS Vector Search による ChatGPT RAG アプリケーションのパーソナライズ

image
コミュニティの皆さん、こんにちは。
この記事では、iris-RAG-Gen という私のアプリケーションをご紹介します。

iris-RAG-Gen は、IRIS Vector Search の機能を使用して、Streamlit ウェブフレームワーク、LangChain、および OpenAI で ChatGPT をパーソナライズするジェネレーティブ AI 検索拡張生成(RAG: Retrieval-Augmented Generation)アプリケーションです。 このアプリケーションは IRIS をベクトルストアとして使用します。
image

アプリケーションの機能

  • ドキュメント(PDF または TXT)を IRIS に取り込む
  • 選択されたドキュメントの取り込みを使ってチャットする
  • ドキュメントの取り込みを削除する
  • OpenAI ChatGPT

ドキュメント(PDF または TXT)を IRIS に取り込む

以下の手順に従って、ドキュメントを取り込みます。

  • OpenAI キーを入力します。
  • ドキュメント(PDF または TXT)を選択します。
  • ドキュメントの説明を入力します。
  • 「Ingest Document」ボタンをクリックします。

image
 

ドキュメントの取り込み機能は、ドキュメントの詳細を rag_documents テーブルに挿入し、ベクトルデータを保存する 'rag_document + id'(rag_documents の ID)テーブルを作成します。

image

以下の Python コードは選択されたドキュメントをベクトルに保存します。

from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.document_loaders import PyPDFLoader, TextLoader
from langchain_iris import IRISVector
from langchain_openai import OpenAIEmbeddings
from sqlalchemy import create_engine,text

class RagOpr: #Ingest document. Parametres contains file path, description and file type def ingestDoc(self,filePath,fileDesc,fileType): embeddings = OpenAIEmbeddings() #Load the document based on the file type if fileType == "text/plain": loader = TextLoader(filePath)
elif fileType == "application/pdf": loader = PyPDFLoader(filePath)

    #load data into documents
    documents = loader.load()        
    
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=400, chunk_overlap=0)
    #Split text into chunks
    texts = text_splitter.split_documents(documents)
    
    #Get collection Name from rag_doucments table. 
    COLLECTION_NAME = self.get_collection_name(fileDesc,fileType)
           
    # function to create collection_name table and store vector data in it.
    db = IRISVector.from_documents(
        embedding=embeddings,
        documents=texts,
        collection_name = COLLECTION_NAME,
        connection_string=self.CONNECTION_STRING,
    )

#Get collection name
def get_collection_name(self,fileDesc,fileType):
    # check if rag_documents table exists, if not then create it 
    with self.engine.connect() as conn:
        with conn.begin():     
            sql = text("""
                SELECT *
                FROM INFORMATION_SCHEMA.TABLES
                WHERE TABLE_SCHEMA = 'SQLUser'
                AND TABLE_NAME = 'rag_documents';
                """)
            result = []
            try:
                result = conn.execute(sql).fetchall()
            except Exception as err:
                print("An exception occurred:", err)               
                return ''
            #if table is not created, then create rag_documents table first
            if len(result) == 0:
                sql = text("""
                    CREATE TABLE rag_documents (
                    description VARCHAR(255),
                    docType VARCHAR(50) )
                    """)
                try:    
                    result = conn.execute(sql) 
                except Exception as err:
                    print("An exception occurred:", err)                
                    return ''
    #Insert description value 
    with self.engine.connect() as conn:
        with conn.begin():     
            sql = text("""
                INSERT INTO rag_documents 
                (description,docType) 
                VALUES (:desc,:ftype)
                """)
            try:    
                result = conn.execute(sql, {'desc':fileDesc,'ftype':fileType})
            except Exception as err:
                print("An exception occurred:", err)                
                return ''
            #select ID of last inserted record
            sql = text("""
                SELECT LAST_IDENTITY()
            """)
            try:
                result = conn.execute(sql).fetchall()
            except Exception as err:
                print("An exception occurred:", err)
                return ''
    return "rag_document"+str(result[0][0])

 

管理ポータルで以下の SQL コマンドを入力し、ベクトルデータを取得します。

SELECT top 5
id, embedding, document, metadata
FROM SQLUser.rag_document2

image

 

選択されたドキュメントの取り込みを使ってチャットする

チャットオプションの選択セクションから「Document」を選択して質問を入力します。アプリケーションはベクトルデータを読み取り、関連する回答を返します。
image
以下の Python コードは、選択されたドキュメントをべく鳥に保存します。

from langchain_iris import IRISVector
from langchain_openai import OpenAIEmbeddings,ChatOpenAI
from langchain.chains import ConversationChain
from langchain.chains.conversation.memory import ConversationSummaryMemory
from langchain.chat_models import ChatOpenAI

class RagOpr: def ragSearch(self,prompt,id): #Concat document id with rag_doucment to get the collection name COLLECTION_NAME = "rag_document"+str(id) embeddings = OpenAIEmbeddings() #Get vector store reference db2 = IRISVector ( embedding_function=embeddings,
collection_name=COLLECTION_NAME, connection_string=self.CONNECTION_STRING, ) #Similarity search docs_with_score = db2.similarity_search_with_score(prompt) #Prepair the retrieved documents to pass to LLM relevant_docs = ["".join(str(doc.page_content)) + " " for doc, _ in docs_with_score] #init LLM llm = ChatOpenAI( temperature=0,
model_name="gpt-3.5-turbo" ) #manage and handle LangChain multi-turn conversations conversation_sum = ConversationChain( llm=llm, memory= ConversationSummaryMemory(llm=llm), verbose=False ) #Create prompt template = f""" Prompt: {prompt} Relevant Docuemnts: {relevant_docs} """ #Return the answer resp = conversation_sum(template) return resp['response']


詳細については、iris-RAG-Gen の Open Exchange アプリケーションページをご覧ください。

よろしくお願いします。