---
# System prepended metadata

title: LangChain

---

![langchain logo](https://miro.medium.com/v2/resize:fit:1200/1*-PlFCd_VBcALKReO3ZaOEg.png)

## Setup
- 使用 llama2
    
## RAG
![RAG](https://python.langchain.com/assets/images/data_connection-95ff2033a8faa5f3ba41376c0f6dd32a.jpg)
### Text Embedding
* [Text Embedding model](https://python.langchain.com/docs/modules/data_connection/text_embedding/)
* [What is Text Embedding](https://stackoverflow.blog/2023/11/09/an-intuitive-introduction-to-text-embeddings/)
---
- 詞嵌入只是單單把要輸入的文本或句子轉為向量嗎？
    - 不僅是轉換成能用數字表達的矩陣表示法
    - 其中的數值牽涉到文本的語意
    ---
- 文本的轉換後的樣式都是單一向量嗎？
    - 有很多種形式，要看使用的 model
    - 都是高密度的向量，會根據上下文來生成
    ---
- 著名的模型：
    - Word2Vec
        - 生成維度較低的向量
        - 每個詞在不同的句子中，具有相同的詞嵌入（靜態生成）
        - 只關注上下幾個詞，不能捕捉完整的句意
    - BERT
        - 生成高維度向量
        - 每個詞在不同的句子中，具有不同的詞嵌入（動態生成）
        - 根據整個句子的意思產生詞嵌入，能處理複雜的上下文

---
### [Vector stores](https://python.langchain.com/docs/modules/data_connection/vectorstores/)
- What is Vector store ?
![Vector store](https://python.langchain.com/assets/images/vector_stores-125d1675d58cfb46ce9054c9019fea72.jpg)
    - 在前面我們透過 tranformer model 把文本轉換成 Embeddings 後，需要一個存放他們的地方
    - Vector store 就是用來存放詞嵌入的 database，並提供相似文檔檢索的功能
    ---
- 使用流程
    - Create a Vector store
    
    
        ```python
        from langchain_community.document_loaders import TextLoader
        from langchain_openai import OpenAIEmbeddings
        from langchain_text_splitters import CharacterTextSplitter
        from langchain_chroma import Chroma

        # Load the document, split it into chunks, embed each chunk and load it into the vector store.
        raw_documents = TextLoader('../../../state_of_the_union.txt').load()
        text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
        documents = text_splitter.split_documents(raw_documents)
        db = Chroma.from_documents(documents, OpenAIEmbeddings())
        ```
        - 詞分割：
            - 先把大型的文檔分割成多個組塊，因為 Embedding model 有 token 上限
            - chunk_overlap：設定組塊之間重疊的詞語的數量，確保完整的句子不會被分割在不同組塊之間
        - 存入 Vector store (Chroma)
            - documents 要存入的文檔
            - OpenAIEmbeddings()：當 from_documents 被呼叫時，會先使用 OpenAI 的 model 做 Text Embedding，然後再存入 Vector store
    - Similarity search
        - By string
            ```python=
            query = "What did the president say about Ketanji Brown Jackson"
            docs = db.similarity_search(query)
            print(docs[0].page_content)
            ```
        - By vector
            ```python=
            embedding_vector = OpenAIEmbeddings().embed_query(query)
            docs = db.similarity_search_by_vector(embedding_vector)
            print(docs[0].page_content)
            ```
    ---
    - Asynchronous operations : 因為文本輸入跟檢索可能需要花較長的處理時間 -> 支援非同步的方法
    - Maximum marginal relevance search (MMR)：透過檢索多個與輸入文本相關的詞嵌入，先選出 fetch_k 個，最後提供最相似的 k 個
        ```pyhoon!
        query = "What did the president say about Ketanji Brown Jackson"
        found_docs = await qdrant.amax_marginal_relevance_search(query, k=2, fetch_k=10)
        for i, doc in enumerate(found_docs):
            print(f"{i + 1}.", doc.page_content, "\n")
        ```
---
### [Retrievers](https://python.langchain.com/docs/modules/data_connection/retrievers/)
- What is Retrievers ?
    - based on Vector store 建立的一個接收input(文本）的模組，會回傳包含一個或多個相似文本的 documents
- 流程

    - 建立一個 prompt 的模板 & document_chain
        ```python  
        from langchain.chains.combine_documents import create_stuff_documents_chain

        prompt = ChatPromptTemplate.from_template("""Answer the following question based only on the provided context:

        <context>
        {context}
        </context>

        Question: {input}""")

        document_chain = create_stuff_documents_chain(llm, prompt)
        ```
        - context : 跟 input 相關的上下文
        - create_stuff_documents_chain 把 llm 與 prompt 串接成一個 documents_chain 可以透過 invoke() 來觸發

        ---
    - 手動輸入 context
        ```python!
        from langchain_core.documents import Document

        document_chain.invoke({
            "input": "how can langsmith help with testing?",
            "context": [Document(page_content="langsmith can let you visualize test results")]
        })
        ```
    - 為什麼要使用 Retriever ?
        - 因為使用者並不知道上下文 -> 透過 Retriever 對 vector store 做 Similarity search 產生 context 
            ```python    
            from langchain.chains import create_retrieval_chain

            retriever = vector.as_retriever()
            retrieval_chain = create_retrieval_chain(retriever, document_chain)
            ```
    

