vectorstore = MariaDBStore(
embedding_length=768,
embeddings=embeddings,
datasource="mariadb+mariadbconnector://root:1234@localhost:3306/exoluse",
collection_name="content" # 테이블명
)
# 2. 벡터 검색기 (retriever)
retriever = vectorstore.as_retriever(
search_type="similarity", # 또는 "similarity_score_threshold"
search_kwargs={"k": 5} # top 5
)
분명 테이블에는 데이터가 있다고...
docs1 = retriever.invoke("배추")
print(f"검색 결과 문서 수: {len(docs1)}")
for i, doc in enumerate(docs1):
print(f"[{i+1}] {doc.page_content[:100]}")
뭔가 이상하다. 내가 설정한 테이블이 아닌 것 같다...
250629 10:49:48 24 Connect root@localhost on exoluse using Socket
24 Query SET AUTOCOMMIT=0
24 Query SELECT VERSION()
24 Query SELECT DATABASE()
24 Query SELECT @@tx_isolation
24 Query SELECT @@sql_mode
24 Query SELECT @@lower_case_table_names
24 Query ROLLBACK
24 Query CREATE TABLE IF NOT EXISTS langchain_embedding (id VARCHAR(36) NOT NULL DEFAULT UUID_v7() PRIMARY KEY,content TEXT,metadata JSON,embedding VECTOR(768) NOT NULL,VECTOR INDEX idx_langchain_embedding_embedding_idx (embedding) ) ENGINE=InnoDB
24 Query CREATE TABLE IF NOT EXISTS langchain_collection(id UUID NOT NULL DEFAULT UUID_v7() PRIMARY KEY,label VARCHAR(256),metadata JSON,UNIQUE KEY idx_langchain_collection_label (label))
24 Query ALTER TABLE langchain_embedding ADD COLUMN IF NOT EXISTS collection_id uuid, ADD CONSTRAINT FOREIGN KEY IF NOT EXISTS langchain_embedding_collection_id_fkey (collection_id) REFERENCES langchain_collection(id) ON DELETE CASCADE
24 Query CREATE INDEX IF NOT EXISTS coll_id_idx ON langchain_embedding (collection_id)
24 Query COMMIT
24 Query ROLLBACK
25 Connect root@localhost on exoluse using Socket
25 Query SET AUTOCOMMIT=0
25 Query SELECT id FROM langchain_collection WHERE label='test_collection'
25 Query ROLLBACK
24 Prepare INSERT INTO langchain_collection(label, metadata) VALUES (?,?) RETURNING id
24 Execute INSERT INTO langchain_collection(label, metadata) VALUES ('test_collection','null') RETURNING id
24 Query COMMIT
24 Close stmt
24 Query ROLLBACK
25 Prepare INSERT INTO langchain_embedding (id, content, metadata, embedding, collection_id) VALUES (?,?,?,?,?) ON DUPLICATE KEY UPDATE content = VALUES(content), metadata = VALUES(metadata), embedding = VALUES(embedding)
25 Execute INSERT INTO langchain_embedding (id, content, metadata, embedding, collection_id) VALUES (?,?,?,?,?) ON DUPLICATE KEY UPDATE content = VALUES(content), metadata = VALUES(metadata), embedding = VALUES(embedding)
25 Query COMMIT
25 Close stmt
25 Query ROLLBACK
24 Prepare SELECT id, content, metadata, vec_distance_cosine(embedding, ?) as distance FROM langchain_embedding WHERE collection_id = ? ORDER BY distance ASC LIMIT ?
24 Execute SELECT id, content, metadata, vec_distance_cosine(embedding, '\�\�\�0;;\�\�\�\�\�\�U\�\�\�q\�?$\�<\�l\�<d\�\�\�߱ʻh\�\�;ڕ=\�\�\�<_\�\�:\�\0*=\�\�\�\'@\�T\�\�\�\�⭽\�\�~=\�\�\�\�[\�nμdPh\�+\�\�=\�\�:mN=\�4=\�\�\�y\�\�\�\�\�4bg\�\�\�K;\�\�9\�\�\�\�<\�<%\�6\�P\�D=!\�=\"\�\�\�\�\�\�<\"\�\�;2\�\�\�0\�ܼ\�\�\�<`\�\�;\�S\�<\�M_=\�\�\�=\�\�S\�\�Q\�\�\�\� =\�\�=E\�\�U\�\�\�#\�=L\�\�\�=\�X\�\�\�\�\�\�6=\�я=\�\�N\�\�s\�=\�\�=/xc\�\�\�F=\�\r\�<\�u\�\�3aA\�sP\�<\�64=;\\\�<\�ؗ<\�N \�\�G\�\�\�d\�\�>\�;\�\�\�\�U\�;\�\�\�<\�\�\�;\�\�\�=x\�:\�[u=\�H=;\�\�;\�Ћ<Aż\�\�=\�\�d=\�P\�\�%a\�8\�=;\�|I=Tt?\�\�G\�=5\�%\�Y\�\�.\�\�\�$\�\�.\�<\�^~;\�\n\�Ȓc<+Q\�\�\�\�<\�ռ\�\�m\�\�\Z2\�\�\�d=5\�\�\�.x\�ϖE=\�\�\�l\�\�<_.\�\�Sl<2b\�Hl+\�\�һ\�x(\� fU=.y&=\�\�=\�\�ټ\�\�\�M\�<\�\�L\�\�[<=i/:xy\�\�\�Bڼ\�\�μ9{\�:\�!=\�R\0\�\�G\�<\�&s\�\�=\�\�<*\n\�\�\�)O\' \�*H;g\�ڼQ蓽Z5=q߱<\�ڷ\�\�\�\�<v\�<K\'\�;\�\�H\�\�\�\�sBg\�\�\�7\�\�\�=<@\�6=\�\�<UG\�\�\�E=3\�\�\�\�ީ\�\�&=A\�\�=0\�;\�c=\\ߜ\�K\�\�\�.f\�\�\�\�:\�i\�<Ov\�\�\�:<Ux\�u8N=N\�<\�\�t\�9\"\�lԧ=\�O\�<,7\�\�\�\�\�\�Լ`Q4\�\�,\�\�*\�ڂ̻3\�=L&a\�4al\�\�\�F\�Zӌ\�3\�\�<VLM\�\�+=݇R\�\�k\�\�b\�1\�<,\�<bz\�<\�;N\�\�\�g=\n\�\�<\�\�\n<\�/\�é\�<\�C=]\�<\r\�<w?۹\�\�7=\�-\�CJ\�+\�b\�0\�&\�\�\�\Z\�\�\�\�\�6(.<4ݳ\�ɇ;܃\�<_\�5<\�\�\�\�\�_\�\�\�\�<\�\�/T\�<\�e\�\�\�\�=0\�\�\�O\�\�1fZ=\�\�<\�\�=\�\�\�D,]<®\�<E\�(=(\�\�<\�c`\�\�\�\�[\�\�<\�\�\�<%\�8^x\�:X\�=\�\�z<\�\�\�;d\�L\�\\\�\�:ms:=\�\�\�\�\�<>g<\�R)=\�\�\�\�;\�\�\�\�\�\�;4\�F\�\�\�f\�i���^6\� 9\�\�r\�\�<ۘ\�<\�iP=k\�\�<\�<\�1=\�f\�\�J\�\�\�A\�\�<_e\�N\�\�\�\n\�J=;f\�:\�\�\�\�\�\�5ѳ;Q\'\�\�^>h<V\�;\�\�Ҽ\�\�\�\�5\Z\�<5C\�\�M\�\�\�^\�;XZ=\�\r\�?r\�<y\�7=\�օ<\�\�\r=\�\�\�;\�\�\�<\�\�|<\�}\�<҃\�\�\�\�ң\�\�BL\�<>)\�\�5\�\�=\�u\�\�\�9\�\�\�\�\�E\�<\�\�\�<\�\�\�\�[\�\�\�\�\�<\�[}=G\�<\�\�=s\�\�:X\�\�\�8\�<\�\�\�\�\�\�0O=e\�༏8=VЂ<D\�κ\�f\�\Z\'\�<P\�<ִ\�\�\�\�\�<\�(=E\�ݼ-\�;3C\�\�\'9=\�\�\�=N\�V\�\�\�\�<s\'\�U?<ʚ<\�$=H\�\�\�\�<\�L=1\�\�\�=v\�\�\�;\�\�\�\�%\�\�\�Q\�;l\�\�<\�~\�\�\�\�d\�\�s\�;\�\�\�\�=\�[\�V\�\�Ě<\�͋<a\�<\�=\�\�\�<K\�\�\�\�\�\�D<\�|\�=\�+\�<\�J\�<\�\�\�\�*n\�6\�\�0\�=Wxl;~\r\�\�\�4h<)Y-=^c\�<Ո\�\�O\�;x\n=*;0\�\�V =\�\�3\�A\�<s\�\�\�\�\�<>X\�\�z\�\�]\�<v\�7=\�}<\�Lx<\�9\�\�au9\�\�홼od\�\�t<\�<\�@=%:\�\�\�ɻ\�#A=Ms<?V\�;3\�<\�\�\�<)\�\�\�$\n\�yRo=0>=\�\�<\�\�\n<\�Y<\�/=\�s=\�ؒ<rW\�\�\�\�?<\�\�=\�-\�<W\�1=u\�.\�V/x\�\n\�<\�b;\�\�\�;\�\�\�s\�ؼ\�\�+=\�m\�<Ƚ8=\�t$<\�\�W=\�1(=\�\�,\�;,Ku\�\�\�<\�r`=ȊT=\�\�\�\�\�u缝\�\�\�\�=\�\�=\�1<\�\Z\�<D8\�<\�\�\�-\�b\�\�\�\�/\�\�\�\�\�\�<\�r<\nϮ;2F\�<\�\�\�\�b\�\�;\�\�\�\�\�a\�<\�F\�\�N=n=\�\�c=\�\�\�\�\�;\�N\�=0\�\�D=ؤ\�<5:T\�|+\"<\�+\�\�=\�\�\�3\�\�\�\�\�\�&\�IY=\�e<\0\�\�ӲX\�%b^=tK\�\�\\\�=\�\�-=\�\�F;\'r`\�H\�Z=\�]#;5\�/\�= \'p<\�D\�<\�xx<\�j\�\�\�\�\�<\�>\�<P\�<\�\�;\�<\�q\�\�\�\�\�\�B\�\�\�4\�@ƻ\�=,m:͍<]\�\�L!\�<\�\�\�\�d\�\�\�\�<\�ܪ=Bǘ\�Pq\�\�\�\n\�\� \�\�\�#Z;U㴼\n=T\�!e=<B@=m\�Ȼ\�B:\�\�\�\�WO \�\�\�Ӽ\�\�w=\�.<]S\r=\�\�<\�\�\�rI<\�\�G;\�\�2<8ʼ \�5<\�\�\�\�.\�@\�\�Tգ\�\�O\�\�\�\�\�v\�\�<\'h@\�m\�\�;\�\�\�\�\�\�\�\�<=\�.<\�\�9=\�\�#\�\�\�0:\�\�<\�\�\�=6H\�\�\r՛;\�\�?<\�n:\�u\�<\�9ȼ\�/���H!\�ϯ\�\�\�\�\n\�\�\�\�\�l\�;G\�\�\�\�\�_\�M\�E\�6\�\�\�}\�\�㡼\�\�Լ}\�\�Y^\0<\�Z\�\�\�o\�\�\�W\�<\�Ȕ\�<\�ʹ\�a^=\�L;\�\�i<!\�,\�ڸ6=k\�z;\�~\�\\\� =34\�b\�\�\�\"\�;^\�\�\�\�]\�\�\�\�\�W+=s/Q\�T\�u=\�\�W,\'\�\�\�<\�\"=\�\�Q<\�\�\�;K\�=7\�\�\�&\�<z\�\�\�*\�m;b\r\�\�)\�Gh\�\�n\�<<I\�<\�\�<<\�1=\ruܼO\�\�\�/=\�\�\�<b\�\�\�FH\�\�m\�8;\�\�1\�GDZ<!\�Ƽ|=;C\�<Ɠ\�=5W\�<!\�:\�=\�<\�\�=\�\�=\�\�l\�tě<\� Z<~\�<\�\�\'\�\�=s=\�\�=\�c\�<\�\�\�Z\�\�\�2\ZG=Z\�ü!;1\�Jn̼E\�\�(\�\�\�c\�;U\�\�<\�\�<\�gp\� \r\�\�\�\�\�q\�\�\�\�\�\�x!=ޟ\�<\�SV\�\�gG\�\�\�D\�Q\�\�<=\�\�<\�\�:@6\�\�_\�p<z#/\�+\�\�\�\�\�`<Ҡ;>\�<\�\�\�\�{W=i\�\r\�>#=,\�5\� <\�\�)W\�\�\�\�[\�\�\�sy\�vo;\�/Ӽ\�v\�q\�ȼfk\�=B\�\�\�\�\�;\�\�\�\�\�\'=%\�y\�\r\�\�\�\�+\�\�\�^=Ϭ̷\�\�=\�\�\�9Ѓ;\�=4\�\�ݠ=/M\�;\�\'\�<+\Z\�\�Ӛ\�B\�\�\ZK=0z\�=G,\�\�th\�\�\�\�ۼ\�\�!\�:\�\�\�\�;g\�\n\�\� @=\�\�Q\�1\�[<:`\�\�GQ\�\�\�<AB\�<F\�=\�\�\�\�\�\�\�\�\\\�8\�\�; c\�\�c\�܉<\�J=j\�G=\�\�\�\�\�\�b\�녧<\�\�\�= \�V\�\�f<Ȉ\�\�\�K[\�xNX\�B-f<+\�.<[\�\�r`\�J8=\�_<\�\�9\�A\�\�\�l^\�V\�&\�1<\�\�K\'\�E\�q\�[\�\�\�') as distance FROM langchain_embedding WHERE collection_id = '0197b960-56d1-7bbc-9641-8f3a3c9df28a' ORDER BY distance ASC LIMIT 2
24 Close stmt
24 Query ROLLBACK
25 Quit
24 Quit
chatgpt 의 힘을 빌려 겨우 찾았다.
기본값이 langchain_embedding, langchain_collection 이다. 이러니까 안나오지...
from langchain_ollama import OllamaEmbeddings
from langchain_mariadb import MariaDBStore
from langchain_core.documents import Document
import time # UUID 생성을 위한 임시 방편 (실제로는 Langchain이 알아서 처리)
# 1. 임베딩 및 벡터스토어 설정
embeddings = OllamaEmbeddings(model="nomic-embed-text")
# collection_name을 "my_collection_name" 등으로 지정하면,
# langchain_embedding 테이블의 collection_id 컬럼에 이 값이 저장됩니다.
# 이 collection_id를 통해 특정 그룹의 문서를 나중에 필터링할 수 있습니다.
vectorstore = MariaDBStore(
embedding_length=768,
embeddings=embeddings,
datasource="mariadb+mariadbconnector://root:1234@localhost:3306/exoluse",
collection_name="my_document_collection" # 이 값이 collection_id로 사용됩니다.
)
# 2. 저장할 Document 객체 생성
# 각 Document는 page_content(본문)와 metadata(부가 정보)를 가집니다.
documents_to_add = [
Document(
page_content="금배추는 한국에서 주로 재배되는 배추 품종 중 하나입니다. "
"일반 배추보다 잎이 부드럽고 단맛이 강한 것이 특징입니다. "
"주로 김장용이나 겉절이용으로 많이 사용됩니다. "
"재배 기간이 짧고 병충해에 강하여 농가에서 선호합니다.",
metadata={"category": "농업", "title": "금배추의 특징과 용도"}
),
Document(
page_content="인공지능(AI)은 인간의 학습 능력, 추론 능력, 지각 능력 등을 "
"컴퓨터 프로그램으로 구현한 기술입니다. 머신러닝, 딥러닝 등의 "
"하위 분야를 포함하며, 자율 주행, 의료 진단, 자연어 처리 등 "
"다양한 분야에서 활용되고 있습니다.",
metadata={"category": "기술", "title": "인공지능 개요 및 활용 분야"}
),
Document(
page_content="서울의 남산타워는 서울을 대표하는 랜드마크 중 하나입니다. "
"정식 명칭은 N서울타워이며, 1975년에 완공되었습니다. "
"케이블카를 타고 올라갈 수 있으며, 아름다운 서울의 야경을 "
"감상할 수 있는 명소입니다. 사랑의 자물쇠로도 유명합니다.",
metadata={"category": "관광", "title": "서울 남산타워 방문 가이드"}
),
]
# 3. add_documents 메서드를 사용하여 데이터 추가
print(f"--- 'langchain_embedding' 테이블에 {len(documents_to_add)}개 문서 추가 중 ---")
# add_documents는 추가된 문서의 ID 리스트를 반환합니다.
added_ids = vectorstore.add_documents(documents_to_add)
print(f"문서 추가 완료. 추가된 문서 ID: {added_ids}")
# 데이터가 잘 들어갔는지 확인하기 위해 검색기를 사용하여 테스트
print("\n--- 추가된 문서 검색 확인 (금배추 쿼리) ---")
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
query_result = retriever.invoke("금배추")
print(f"검색 결과 문서 수: {len(query_result)}")
for i, doc in enumerate(query_result):
print(f"[{i+1}] 내용 (앞 150자): {doc.page_content[:150]}...")
print(f" 메타데이터: {doc.metadata}")
그냥 복잡하니 langchain 기본설정 쓰는게 나을수도...
MariadbStore 설정을 보자...
% vi /Users/exoluse/Desktop/dev/mariadb_rag/.venv/lib/python3.13/site-packages/langchain_mariadb/vectorstores.py
중간 부분에 이런게 있다. config 에 임베딩 id, content, metadata 를 설정하고 있다.
Advanced Usage:
Custom configuration:
```python
from langchain_mariadb import (
MariaDBStore, MariaDBStoreSettings, TableConfig, ColumnConfig
}
# Configure custom table and column names
config = MariaDBStoreSettings(
tables=TableConfig(
embedding_table="custom_embeddings",
collection_table="custom_collections"
),
columns=ColumnConfig(
embedding_id="doc_id",
content="text_content",
metadata="doc_metadata"
)
)
store = MariaDBStore.from_texts(
texts=["Hello, world!"],
embedding=embeddings,
datasource=pool,
config=config
)
```
from langchain_ollama import ChatOllama, OllamaEmbeddings
from langchain_mariadb import MariaDBStore
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate
# 1. 임베딩 및 벡터스토어 설정
embeddings = OllamaEmbeddings(model="nomic-embed-text") # 또는 bge-m3
vectorstore = MariaDBStore(
embedding_length=768,
embeddings=embeddings,
datasource="mariadb+mariadbconnector://root:1234@localhost:3306/exoluse",
collection_name="my_document_collection" # 테이블명
)
# 2. 벡터 검색기 (retriever)
retriever = vectorstore.as_retriever(
search_type="similarity",
search_kwargs={"k": 1}
)
docs1 = retriever.invoke("금배추")
print(f"검색 결과 문서 수: {len(docs1)}")
for i, doc in enumerate(docs1):
print(f"[{i+1}] {doc.page_content[:1000]}")
# 3. 프롬프트 템플릿
prompt = ChatPromptTemplate.from_template("""
[문서]:
{context}
당신은 유능한 AI 도우미입니다. [문서]를 참고하여 질문에 정리된 답변을 작성하세요.
[문서]에 없는 내용은 답변하지 마세요.
질문: {input}
""")
# 4. LLM + 문서 결합 체인
llm = ChatOllama(model="exaone3.5:7.8b") # 또는 exaone3.5-custom
combine_docs_chain = create_stuff_documents_chain(
llm=llm,
prompt=prompt
)
# 5. RAG Retrieval Chain
retrieval_chain = create_retrieval_chain(
retriever=retriever,
combine_docs_chain=combine_docs_chain
)
# 6. 질문 실행
query = "금배추"
response = retrieval_chain.invoke({"input": query})
# 7. 결과 출력
print("📌 질문:", query)
print("🧠 답변:\n", response["answer"])
뭔가 해결된 느낌이다.
랭체인식 Mariadb vector를 사용해 보니 뭔가 불편한점이 많다.
기본설정을 쓰자니 embedding 이 한곳에 몰려있고 따로 세팅을 하자니 많이 귀찮다...