06. Runnable

Python
# Membaca file .env dan menetapkan environment variable
from dotenv import load_dotenv
 
# Memuat informasi token
load_dotenv()
Python
# Mengatur LangSmith tracing. https://smith.langchain.com
# !pip install -qU langchain-teddynote
from langchain_altero import logging
 
# Memasukkan nama proyek.
logging.langsmith("CH01-Basic")
Output
Starting a LangSmith trace.
[project name].
CH01-Basic

Cara Efektif Menyampaikan Data

  • RunnablePassthrough dapat digunakan untuk menyampaikan data tanpa mengubahnya atau dengan menambahkan kunci tambahan.
  • Jika RunnablePassthrough() dipanggil sendiri, ia akan menerima input dan meneruskannya tanpa perubahan.
  • Jika dipanggil menggunakan metode RunnablePassthrough.assign(...), ia akan menerima input dan menambahkan argumen tambahan yang diberikan ke fungsi assign.

RunnablePassthrough

Python
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
 
# Membuat prompt dan LLM.
prompt = PromptTemplate.from_template("{num} kali 10 adalah?")
llm = ChatOpenAI(temperature=0)
 
# Membuat chain.
chain = prompt | llm

Saat menjalankan chain menggunakan invoke(), tipe data input harus berupa dictionary

Python
# Menjalankan chain.
chain.invoke({"num": 5})
Output
AIMessage(content = 'Ini adalah 50.', response_metadata = {'token_usage': {'token_selesai': 3, 'prompt_token': 16, 'total_token': 19}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': Tidak ada, 'finish_reason': 'stop', 'logprobs': None}, id='run-29242a8b-01c0-41ad-8f5b-7613e6876dc5-0', usage_metadata={'input_tokens': 16, 'output_tokens': 3, 'total_token': 19})

Namun, dengan pembaruan library LangChain, jika hanya ada satu variabel dalam template, cukup menyampaikan nilainya saja juga dimungkinkan.

Python
# Menjalankan chain.
chain.invoke(5)
Output
AIMessage(content='50', response_metadata={'token_usage': {'completion_tokens': 1, 'prompt_tokens': 16, 'total_tokens': 17}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-44f606db-2437-4d1f-9cee-ddfc69428745-0', usage_metadata={'input_tokens': 16, 'output_tokens': 1, 'total_tokens': 17})

Berikut adalah contoh menggunakan RunnablePassthrough.

RunnablePassthrough adalah objek runnable, dan objek runnable dapat dieksekusi secara terpisah menggunakan metode invoke().

Python
from langchain_core.runnables import RunnablePassthrough
 
# runnable
RunnablePassthrough().invoke({"num": 10})

Berikut ini adalah contoh bagaimana membangun sebuah chain menggunakan RunnablePassthrough

Python
runnable_chain = {"num": RunnablePassthrough()} | prompt | ChatOpenAI()
 
# Nilai dict telah diubah menjadi RunnablePassthrough().
runnable_chain.invoke(10)
Output
AIMessage(content='Ini adalah 100.', response_metadata={'penggunaan_token': {'token_selesai': 3, 'token_prompt': 16, 'total_token': 19}, 'nama_model': 'gpt-3.5-turbo', 'sidik_jari_sistem': None, 'alasan_selesai': 'stop', 'logprobs': None}, id='run-66270ca2-4d62-4c71-859b-de6318f29909-0', penggunaan_metadata={'token_masukan': 16, 'token_keluaran': 3, 'total_token': 19})

Berikut ini adalah hasil perbandingan ketika menggunakan RunnablePassthrough.assign().

Python
RunnablePassthrough().invoke({"num": 1})

RunnablePassthrough.assign()

  • Menggabungkan pasangan key/value dari nilai yang masuk dengan pasangan key/value yang baru ditetapkan.
Python
# Kunci input: num, kunci yang ditetapkan (assign): new_num
(RunnablePassthrough.assign(new_num=lambda x: x["num"] * 3)).invoke({"num": 1})
Output
{'num': 1, 'new_num': 3}

RunnableParallel

Python
from langchain_core.runnables import RunnableParallel
 
# Membuat instance RunnableParallel. Instance ini dapat menjalankan beberapa instance Runnable secara paralel.
runnable = RunnableParallel(
    # Mengirimkan instance RunnablePassthrough sebagai argumen kata kunci 'passed'. Ini berfungsi untuk melewatkan data yang diterima tanpa perubahan.
    passed=RunnablePassthrough(),
    # Menggunakan RunnablePassthrough.assign dengan argumen kata kunci 'extra' untuk menetapkan fungsi lambda 'mult'. Fungsi ini akan mengalikan nilai dari kunci 'num' dalam dictionary yang diterima dengan 3.
    extra=RunnablePassthrough.assign(mult=lambda x: x["num"] * 3),
    # Menyediakan fungsi lambda sebagai argumen kata kunci 'modified'. Fungsi ini akan menambahkan 1 pada nilai dari kunci 'num' dalam dictionary yang diterima.
    modified=lambda x: x["num"] + 1,
)
 
# Memanggil metode invoke pada instance runnable dengan mengirimkan dictionary {'num': 1} sebagai input.
runnable.invoke({"num": 1})
Output
{'passed': {'num': 1}, 'extra': {'num': 1, 'mult': 3}, 'modified': 2}

Chain juga dapat diterapkan ke RunnableParallel

Python
chain1 = (
    {"country": RunnablePassthrough()}
    | PromptTemplate.from_template("Apa ibu kota dari {country}?")
    | ChatOpenAI()
)
chain2 = (
    {"country": RunnablePassthrough()}
    | PromptTemplate.from_template("Berapa luas {country}?")
    | ChatOpenAI()
)
Python
combined_chain = RunnableParallel(capital=chain1, area=chain2)
combined_chain.invoke("Indonesia")
Output
{'capital': AIMessage(content = 'Ini Seoul', response_metadata = {'token_usage': {'token_selesai': 5, 'prompt_token': 19, 'total_token': 24}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': Tidak ada, 'finish_reason': 'stop', 'logprobs': None}, id='run-d9324c24-9670-4430-97d6-1272f5dbe0f2-0', usage_metadata={'input_tokens': 19, 'output_tokens': 5, 'total_token': 24}), 'area': AIMessage(content = 'Luas total Korea Selatan adalah sekitar 100.363 km².', response_metadata = {'penggunaan_token': {'token_selesai': 24, 'prompt_token': 20, 'total_token': 44}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': Tidak ada, 'finish_reason': 'stop', 'logprobs': None}, id='run-f27442a3-fc9c-4d08-9fdf-189c1b4585c8-0', usage_metadata={'input_tokens': 20, 'output_tokens': 24, 'total_token': 44})}

RunnableLambda

Anda dapat memetakan fungsi kustom menggunakan RunnableLambda.

Python
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from datetime import datetime
 
 
def get_today(a):
    # Mendapatkan tanggal hari ini
    return datetime.today().strftime("%b-%d")
 
 
# Mencetak tanggal hari ini
get_today(None)
Python
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
 
# Membuat prompt dan model LLM.
prompt = PromptTemplate.from_template(
    "Daftarkan {n} orang terkenal yang berulang tahun pada {today}. Harap sertakan tanggal lahir mereka."
)
llm = ChatOpenAI(temperature=0, model_name="gpt-4o")
 
# Membuat chain.
chain = (
    {"today": RunnableLambda(get_today), "n": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)
Python
# Output
print(chain.invoke(3))
Output
Tentu, berikut adalah tiga orang terkenal yang berulang tahun pada 15 Agustus beserta tanggal lahir mereka:

1. **Napoleon Bonaparte** - Lahir pada 15 Agustus 1769. Ia adalah seorang pemimpin militer dan politikus Prancis yang menjadi Kaisar Prancis dari tahun 1804 hingga 1814, dan sekali lagi pada tahun 1815 selama Seratus Hari.

2. **Ben Affleck** - Lahir pada 15 Agustus 1972. Ia adalah seorang aktor, sutradara, penulis skenario, dan produser film Amerika yang terkenal dengan perannya dalam film-film seperti "Good Will Hunting," "Argo," dan "Batman v Superman: Dawn of Justice."

3. **Jennifer Lawrence** - Lahir pada 15 Agustus 1990. Ia adalah seorang aktris Amerika yang dikenal dengan perannya dalam film-film seperti "The Hunger Games" dan "Silver Linings Playbook," yang membuatnya memenangkan Academy Award untuk Aktris Terbaik.

Semoga informasi ini bermanfaat!

Gunakan itemgetter untuk mengekstrak kunci tertentu.

Python
from operator import itemgetter
 
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableLambda
from langchain_openai import ChatOpenAI
 
 
# Fungsi yang mengembalikan panjang sebuah kalimat.
def length_function(text):
    return len(text)
 
 
# Fungsi yang mengalikan panjang dua kalimat dan mengembalikan nilainya.
def _multiple_length_function(text1, text2):
    return len(text1) * len(text2)
 
 
# Fungsi yang menggunakan _multiple_length_function untuk mengalikan panjang dua kalimat dan mengembalikan nilainya.
def multiple_length_function(_dict):
    return _multiple_length_function(_dict["text1"], _dict["text2"])
 
 
prompt = ChatPromptTemplate.from_template("{a} + {b} adalah berapa?")
model = ChatOpenAI()
 
chain1 = prompt | model
 
chain = (
    {
        "a": itemgetter("word1") | RunnableLambda(length_function),
        "b": {"text1": itemgetter("word1"), "text2": itemgetter("word2")}
        | RunnableLambda(multiple_length_function),
    }
    | prompt
    | model
)
Python
chain.invoke({"word1": "hello", "word2": "world"})
Output
content='5 + 25 = 30' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 7, 'prompt_tokens': 15, 'total_tokens': 22}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-f20b6009-ce11-4e43-a70d-ebab540faeac-0' usage_metadata={'input_tokens': 15, 'output_tokens': 7, 'total_tokens': 22}