AI-Master-Book
  • about AI-Master-Book
  • AI Master Book
    • 이상치 탐지 with Python
    • 베이지안 뉴럴네트워크 (BNN) with Python
    • 그래프 뉴럴네트워크 (GNN) with Python
    • 데이터 마케팅 분석 with Python
  • LLM MASTER BOOK
    • OpenAI API 쿡북 with Python
    • 기초부터 심화까지 RAG 쿡북 with Python
    • MCP 에이전트 쿡북 with Python
  • LLMs
    • OpenAI API
      • 1️⃣ChatCompletion
      • 2️⃣DALL-E
      • 3️⃣Text to Speech
      • 4️⃣Video to Transcripts
      • 5️⃣Assistants API
      • 6️⃣Prompt Engineering
      • 7️⃣OpenAI New GPT-4o
    • LangChain
      • LangChain Basic
        • 1️⃣Basic Modules
        • 2️⃣Model I/O
        • 3️⃣Prompts
        • 4️⃣Chains
        • 5️⃣Agents
        • 6️⃣Tools
        • 7️⃣Memory
      • LangChain Intermediate
        • 1️⃣OpenAI LLM
        • 2️⃣Prompt Template
        • 3️⃣Retrieval
        • 4️⃣RAG ChatBot
        • 5️⃣RAG with Gemini
        • 6️⃣New Huggingface-LangChain
        • 7️⃣Huggingface Hub
        • 8️⃣SQL Agent & Chain
        • 9️⃣Expression Language(LCEL)
        • 🔟Llama3-8B with LangChain
      • LangChain Advanced
        • 1️⃣LLM Evaluation
        • 2️⃣RAG Evaluation with RAGAS
        • 3️⃣LangChain with RAGAS
        • 4️⃣RAG Paradigms
        • 5️⃣LangChain: Advance Techniques
        • 6️⃣LangChain with NeMo-Guardrails
        • 7️⃣LangChain vs. LlamaIndex
        • 8️⃣LangChain LCEL vs. LangGraph
    • LlamaIndex
      • LlamaIndex Basic
        • 1️⃣Introduction
        • 2️⃣Customization
        • 3️⃣Data Connectors
        • 4️⃣Documents & Nodes
        • 5️⃣Naive RAG
        • 6️⃣Advanced RAG
        • 7️⃣Llama3-8B with LlamaIndex
        • 8️⃣LlmaPack
      • LlamaIndex Intermediate
        • 1️⃣QueryEngine
        • 2️⃣Agent
        • 3️⃣Evaluation
        • 4️⃣Evaluation-Driven Development
        • 5️⃣Fine-tuning
        • 6️⃣Prompt Compression with LLMLingua
      • LlamaIndex Advanced
        • 1️⃣Agentic RAG: Router Engine
        • 2️⃣Agentic RAG: Tool Calling
        • 3️⃣Building Agent Reasoning Loop
        • 4️⃣Building Multi-document Agent
    • Hugging Face
      • Huggingface Basic
        • 1️⃣Datasets
        • 2️⃣Tokenizer
        • 3️⃣Sentence Embeddings
        • 4️⃣Transformers
        • 5️⃣Sentence Transformers
        • 6️⃣Evaluate
        • 7️⃣Diffusers
      • Huggingface Tasks
        • NLP
          • 1️⃣Sentiment Analysis
          • 2️⃣Zero-shot Classification
          • 3️⃣Aspect-Based Sentiment Analysis
          • 4️⃣Feature Extraction
          • 5️⃣Intent Classification
          • 6️⃣Topic Modeling: BERTopic
          • 7️⃣NER: Token Classification
          • 8️⃣Summarization
          • 9️⃣Translation
          • 🔟Text Generation
        • Audio & Tabular
          • 1️⃣Text-to-Speech: TTS
          • 2️⃣Speech Recognition: Whisper
          • 3️⃣Audio Classification
          • 4️⃣Tabular Qustaion & Answering
        • Vision & Multimodal
          • 1️⃣Image-to-Text
          • 2️⃣Text to Image
          • 3️⃣Image to Image
          • 4️⃣Text or Image-to-Video
          • 5️⃣Depth Estimation
          • 6️⃣Image Classification
          • 7️⃣Object Detection
          • 8️⃣Segmentatio
      • Huggingface Optimization
        • 1️⃣Accelerator
        • 2️⃣Bitsandbytes
        • 3️⃣Flash Attention
        • 4️⃣Quantization
        • 5️⃣Safetensors
        • 6️⃣Optimum-ONNX
        • 7️⃣Optimum-NVIDIA
        • 8️⃣Optimum-Intel
      • Huggingface Fine-tuning
        • 1️⃣Transformer Fine-tuning
        • 2️⃣PEFT Fine-tuning
        • 3️⃣PEFT: Fine-tuning with QLoRA
        • 4️⃣PEFT: Fine-tuning Phi-2 with QLoRA
        • 5️⃣Axoltl Fine-tuning with QLoRA
        • 6️⃣TRL: RLHF Alignment Fine-tuning
        • 7️⃣TRL: DPO Fine-tuning with Phi-3-4k-instruct
        • 8️⃣TRL: ORPO Fine-tuning with Llama3-8B
        • 9️⃣Convert GGUF gemma-2b with llama.cpp
        • 🔟Apple Silicon Fine-tuning Gemma-2B with MLX
        • 🔢LLM Mergekit
    • Agentic LLM
      • Agentic LLM
        • 1️⃣Basic Agentic LLM
        • 2️⃣Multi-agent with CrewAI
        • 3️⃣LangGraph: Multi-agent Basic
        • 4️⃣LangGraph: Agentic RAG with LangChain
        • 5️⃣LangGraph: Agentic RAG with Llama3-8B by Groq
      • Autonomous Agent
        • 1️⃣LLM Autonomous Agent?
        • 2️⃣AutoGPT: Worldcup Winner Search with LangChain
        • 3️⃣BabyAGI: Weather Report with LangChain
        • 4️⃣AutoGen: Writing Blog Post with LangChain
        • 5️⃣LangChain: Autonomous-agent Debates with Tools
        • 6️⃣CAMEL Role-playing Autonomous Cooperative Agents
        • 7️⃣LangChain: Two-player Harry Potter D&D based CAMEL
        • 8️⃣LangChain: Multi-agent Bid for K-Pop Debate
        • 9️⃣LangChain: Multi-agent Authoritarian Speaker Selection
        • 🔟LangChain: Multi-Agent Simulated Environment with PettingZoo
    • Multimodal
      • 1️⃣PaliGemma: Open Vision LLM
      • 2️⃣FLUX.1: Generative Image
    • Building LLM
      • 1️⃣DSPy
      • 2️⃣DSPy RAG
      • 3️⃣DSPy with LangChain
      • 4️⃣Mamba
      • 5️⃣Mamba RAG with LangChain
      • 7️⃣PostgreSQL VectorDB with pgvorco.rs
Powered by GitBook
On this page
  • LCEL: LangChain Expression Language
  • Setup Environments
  • Basic ChatPromptTemplate
  • LCEL(LangChain Expression Language) Chain
  • RAG with LCEL
  • Runnable Function
  • LCEL: ChatWithHistory
  • Chat with returning documents
  1. LLMs
  2. LangChain
  3. LangChain Intermediate

Expression Language(LCEL)

LCEL: LangChain Expression Language

LangChain Expression Language, LCEL은 체인을 쉽게 구성할 수 있는 선언적 방식입니다. LCEL은 가장 간단한 "프롬프트 + LLM" Chain부터 가장 복잡한 체인까지 코드 변경 없이 프로토타입을 프로덕션에 적용할 수 있도록 설계되었습니다.

LCEL을 사용하면 기본 구성 요소로 복잡한 체인을 쉽게 구축할 수 있으며 스트리밍, 병렬 처리, 로깅과 같은 기본 기능을 지원합니다.

LCEL을 사용하여 기본적인 Chain 구성을 실행해보고, ChatwithHistory를 실행해 보겠습니다.

Setup Environments

%pip install langchain-openai
import os
from dotenv import load_dotenv  

load_dotenv()
api_key = os.getenv("OPENAI_API_KEY")

Basic ChatPromptTemplate

from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_template(
    "{topic}에 대한 흥미로운 사실을 알려줄래?"
)
prompt_val = prompt.invoke(
    {"topic": "dog"}
)
print(prompt_val)
messages=[HumanMessage(content='dog에 대한 흥미로운 사실을 알려줄래?')]
print(prompt_val.to_messages())
[HumanMessage(content='dog에 대한 흥미로운 사실을 알려줄래?')]
from langchain_openai import ChatOpenAI

model = ChatOpenAI(
    model="gpt-3.5-turbo"
)
result = model.invoke(prompt_val)
result
AIMessage(content='개는 인간이 길들여진 가장 오래된 동물 중 하나입니다. 약 1만 3천년 전부터 사람들과 함께 살아왔으며, 진화의 과정에서 인간과 함께 살아가며 조화롭게 발전해왔습니다. 이는 개가 인간의 가장 가까운 친구 중 하나로 여겨지는 이유 중 하나입니다.', response_metadata={'token_usage': {'completion_tokens': 125, 'prompt_tokens': 29, 'total_tokens': 154}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_c2295e73ad', 'finish_reason': 'stop', 'logprobs': None}, id='run-4aebcc59-1495-41b9-b460-13f9d15f56bc-0')
from langchain_core.output_parsers import StrOutputParser

output_parser = StrOutputParser()
output_parser.invoke(result)
'개는 인간이 길들여진 가장 오래된 동물 중 하나입니다. 약 1만 3천년 전부터 사람들과 함께 살아왔으며, 진화의 과정에서 인간과 함께 살아가며 조화롭게 발전해왔습니다. 이는 개가 인간의 가장 가까운 친구 중 하나로 여겨지는 이유 중 하나입니다.'

LCEL(LangChain Expression Language) Chain

prompt = ChatPromptTemplate.from_template(
    "{topic}에 대한 흥미로운 사실을 알려줄래?"
)
model = ChatOpenAI()
output_parser = StrOutputParser()

# lcel로 multi-chain을 구성
basicchain = model | output_parser
basicchain.invoke("안녕!")
'안녕하세요! 무엇을 도와드릴까요?'
# lcel로 prompt-model-output_parser 구성
chain = prompt | model | output_parser

chain.invoke({"topic": "dog"})
'개는 인간의 가장 오래된 친구 중 하나로 알려져 있습니다. 실제로, 최근 연구에 따르면 15,000년에서 30,000년 전에 이미 인간과 함께 살았던 것으로 밝혀졌습니다. 이는 개가 인류의 가장 오래된 반렬족 중 하나로 여겨지는 이유 중 하나입니다.'

RAG with LCEL

from langchain.schema import Document
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_core.runnables import RunnablePassthrough

# openAI Embedding 사용
embedding_function = OpenAIEmbeddings()

# prompt 구성
docs = [
    Document(
        page_content="개는 피자 먹는 것을 좋아한다.", metadata={"source": "animal.txt"}
    ),
    Document(
        page_content="고양이는 생선 먹는 것을 좋아한다.", metadata={"source": "animal.txt"}
    ),
]

# Chroma VectorStore 설정
db = Chroma.from_documents(
    docs, embedding_function
)
retriever = db.as_retriever()
retriever.get_relevant_documents(
    "개는 어떤 음식을 먹기를 원해?"
)
[Document(page_content='개는 피자 먹는 것을 좋아한다.', metadata={'source': 'animal.txt'}),
 Document(page_content='고양이는 생선 먹는 것을 좋아한다.', metadata={'source': 'animal.txt'}),
 Document(page_content='the dog loves to eat pizza', metadata={'source': 'animal.txt'}),
 Document(page_content='the cat loves to eat lasagna', metadata={'source': 'animal.txt'})]
retriever.invoke(
    "개는 어떤 음식을 먹기를 원해?"
)
[Document(page_content='개는 피자 먹는 것을 좋아한다.', metadata={'source': 'animal.txt'}),
 Document(page_content='고양이는 생선 먹는 것을 좋아한다.', metadata={'source': 'animal.txt'}),
 Document(page_content='the dog loves to eat pizza', metadata={'source': 'animal.txt'}),
 Document(page_content='the cat loves to eat lasagna', metadata={'source': 'animal.txt'})]
template = """Answer the question based only on the following context:
{context}

Question: {question}
"""

prompt = ChatPromptTemplate.from_template(template)
model = ChatOpenAI()
from operator import itemgetter

# Retrieval Chain으로 'context', 'question'을 구성한다.
retrieval_chain = (
    {
        "context": (lambda x: x["question"]) | retriever,
        # "question": lambda x: x["question"],
        "question": itemgetter("question"),
    }
    | prompt
    | model
    | StrOutputParser()
)
retrieval_chain.invoke(
    {"question": "개는 어떤 음식을 먹기를 원해?"}
)
'피자'

RunnablePassthrough()로 사용자 정의 함수를 대신 표현하자.

template = """Answer the question based only on the following context:
{context}

Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
model = ChatOpenAI()

retrieval_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | model
    | StrOutputParser()
)
retrieval_chain.invoke(
    "개는 어떤 음식을 먹기를 원해?"
)
'피자(replace pizza)'

Runnable Function

from langchain_core.runnables import RunnableParallel, RunnablePassthrough

runnable = RunnableParallel(
    passed=RunnablePassthrough(),
    extra=RunnablePassthrough.assign(upper=lambda x: x["input"].upper()),
    modified=lambda x: x["input"] * 3,
)

runnable.invoke({"input": "hello!"})
{'passed': {'input': 'hello!'},
 'extra': {'input': 'hello!', 'upper': 'HELLO!'},
 'modified': 'hello!hello!hello!'}


LCEL: ChatWithHistory

import os
from dotenv import load_dotenv  

load_dotenv()
api_key = os.getenv("OPENAI_API_KEY")
from langchain.schema import Document
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
import os
from dotenv import load_dotenv
# openAI Embedding 사용
embedding_function = OpenAIEmbeddings()

# prompt 구성
docs = [
    Document(
        page_content="개는 피자 먹는 것을 좋아한다.", metadata={"source": "animal.txt"}
    ),
    Document(
        page_content="고양이는 생선 먹는 것을 좋아한다.", metadata={"source": "animal.txt"}
    ),
]

# Chroma VectorStore 설정
db = Chroma.from_documents(
    docs, embedding_function
)
retriever = db.as_retriever()
retriever.invoke("정확히 무슨 뜻이야?")
Number of requested results 4 is greater than number of elements in index 2, updating n_results = 2
[Document(page_content='개는 피자 먹는 것을 좋아한다.', metadata={'source': 'animal.txt'}),
 Document(page_content='고양이는 생선 먹는 것을 좋아한다.', metadata={'source': 'animal.txt'})]
from langchain.prompts.prompt import PromptTemplate

rephrase_template = """다음 대화와 후속 질문이 주어졌을 때 후속 질문을 원래 언어로 독립된 질문으로 바꾸어 줄래.

Chat History: {chat_history}
Follow Up Input: {question}
Standalone question:"""

REPHRASE_TEMPLATE = PromptTemplate.from_template(rephrase_template)
from langchain_core.messages import AIMessage, HumanMessage
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

rephrase_chain = REPHRASE_TEMPLATE | ChatOpenAI(temperature=0) | StrOutputParser()
rephrase_chain.invoke(
    {
        "question": "아니, 정말로?",
        "chat_history": [
            HumanMessage(content="개는 어떤 음식을 먹기를 원해?"),
            AIMessage(content="참치!"),
        ],
    }
)
'개는 어떤 음식을 먹기를 원해?'
from langchain_core.prompts import ChatPromptTemplate

template = """Answer the question based only on the following context:
{context}

Question: {question}
"""

ANSWER_PROMPT = ChatPromptTemplate.from_template(template)
from langchain_core.runnables import RunnablePassthrough

retrieval_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | ANSWER_PROMPT
    | ChatOpenAI(temperature=0)
    | StrOutputParser()
)
final_chain = rephrase_chain | retrieval_chain
final_chain.invoke(
    {
        "question": "아니, 정말로?",
        "chat_history": [
            HumanMessage(content="개는 어떤 음식을 먹기를 원해?"),
            AIMessage(content="참치"),
        ],
    }
)
Number of requested results 4 is greater than number of elements in index 2, updating n_results = 2





'피자'

Chat with returning documents

retrieved_documents = {"docs": retriever, "question": RunnablePassthrough()}

final_inputs = {
    "context": lambda x: "\n".join(doc.page_content for doc in x["docs"]),
    "question": RunnablePassthrough(),
}
answer = {
    "answer": final_inputs | ANSWER_PROMPT | ChatOpenAI() | StrOutputParser(),
    "docs": RunnablePassthrough(),
}

final_chain = rephrase_chain | retrieved_documents | answer
result = final_chain.invoke(
    {
        "question": "아니, 정말로?",
        "chat_history": [
            HumanMessage(content="개는 어떤 음식을 먹기를 원해?"),
            AIMessage(content="참치!"),
        ],
    }
)
print(result)
Number of requested results 4 is greater than number of elements in index 2, updating n_results = 2


{'answer': '피자', 'docs': {'docs': [Document(page_content='개는 피자 먹는 것을 좋아한다.', metadata={'source': 'animal.txt'}), Document(page_content='고양이는 생선 먹는 것을 좋아한다.', metadata={'source': 'animal.txt'})], 'question': '개는 어떤 음식을 먹기를 원해?'}}
result["answer"]
'피자'
result["docs"]["docs"]
[Document(page_content='개는 피자 먹는 것을 좋아한다.', metadata={'source': 'animal.txt'}),
 Document(page_content='고양이는 생선 먹는 것을 좋아한다.', metadata={'source': 'animal.txt'})]

PreviousSQL Agent & ChainNextLlama3-8B with LangChain

Last updated 1 year ago

9️⃣