Solrã§ãRAGã§ããããïŒ
ã¯ããã«
ãã®èšäºã¯ãæ å ±æ€çŽ¢ã»æ€çŽ¢æè¡ Advent Calendar 2023 ã® 23æ¥ç®ã®èšäºã§ãã
æ¬èšäºã§ã¯ãSolrãããã¯ãšã³ãã«ããŠãæè¿æµè¡ãã® RAG ãããŠã¿ãŸãã
RAGãšã¯
åäžå€ãã®èšäºã§è§£èª¬ãããŠããã®ã§ä»ãã説æãããŸã§ããªãããã§ããããŠãŒã¶ããã®è³ªåã«åçããããã«å¿ èŠãããªå å®¹ãæžãããæç« ãæ€çŽ¢ãããã®æç« ã LLM ãžã®å ¥åïŒããã³ããïŒã«ä»ãå ããŠå ¥åããææ³ã§ãã
ããŸããŸãªåãããã«çããŠããã ChatGPT ã®èœåã«é©ããããŸãããç¥ããªãç¥èã«é¢ããŠã¯åœç¶ã®ããšãªããçããããŸããã äŸãã°ãChatGPT ã®ç¡æçã§ãã GPT-3.5 ã«ã€ããŠã¯ã2021 幎 9 æãŸã§ã® Web äžã®æ å ±ãããšã«åŠç¿ãããŠããã®ã§ããã以åŸã«äžã«åºãæ å ±ã«ã€ããŠã¯ç¥ããŸããã ãŸããWeb äžã«å ¬éãããŠããæ å ±æºã«é¢ããŠããç¥ããªãã®ã§ãèªç€Ÿã®ãµãŒãã¹åºæã®æ å ±ã«é¢ããåçã瀟å€ç§æ å ±ã«é¢ããŠã¯åœç¶ãªããçããããŸããã
ããããªãããšã«ã€ããŠã¯ãäžåŸçããããŸãããšèšã£ãŠãããã°ãŸã ããã®ã§ãããããããåä»ãªããšãèµ·ããåŸãŸãã ãã«ã·ããŒã·ã§ã³ïŒå¹»èŠïŒãšåŒã°ããçŸè±¡ã§ã誀ã£ãåçã§ããã«ãããããããèªä¿¡æºã ã«çå®ã§ãããã®ããã«åçããŠããŸãããšãããã®ã§ã[1]ã
ãå匷çšéã§ LLM ãè¿ããŠãããµã³ãã«ã³ãŒããåãããããšã©ãŒã§åããªãã£ãçšåºŠã§æžãã°ãŸã ããã§ããããããã¯ããšããŠãªãªãŒã¹ãããã®ãåå «çŸç¶æ ã§ã¯äŒç€Ÿã®ä¿¡çšåé¡ã«ããããã®ã§èŽåœçã§ãã ä»®ã«è¿œå ã§ç¥èãä»äžã§ãããšããŠããAI ã¯ãããçå®ã§ãããåŠãã¯é¢ç¥ããªãã®ã§ããã«ã·ããŒã·ã§ã³ãå®å šã«é²æ¢ããããšã¯ã§ããŸããã
ãããžã®å¯Ÿå¿çãšããŠä»äžçªæ³šç®ãããŠããææ³ããRAGïŒRetrieval Augmented GenerationïŒãšåŒã°ããææ³ã§ã[2]ã
RAG ã¯ã ããã³ãããšåŒã°ãã LLM ãžã®å ¥åæ å ±ã«ã¢ãã«å€éšã®æ å ±æºããã®æ€çŽ¢çµæãä»å ããŠãæ€çŽ¢çµæã«åºã¥ããåçããããŠããŸãã ã¢ãã«ã¯ããã³ããã«å«ãŸããŠãããªãã¡ã¬ã³ã¹æ å ±ãããšã«ãŠãŒã¶ããã®èŠæã«åçããã°ããã®ã§ãç¥èã«ãªãããšã§ãã£ãŠãæ£ç¢ºã«çããããããã«ãªãã®ã§ã¯ãªãããšããçºæ³ã§ãã

ãã®ãªãã¡ã¬ã³ã¹æ å ±ã®ååŸã®ããã«æ€çŽ¢ãšã³ãžã³ãžã®ãªã¯ãšã¹ããæããã¹ãããããããŸãã
Solrã§RAGããã
Qdrant ãªã©ã®ãã¯ãã«æ€çŽ¢ã«ç¹åããŠãããšã³ãžã³ã¯ãã¡ãããElasticsearch ã«ã€ããŠãLangchain ãšã®é£æºãå
¬åŒã«ãµããŒããããŠããŸã[3][4]ã
ç¹ã«ãã ãããªããã°ãããªãã«ãããã䜿ãã®ãéçºã³ã¹ãããããããããšæããŸãã
ãããæ¬èšäºã§ã¯ãã㊠Solr ãããã¯ãšã³ãã«äœ¿ãããšæããŸãã
çç±ã¯ç§ã Solr ã䜿ã£ãŠããããã§ããããã ãã§ãã
æè¿ã¯ãã£ãã Elasticsearch ã«äººæ°ãåãããã¡ã§ããããããããªãããã¿ã§ Solr ã䜿ã£ãŠãã人ããããšæããŸãã
æ¬èšäºã¯ãããªäººã«å±ãã°ãããªãšæããŸãã
ããŠãSolr ãš Langchain ã®é£æºç¶æ³ã§ãããçŸåš issue ã¯åºãŠãããã®ã®ã®å
¬åŒã«ã¯ãŸã ãµããŒããããŠããŸãã[5]ã
ãã ãæå¿ã®æ¹ãäœã£ãã©ã€ãã©ãªã¯ãããŸãã[6]ã
pipã§ç°¡åã«å
¥ããããŸãã
$ pip install eurelis-langchain-solr-vectorstore
Qdrant ã Elasticsearch ã§ãµããŒããããŠãããããªåºæ¬çãªã€ã³ã¿ãŒãã§ã€ã¹ã¯çšæãããŠããŸãã
ã§ãã®ã§ã仿€çŽ¢ãšã³ãžã³ãšåãããã« Solr ãšã飿ºã§ãããã§ãã
æ¬èšäºã§ã¯ãããã䜿ã£ãŠãSolr ãããã¯ãšã³ãã«RAGãã§ããã詊ããŠã¿ãããšæããŸãã
Usage
ã¡ãã£ãš README ãèŠãã ãã ãšäœ¿ãæ¹ããããã«ããã®ã§è§£èª¬ããŸãã
ãŸãã¯ãSolr åŽã§äºåã«ãã£ãŒã«ãã®èšå®ãããŸãã
ãã®èŸºãã¯ä»¥åã«è§£èª¬ããèšäºãããã®ã§ãããããåèã«ã³ã¬ã¯ã·ã§ã³ã®äœæãè¡ã£ãŠãããŸã[7]ã
äŸãã°ãããã¹ãããŒã¿ãšãã®ãã¯ãã«ããŒã¿ãæ ŒçŽãããã£ãŒã«ããçšæããŠãããŸãã
<field name="text" type="string" indexed="true" stored="true"/>
<field name="vector" type="knn_vector" indexed="true" stored="true"/>
<fieldType name="string" class="solr.StrField" sortMissingLast="true" docValues="true"/>
<fieldType name="knn_vector" class="solr.DenseVectorField" vectorDimension="768" similarityFunction="euclidean"/>

ç¶ã㊠Langchain ãã Solr ãšæ¥ç¶ããã¯ã©ã€ã¢ã³ãã€ã³ã¹ã¿ã³ã¹ãçšæããŸãã
from langchain.embeddings import HuggingFaceEmbeddings
from eurelis_langchain_solr_vectorstore import Solr
model_name = "pkshatech/GLuCoSE-base-ja"
embeddings = HuggingFaceEmbeddings(model_name=model_name) # you are free to use any embeddings method allowed by langchain
vector_store = Solr(embeddings, core_kwargs={
'page_content_field': 'text', # field containing the text content
'vector_field': 'vector', # field containing the embeddings of the text content
'core_name': 'langchain', # core name
'url_base': 'http://localhost:8983/solr' # base url to access solr
}) # with custom default core configuration
embeddings ã«ã¯äœ¿çšããã Embedding ã¢ãã«ãããŠãããŸãã
HugginFace ã§å
¬éãããŠããã¢ãã«ã¯ãããã䜿ããŸãã
æ¥æ¬èªLLMãŸãšããšãããã°ããããŸãšãããããŸããã®ã§ãããããã奜ã¿ã®ãã®ãéžã¶ãšãããšæããŸãã
Solr ã®åŒæ°ã«ã¯ããããæ¥ç¶å
ã® Solr ã®èšå®æ
å ±ãå®çŸ©ããŠãããŸãã
-
page_content_field: ãã¯ãã«æ€çŽ¢ã®çµæãšããŠããã®ãã£ãŒã«ãã®å€ãååŸããããéåžžããã¯ãã«ããŒã¿ã®å ã«ãªã£ãããã¹ãããŒã¿ãã£ãŒã«ããæå®ãããflã§ååŸã§ããå¿ èŠãããã®ã§ãSolr åŽã§stored="true"ãªã©ã«èšå®ããŠããå¿ èŠãããã -
vector_field: ãã¯ãã«æ€çŽ¢ã®å¯Ÿè±¡ãšãªããã£ãŒã«ãåãæå®ããã -
core_name: æ€çŽ¢å¯Ÿè±¡ãšãã Solr ã®ã³ã¢åãæå®ããã -
url_base: æ¥ç¶å ã® Solr ã®ãšã³ããã€ã³ããæå®ããã
ã€ã³ããã¯ã¹
æ¥ç¶ã¯ã©ã€ã¢ã³ããçšæåºæ¥ããã Langchain ã®ã€ã³ã¿ãŒãã§ã€ã¹ã䜿ã£ãŠããã¹ãã® Embedding ããã€ã³ããã¯ã¹ãã§ããŸãã
vector_store.add_documents ã䜿ãã°ãããã¹ããæž¡ãã ãã§å
ã®ããã¹ããšãã® Embedding çµæãã€ã³ããã¯ã¹ããŠããã¡ãããŸãã
from langchain.docstore.document import Document
docs = [{"text": "Solrã§ãRAGã§ããããïŒ"}]
metadatas = [{"tag": "solr"}]
indexes = [Document(page_content=doc["text"], metadata=metadata) for doc, metadata in zip(docs, metadatas)]
vector_store.add_documents(indexes)
add_documents ã«ã¯ LangChain ã§çšæãããŠããå°çšã®åã§ããå¿
èŠãããã®ã§ãããããããã®å圢åŒã«å€æããŠãããŸãã
page_content ã« Embedding ãããããããã¹ãããŒã¿ãæž¡ããŠãããŸãã
åãã©ãããããŠããã®ã§ãæ©æ¢°åŠç¿é¢é£ã®åŠçãããããã£ãŠããªããŠãããã£ã2è¡ã ãã§äœ¿ããŠããŸããŸãã
ãã®ä»ã®ãã£ãŒã«ãã«ã€ããŠãã¡ã¿ããŒã¿ãšããŠæž¡ãã°ã€ã³ããã¯ã¹ã§ããŸãã

æ€çŽ¢
æ€çŽ¢ã«ã€ããŠãç°¡åã§ãã
ã€ã³ããã¯ã¹ã®ãšããšåããEmbedding ã¢ãã«ãæå®ããŠã¯ãšãªãæž¡ãã ãã§ãã
query = "Solrã§ã®ãã¯ãã«æ€çŽ¢ã®å§ãæ¹ãæããŠãã ããã"
retriever = vector_store.as_retriever()
docs = retriever.get_relevant_documents(query=query)
docs ã«ã¯ãã€ã³ããã¯ã¹æãšåã Document åã§ãããããããã¥ã¡ã³ãã®å
ããã¹ããååŸã§ããŸãã
ããšã¯ããããªãã¡ã¬ã³ã¹æ
å ±ãšããŠLLMã«æž¡ãã°OKã§ãã
å¿ èŠã«å¿ããŠããŸããŸãªãªãã·ã§ã³ãæå®ã§ããŸãã
retriever = vector_store.as_retriever(
search_typeã=ã"similarity_score_threshold", # ã¹ã³ã¢éŸå€ã䜿çšããããšãã«æå®
search_kwargsã=ã{
"k": k, # topK ä»¶ã®ããã¥ã¡ã³ãã ãååŸãã
"filter": {"tag": "solr"}, # Solr ã® fq ã®æ¡ä»¶ãæå®ã§ããã䜿çšã§ãããã£ãŒã«ãã¯ã€ã³ããã¯ã¹æã« metadata ã§æž¡ãããã£ãŒã«ãã®ã¿
"score_threshold": 0.5 # score ã®éŸå€ããããäžåã£ãããã¥ã¡ã³ãã ãååŸãã
}
)
RAG ã§åççæãããŠã¿ã
ãã£ãããªã®ã§ãRAGã䜿ã£ãŠã¢ãã«ã¯çµ¶å¯Ÿã«ç¥ããªãã§ããã質åã«å¯ŸããŠåçãããŠã¿ãŸãã
ããããå
㯠Solr ã«éããªããæ±çšçãªã話ã§ãã
ChatGPTã§ã®RAGã«ã€ããŠã¯å€ãã®èšäºã§è§£èª¬ãããŠããã®ã§ãæ¥æ¬èªå¯Ÿå¿ããŠããããŒã«ã«LLMã§ãã£ãŠã¿ãŸãã
ä»åã¯ãcyberagent/calm2-7b-chat · Hugging Face ã䜿ã£ãŠã¿ãŸãã
Solr å ¬åŒããã¥ã¡ã³ãã® Dense Vector Search :: Apache Solr Reference Guide ã®ç« ãæ¥æ¬èªèš³ããŠã€ã³ããã¯ã¹ãããŠãããŸãã
ãã®ç¶æ ã§ãé©åœãªãã³ãã¬ãŒããçšæããŠããããã¯ãã«æ€çŽ¢ã®çµæãšãŠãŒã¶å ¥åãåã蟌ãã§ LLM ã«å ¥åããŸãã
context = "ãã¯ãã«æ€çŽ¢ã§ãããããããã¥ã¡ã³ã"
query = "ãŠãŒã¶ã®å
¥å"
prompt = """USER: 貎æ¹ã¯ãŠãŒã¶ãŒã®è³ªåã«çããAIã¢ã·ã¹ã¿ã³ãBotã§ãã
ãŠãŒã¶ãŒã®è³ªåã«å¯ŸããŠé©åãªã¢ããã€ã¹ãçããŸãã
æ
å ±ãšããŠã以äžã®å
容ãåèã«ããŠãã ããã
========
{context}
========
ããŠãã{query}ããšãã質åã«å¯ŸããŠãäžèšã®æ
å ±ãå
ã«ãçããèããŠã¿ãŸãããã
ASSISTANT: """.format(context=context, query=query)
ããã§ã¯ããSolrã§ã®ãã¯ãã«æ€çŽ¢ã®å§ãæ¹ãæããŠãã ããã ãšèããŠã¿ãŸãã
RAG ãªãã ãš Lucene ã«çŽæ¥æãå ãããããªææ¡ãããŠããã®ã«å¯ŸããRAG ããã ãšã¡ãããšã¹ããŒãå®çŸ©ã®æ¹æ³ãªã©ãçããŠãããŸã[8]ã


ã»ãã«ãç§ã®ãµãŒã¯ã«ã§ããããã¡ã£ãšã«ãã§ã«ã€ããŠããšãã絶察ã«ã¢ãã«ãç¥ããªãã§ããã質åãããŠã¿ãŸãã

å®ã¯ããã®è³ªåã«ã€ããŠã¯ãã¯ãã«æ€çŽ¢ã®çµæãããããããã¥ã¡ã³ãã¯æ¬¡ã®ããã«ãªã£ãŠããŸãã
ãã¡ã£ãšã«ãã§ã¯æ€çŽ¢ãšã³ãžã³ãããã«ãŸã€ããèªç¶èšèªåŠçãäžå¿ã«ãµãŒã¯ã«äž»ã§ãããããã¿ãã¡ããèå³ãæã£ãããšãæ¥ã ã¢ãŠããããããŠããå人ãµãŒã¯ã«ã§ããWord2VecãSolré¢é£ã®æžç±ã®å·çãé åžæŽ»åãè¡ã£ãŠããŸãã代衚çãªæžç±ã«ã¯ã仿¥ããå§ãããã¯ãã«æ€çŽ¢ãããWord2Vec䜿ãåãããã¯ããã5åã§ç޹ä»Streamlitããªã©ããããŸããæè¡æžå žãææžåãªã©ã®ã€ãã³ãã«ãåºå±ããŠããã®ã§ãèå³ããã°èŠããŠã¿ãŠãã ããããµãŒã¯ã«ããŒã ããŒãžããããŸãã(https://sashimimochi.netlify.app/)
ãšãã©ãããRAGãŸã§ããå¿
èŠã¯ãªãããã¯ãã«æ€çŽ¢ã®çµæããã®ãŸãŸè¿ãã°ãããããããšããæèŠãèŠãããŸãã
ããã«ã¯ç§ãäžéšåæããããšãã§ã¯ãããŸãã
ãšã¯ããã確ãã«æ å ±éã¯ãããããããã¥ã¡ã³ããã®ãã®ããå¢ããŠããŸããããSolr ã§ã®ãã¯ãã«æ€çŽ¢ã®äŸãªã©ã§ã¯é©åºŠã«èŠçŽãããããç®æ¡æžã圢åŒã§æ§é åãããŠããŠèªã¿ããããªã£ãŠããŸããæåããŸããã
ãããã«
æ¬èšäºã§ã¯ Solr ãããã¯ãšã³ãã«ãã RAG ã詊ããŠã¿ãŸããã
ãªããªãå¯èœæ§ãæããçµæãåŸãããŸããã®ã§ãã¿ãªããããã² RAG 詊ããŠã¿ãŠãã ããã
æ¬èšäºã§ã¯ãããããã¹ãŠãé 調ã«ããŸããã£ããã®ããã«æžããŸããããå®ã¯è£ã§ã¯çµæ§èŠåŽããŸããã
现ãããœãŒã¹ã³ãŒãããããã£ãèŠåŽè©±ã«ã€ããŠã¯è¿æ¥å¥èšäºã«ããŠæçš¿ããããšæããŸãã
ãæ¥œãã¿ã«ã
-
https://xtech.nikkei.com/atcl/nxt/column/18/00692/082900114/ â©ïž
-
https://python.langchain.com/docs/integrations/vectorstores/qdrant â©ïž
-
https://python.langchain.com/docs/integrations/vectorstores/elasticsearch â©ïž
-
https://github.com/langchain-ai/langchain/issues/7273 â©ïž
-
https://github.com/Eurelis/Eurelis-Langchain-SolR-VectorStore â©ïž
-
https://zenn.dev/sashimimochi/articles/1957974d64d571 â©ïž
Discussion