+53

Langchain #1 - Điểm qua các chức năng sừng sỏ nhất của Langchain - một framework cực bá đạo khi làm việc với LLM

Độ hot của Langchain

Langchain là một framework vô cùng hot hit trong thời gian gần đây. Nó được sinh ra để tận dụng sức mạnh của các mô hình ngôn ngữ lớn LLM như ChatGPT, LLaMA... để tạo ra các ứng dụng trong thực tế. Dù mới được phát triển cách đây khoảng 6 tháng (10/2022) và vẫn được cập nhật liên tục hàng ngày nhưng trên Github Langchain đã nhận được những tương tác khủng với lượng star lên đến hơn 34K - bằng hơn 1 nửa số star mà một framework thần thánh khác trong Deep Learning đó là PyTorch thu được sau hơn 6 năm trời vất vả.

Điều đó đủ để thấy langchain hot đến mức độ nào.

image.png

Trong bài viết này chúng ta cùng nhau tìm hiểu tại sao nó lại hot đến mức như thế nhé. OK, let gooooo

Tại sao cần phải có langchain

Chắc hẳn các bạn đã rất quen thuộc với ChatGPT rồi phải không. Ai mà còn chưa dùng ChatGPT thì đăng kí dùng ngay đi nhé kẻo mấy nữa nó lại out date mất. Công nghệ từ đầu 2023 thay đổi tính bằng ngày các bạn ạ. Rồi, quay lại lý do tại sao lại cần sử dụng Langchain. Dù là công nghệ gì đi nữa thì cũng có điểm yếu của nó phải không. Nếu như các bạn đã từng đọc ChatGPT hay là "Chết GPT"? của mình thì hẳn các bạn sẽ thấy mình có liệt kê một vài điểm yếu của nó trong dó tiêu biểu nhất đó là:

  • Không có tính realtime: Bạn thử lên ChatGPT và hỏi nó về thời tiết ngày hôm nay xem. Nó sẽ không trả lời được đâu. Bởi đơn giản nó chỉ là một mô hình ngôn ngữ và chỉ có có thể trả lời được trên các thông tin nó đã được huấn luyện thôi chứ không thể cập nhật dữ liệu một cách real time được. Ví dụ như hình này luôn cho các bạn dễ hình dung nhé

image.png

  • Không truy cập được vào các dữ liệu cá nhân: Điều này là chắc chắn rồi. Nó mà trả lời được các thông tin liên quan đến dữ liệu cá nhân của mình thì quá đáng sợ phải không nào. Ví dụ nãy hỏi nó về tài khoản Facebook của bạn xem nó có biết không nhé

image.png

Đương nhiên câu trả lời cũng là không rồi. Biết thì có mà loạn

Thế một câu hỏi đặt ra là, ô thế làm thế nào để tích hợp mô hình ngôn ngữ với các dữ liệu khác như các trường hợp trên. Trong khi ứng dụng thực tế thì các trường hợp này nhiêu vô số kể. Vậy thì câu trả lời đó chính là LANGCHAIN.

Túm cái váy lại, langchain là một framework giúp các bạn không chỉ tương tác với các mô hình ngôn ngữ lớn mà còn cho phép ứng dụng của bạn tận dụng thêm các thông tin từ nhiều nguồn data khác của bên thứ 3 như Google, Notion, Facebook... cũng như cung cấp các component cho phép sử dụng các language model trong nhiều tình huống khác nhau trên thực tế. Các bạn có thể hình dung langchain như một cầu nối giữa mô hình ngôn ngữ và các ứng dụng bên thứ ba như hình dưới đây vậy.

langchain_01.png

Trong đó có hai ưu điểm chính của framework langchain là:

  • Cung cấp các component đa dạng: LangChain cung cấp một loạt các component cần thiết cho việc tương tác với các language model. Các component này được thiết kế dễ dàng sử dụng, mở rộng và tuỳ biến cho nhiều bài toán khác nhau.
  • Cung cấp các chains cho các use-case cụ thể: Một chains được hiểu là một chuỗi các component ghép nối lại với nhau theo thứ tự nhất định để từ đó có thể giải quyết được các trường hợp sử dụng trong thực tế. Các use-case mà langchain cung cấp như trợ lý ảo, hỏi đáp dựa trên các tài liệu, chatbot, hỗ trợ truy vấn dữ liệu bảng biểu, tương tác với các API, trích xuất đặc trưng của văn bản, đánh giá văn bản, tóm tắt văn bản. Chúng ta sẽ cùng nhau tìm hiểu chi tiết từng thành phần trong các phần tiếp theo nhé.

Chuẩn bị công cụ để chiến đấu

Cài đặt langchain

Rất đơn giản thôi. Gõ dòng sau

pip install openai

Mở IDE lên để code nào

Setup API Key

Trong bài này mình sẽ sử dụng luôn OpenAI Platform để làm ví dụ minh hoạ. Như đã nói ở trên đó, bạn nào chưa có tài khoản thì tạo ngay tài khoản thôi. Còn bạn nào đã có tài khoản rồi thì có thể truy cập vào đây để lấy API Key nhé.

Tiếp tục tạo một file apikey.py để chứa API

# apikey.py
OPENAI_API_KEY = "xxxxx"

Đơn giản quá phải không nào. Chỉ còn một bước nhỏ nữa thôi là chúng ta sẽ bắt đầu một thế giới hoàn toàn mới với Langchain rồi đó.

Import API Key vào ứng dụng

Trong file models-demo.py chúng ta thực hiện import API Key rất đơn giản các bạn chỉ cần setup biến môi trường là xong

# models-demo.py

import os
from apikey import OPENAI_API_KEY

os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY

Hệ thống component của langchain

Như đã nói ở trên thì Langchain là mộtr framework tận dụng cho LLM nên có thể nói tất cả các nội dung chúng ta đang xét ở đây đều liên quan đến dữ liệu dạng văn bản. Và để cung cấp cho việc tương tác với dạng dữ liệu này được đơn giản hơn thì Langchain cung cấp cho chúng ta một loạt các hệ thống gọi là component. Mỗi component sẽ có một mục đích khác nhau. Chúng ta cùng lướt qua một số component cơ bản nhé

Models

Models ở đây muốn nói đến các mô hình ngôn ngữ lớn. Langchain là một framework tận dụng sức mạnh của mô hình ngôn ngữ lớn nên chắc chắn là không thể thiếu bộ não của nó rồi đúng không. Tuy nhiên cần lưu ý rằng, bản thân langchain KHÔNG CHỨA CÁC MÔ HÌNH mà nó sẽ chứa các INTERFACE để giúp tương tác với mô hình một cách dễ dàng hơn. Các mô hình có thể được lưu trên hệ thống của OpenAI, Huggingface.... Chúng ta sẽ chỉ việc import các APIKEY và sử dụng thôi. Có một số loại mô hình chúng ta cần lưu ý như sau

LLM Model

Large Language Models (LLMs) chính là các mô hình ngôn ngữ lớn được tạo ra bởi các cụ lớn trong ngành. Quen thuộc nhất với các bạn thì đó là GPT3.5 nền tảng của ChatGPT và xa xưa hơn chút thì chúng ta có GPT-2, GPT-3 đều là các LLM nổi tiếng. Ngoài ra thì còn rất nhiều các loại LLM khác được Langchain hỗ trợ. Vê cơ bản thì các bạn hiểu chức năng của nó là:

Input của LLM là một text string có thể là câu hỏi, một yêu cầu hoặc một câu bất kì. Output của nó cũng là một text string tương ứng với yêu cầu của input đầu vào.

Một ví dụ về việc sử dụng LLM với Langchain như sau

# models-demo.py

import os
from apikey import OPENAI_API_KEY

os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY

llm = OpenAI(model_name="text-ada-001", n=2, best_of=2)

llm_result = llm.generate(
    ["Write a short title for the Viblo article about new framework Langchain"]
)

print(llm_result)

Kết quả sẽ trả về thông tin chi tiết của câu trả lời bao gồm các thông tin như kết quả trả về cũng như các token_usage để chúng ta biết đường mà kiểm soát chi phí.

generations=[[Generation(text='\n\nLangchain: The Next Generation of Blockchain Technology', generation_info={'finish_reason': 'stop', 'logprobs': None}), Generation(text='\n\nLangchain: The Future of Data Security', generation_info={'finish_reason': 'stop', 'logprobs': None})]] llm_output={'token_usage': {'prompt_tokens': 15, 'total_tokens': 38, 'completion_tokens': 23}, 'model_name': 'text-ada-001'}

CHÚ Ý: Ở phía trên do mình chưa cung cấp đầy đủ thông tin về framework Langchain nên nó tự suy luận rằng framework này liên quan đến Blockchain (chắc do có chữ chain trong tên) và gợi ý đặt tiêu đề bài viết là Langchain: The Next Generation of Blockchain Technology. Tóm lại là phải có biết cách đặt câu hỏi và yêu cầu sao cho phù hợp. Cái này người ta gọi là prompt engineering

Nói chung là, sử dụng Langchain các bạn sẽ có một đống các giao diện mà không cần quá quan tâm đến mô hình phía sau. Cần thay đổi cái nào thì thay đổi thôi. Các loại mô hình mà Langchain hiện đang hỗ trợ các bạn có thể xem ở đây

Chat Model

Về cơ bản các Chat model cũng được base trên các mô hình ngôn ngữ lớn tuy nhiên nó sẽ gắn với các ngữ cảnh trong Chatbot. Tiêu biểu và quen thuộc nhất của các loại model này là ChatGPT. Các bạn cứ hiểu đơn giản thì đổi với Chat model thì input đầu vào sẽ không chỉ đơn giản là text và nó sẽ là các chat message. Các chat message này sẽ được input bởi con người, hoặc là câu trả lời của AI hoặc là các thông tin từ hệ thống. Sau khi có được tập hợp các Chat Message thành một đoạn hội thoại thì sẽ đưa đoạn hội thoại đó vào Chat Model. Các loại message đưa vào Chat Model bao gồm:

  • AIMessage: Các message được tạo ra bởi mô hình
  • HumanMessage: Các message được tạo ra bởi con người
  • SystemMessage: Các message được sinh ra bởi hệ thống mục đích để hướng dẫn cho mô hình biết được một số thông tin giúp sinh kết quả tốt hơn
  • ChatMessage: Đây là một lớp chung, từ đó chúng ta có thể custom các message với các role bất kì

Các bạn có thể thử ngay với nó

from langchain.chat_models import ChatOpenAI
from langchain.schema import AIMessage, HumanMessage, SystemMessage

chat = ChatOpenAI(temperature=0)

messages = [
    SystemMessage(
        content="You are a virtual assitant can translate any text input to Vietnamese. You can auto detect the language of input text. You can return the language of input text belong the traslated text. The format is: [source language] - [translated text]"
    ),
    HumanMessage(content="I love you"),
]

print(chat(messages))

Ở ví dụ trên thì mình có một message từ hệ thống để nói với mô hình rằng nó sẽ hoạt động như một trợ lý ảo dịch bất kì một ngôn ngữ nào sang tiếng việt. Nó còn có chức năng tự động phát hiện ngôn ngữ nguồn và trả về kết quả với format [source language] - [translated text]. Sau đó, bạn hãy tưởng tượng người dùng sẽ gõ vào đoạn chat đó một câu là I love you. Lúc này mô hình sẽ tự hiểu rằng cần phải tự động dịch nó sang tiếng việt. Các bạn chạy thử sẽ thấy kết quả như sau

content='English - Tôi yêu bạn.'

Và đây chính là một AIMessage trả về bổ sung thêm vào cuộc hội thoại. Giờ chúng ta sẽ thử thêm một câu khác nữa nhé.

Giờ hãy thử một câu tiếng Nhật xem sao. Thêm vào tiếp đoạn messages phía trên

messages = [
    SystemMessage(
        content="You are a virtual assitant can translate any text input to Vietnamese. You can auto detect the language of input text. You can return the language of input text belong the traslated text. The format is: [source language] - [translated text]"
    ),
    HumanMessage(content="I love you"),
    AIMessage(content="English - Tôi yêu bạn."),
    HumanMessage(content="どうもありがとうございます"),
]

print(chat(messages))

Và giờ kết quả sẽ trả về là

content='Japanese - Cảm ơn bạn rất nhiều.'

Có thể thấy rằng với langchain thì việc xây dựng một chatbot là rất dễ dàng và trực quan phải không các bạn.

Text Embedding Model

Hiểu đơn giản thì embedding chính là đại diện cho một đoạn văn bản. Nó sẽ được biểu diễn bằng một vector có số chiều cố định ví dụ 128 chiều chẳng hạn. Hai vector nào càng gần nhau thì chúng càng có ngữ nghĩa hoặc nội dung giống nhau. Langchain cho phép chúng ta kết nối đến các loại mô hình sinh embedding khác nhau gọi là các Embedding providers (OpenAI, Cohere, Hugging Face, etc).

Tuỳ thuộc vào use case của các bạn mà cần sử dụng embedding. Ví dụ như trong trường hợp muốn tìm kiếm các nội dung liên quan đến câu truy vấn trong đống dữ liệu chẳng hạn thì chúng ta có thể sử dụng embedding. Các bạn có thể thử nó như sau

from langchain.embeddings import OpenAIEmbeddings

embeddings = OpenAIEmbeddings()
text = "This is a test document."

query_result = embeddings.embed_query(text)
print(len(query_result), type(query_result))

Kết quả trả về như sau

1536 <class 'list'>

Tức là một vector có số chiều 1536 chiều. Các bạn có thể lưu lại vector này vào một database hoặc một search engine để thuận tiện cho việc truy vấn sau này

Prompts

Prompt templates

Format Prompt

Gần đây chúng ta nghe đến khái niệm prompt engineering tức là các kĩ thuật viết prompt cho mô hình ngôn ngữ khiến nó có thể trả lời đúng các vấn đề mà chúng ta muốn mô hình ngôn ngữ thực hiện. Một prompt template hiểu đơn giản là một đoạn text bao gồm các chỉ dẫn, các yêu cầu, các ví dụ để đưa vào mô hình ngôn ngữ và nó có thể nhận đầu vào là các tham số do người dùng truyền vào. Từ các tham số này và prompt template chúng ta có thể xây dựng thành một prompt hoàn chỉnh.

Ví dụ luôn cho các bạn, khi chúng ta đang yêu cầu sinh ra một tiêu đề cho video với nội dung ABC và phong cách XYZ chẳng hạn. Sau đó người dùng chỉ việc điền vào ABC và XYZ thôi. Chúng ta sẽ làm như sau

# prompts-demo.py

import os
from apikey import OPENAI_API_KEY
from langchain.llms import OpenAI
from langchain import PromptTemplate

os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY
# Text model example

llm = OpenAI(model_name="text-ada-001", temperature=0.9)

template = """
    Write a title for a Youtube video about {content} with {style} style.
"""

prompt_template = PromptTemplate(
    input_variables=["content", "style"],
    template=template,
)

# Example format prompt 
print(prompt_template.format(content="Deep Learning in 1 minutes", style="funny"))

Chúng ta có thể hình dung đơn giản nó giống như việc format string trong Python vậy thôi. Kết quả sẽ như thế này

Write a title for a Youtube video about Deep Learning in 1 minutes with funny style.

Lưu Prompt thành JSON

Đôi lúc chúng ta sẽ cần lưu lại các prompt template thành dạng JSON để có thể chia sẻ cho người khác hoặc dễ dàng quản lý hơn trong dự án, việc này được thực hiện đơn giản như sau:

# Save prompt to json
prompt_template.save("video_title.json")

Chúng ta sẽ thu được file JSON như sau

{
    "input_variables": [
        "content",
        "style"
    ],
    "output_parser": null,
    "partial_variables": {},
    "template": "\n    Write a title for a Youtube video about {content} with {style} style.\n",
    "template_format": "f-string",
    "validate_template": true,
    "_type": "prompt"
}

Sau đó để load lại prompt template này thì cũng rất đơn giản. Các bạn làm như sau

from langchain.prompts import load_prompt
loaded_prompt = load_prompt("video_title.json")

Thêm một vài few-shot examples cho prompt

Few-shot learning: hiểu đơn giản là bạn chỉ cần cung cấp cho mô hình một vài ví dụ, input và output mong muốn thì mô hình có thể thực hiện tương tự với các câu hỏi khác. Đây được hiểu đơn giản là mồi cho mô hình ngôn ngữ biết cách trả lời giống như mong muốn của bạn hơn. Langchain hỗ trợ chúng ta đưa vào các Few-shot Example sử dụng FewShotPromptTemplate.

Ví dụ về prompt extract thông tin điều khiển nhà thông minh

Chúng ta chắc hẳn đã quá quen thuộc với bài toán extract các thông tin điều khiển từ nhà thông minh rồi phải không. Nếu như trước đây nó được giải quyết rất phức tạp với các thuật toán NLP thì giờ đây chúng ta có thể thực hiện đơn giản bằng các LLM. Ví dụ như chúng ta hãy đưa cho LLM một vài ví dụ tiêu biểu

# First, create the list of few shot examples.
examples = [
    {
        "command": "Turn on the kitchen light",
        "action": "turn on",
        "object": "light",
        "location": "kitchen",
        "value": "",
    },
    {
        "command": "Turn off the TV in the living room",
        "action": "turn off",
        "object": "TV",
        "location": "living room",
        "value": "",
    },
    {
        "command": "Increase the bedroom temperature by 2 degrees",
        "action": "Increase temperture",
        "object": "air-conditional",
        "location": "bed room",
        "value": "2 degrees",
    },
]

Ở trên là các command tương ứng với nó là các action, object, location và value được extract ra từ command đó. Tiếp theo chúng ta cần định nghĩa một template cho việc đưa các example vào.

example_formatter_template = """
    Input command from user: {command}
    The information extracted from above command:\n
    ----
    Action: {action}\n
    Object: {object}\n
    Location: {location}\n
    Value: {value}\n
"""

example_prompt = PromptTemplate(
    input_variables=["command", "action", "object", "location", "value"],
    template=example_formatter_template,
)

Cuối cùng chúng ta sẽ thực hiện tạo ra một prompt template cho các ví dụ FewShot trên

few_shot_prompt = FewShotPromptTemplate(
    # These are the examples we want to insert into the prompt.
    examples=examples,
    # This is how we want to format the examples when we insert them into the prompt.
    example_prompt=example_prompt,
    # The prefix is some text that goes before the examples in the prompt.
    # Usually, this consists of intructions.
    prefix="Extract the detail information for an IoT input command. Return the corresponding action, object, location and value. Below are some examples:",
    # The suffix is some text that goes after the examples in the prompt.
    # Usually, this is where the user input will go
    suffix="Input command from user: {command}\nThe information extracted from above command::",
    # The input variables are the variables that the overall prompt expects.
    input_variables=["command"],
    # The example_separator is the string we will use to join the prefix, examples, and suffix together with.
    example_separator="\n\n",
)

Chúng ta có thể chạy thử prompt trên xem nó sẽ đưa vào mô hình ngôn ngữ các thông tin gì nhé

print(few_shot_prompt.format(command="Turn off the bath room light"))

và kết quả sẽ trả về như sau

Extract the detail information for an IoT input command. Return the corresponding action, object, location and value. Below are some examples:


    Input command from user: Turn on the kitchen light
    The information extracted from above command::

    ----
    Action: turn on

    Object: light

    Location: kitchen

    Value: 




    Input command from user: Turn off the TV in the living room
    The information extracted from above command::

    ----
    Action: turn off

    Object: TV

    Location: living room

    Value: 




    Input command from user: Increase the bedroom temperature by 2 degrees
    The information extracted from above command::

    ----
    Action: Increase temperture

    Object: air-conditional

    Location: bed room

    Value: 2 degrees



Input command from user: Turn off the bath room light
The information extracted from above command:

Đây chính là đầu vào cho mô hình ngôn ngữ.

Chains

Chain là một thành phần rất quan trọng trong framework langchain. Chúng ta có thể thấy tên của framework này được ghép bởi lang là đại diện cho mô hình ngôn ngữ và chain chính là thứ mà chúng ta sẽ tìm hiểu ở phần này. Vậy nó là gì và tại sao lại cần đến nó thì mời bạn đọc tiếp nhé.

Chain là gì? Tại sao lại cần đến chain?

Chains cho phép chúng ta combine rất nhiều các components vào với nhau thành một chuỗi các component, từ đó có thể dễ dàng tạo ra được các các ứng dụng đơn giản, tự nhiên và nhanh chóng nhất. Với các ví dụ phía trên, hoàn toàn chúng ta có thể sử dụng một chain để thực hiện mục đích đó. Có thể định nghĩa đơn giản như sau:

  • Prompt: là những thứ mà chúng ta cần đưa vào mô hình ngôn ngữ
  • Chain: là phương tiện giúp chúng ta đưa các prompt vào mô hình ngôn ngữ và nhận về kết quả

Ví dụ với các prompt về sinh video Youtubeđiều khiển nhà thông minh phía trên chúng ta có thể lắp nó vào một chain và đưa vào mô hình ngôn ngữ, nhận về kết quả như sau

Đối với chain sinh video Youtube

# prompts-demo.py
from langchain.chains import LLMChain

# Define a chain
chain = LLMChain(llm=llm, prompt=prompt_template)

print(chain.run(content="Deep Learning in 1 minutes", style="funny"))

Kết quả trả về sẽ là

How to Use Deep Learning for 1 Minute Perfectussions

Hoặc với bài toán trích xuất thông tin command cho nhà thông mình

chain = LLMChain(llm=llm, prompt=few_shot_prompt)

print(chain.run(command="Turn off the bath room light"))

thì kết quả trả về nó sẽ như sau

Input command from user: Turn off the bath room light
The information extracted from above command:


----
Action: turn off

Object: light

Location: bath room

Value:

Tạo chains đơn giản với SimpleSequentialChain

Thông thường chúng ta sẽ không chỉ sử dụng chain với 1 prompt duy nhất mà thường là tổng hợp của nhiều prompt. Điều này cũng dễ hiểu bởi thông thường để thực hiện một việc gì đó thì chúng ta cần phải chia ra thành nhiều step khác nhau. Mỗi step sẽ là một prompt riêng biệt và kết quả của step hiện tại sẽ là input cho step tiếp theo. Lúc này chúng ta sẽ cần sử dụng combine chains. Một cách đơn giản nhất đó là SequentialChain khi đó một step sẽ có một input/output và output của step hiện tại sẽ là input của step tiếp theo.

Ví dụ như trong usecase mà chúng ta đang thử nghiệm bên trên, giả sử sau khi chúng ta đã bắt mô hình ngôn ngữ nghĩ ra tên cho video Youtube của chúng ta thì tiếp theo chúng ta có thể bắt nó sinh ra dàn ý các mục chúng ta nên nói trong video đó. Các bạn thực hiện như sau:

Đầu tiên chúng ta tạo hai prompt template

# chains-demo.py

from langchain.chains import SimpleSequentialChain

video_title_prompt_template = PromptTemplate(
    input_variables=["content"],
    template="""
        Write a title for a Youtube video about {content}
    """,
)

video_outline_prompt_template = PromptTemplate(
    input_variables=["title"],
    template="""
        Write a outline of a Youtube video about {title}. Output in the bullet list format. 
    """,
)

Sau đó tạo ra 2 chain với prompt template đã tạo ở trên với combine nó lại bằng SimpleSequentialChain

overall_chain = SimpleSequentialChain(
    chains=[
        LLMChain(llm=llm, prompt=video_title_prompt_template),
        LLMChain(llm=llm, prompt=video_outline_prompt_template),
    ],
    verbose=True,
)

Cuối cùng ta chạy chain đó và xem kết quả step-by-step

video_outline = overall_chain.run("Deep Learning in 1 minutes")
print(video_outline)

Chúng ta sẽ thu được kết quả của từng chain như sau

# Output của chain 1: sinh title 

    "Deep Learning in 1 Minute: Unlocking the Power of AI"
# Output của chain 2: sinh outline

• Introduction 
    - What is Deep Learning? 
    - What are the benefits of Deep Learning? 
• Overview of Deep Learning 
    - What is the difference between Machine Learning and Deep Learning? 
    - What are the components of Deep Learning? 
• Applications of Deep Learning 
    - How is Deep Learning used in the real world? 
    - Examples of Deep Learning in action 
• Conclusion 
    - Summary of Deep Learning 
    - Benefits of Deep Learning 
    - Final thoughts

Tạo chain phức tạp hơn với SequentialChain

Ở ví dụ trên thì chúng ta đã thử nghiệm với các chain đơn giản với chỉ 1 input và 1 output cho từng chain, nhưng trong thực tế thì không phải lúc nào cũng xuất hiện các chain đơn giản như vậy. Thường thì 1 chain sẽ có thể nhận nhiều input và trả ra nhiều output. Giờ chúng ta sẽ quay lại với ví dụ bên trên nhưng thay vì sinh title theo nội dung thì có thể theo cả style nữa. Chúng ta sửa lại template đó như sau

video_title_prompt_template = PromptTemplate(
    input_variables=["content", "style"],
    template="""
        Write a title for a Youtube video about {content} with {style} style.
    """,
)

video_outline_prompt_template = PromptTemplate(
    input_variables=["title"],
    template="""
        Write a outline of a Youtube video about {title}. Output in the bullet list format. 
    """,
)

Sau đó chúng ta sửa lại chains với SequentialChain

overall_chain = SequentialChain(
    chains=[
        LLMChain(llm=llm, prompt=video_title_prompt_template, output_key="title"),
        LLMChain(llm=llm, prompt=video_outline_prompt_template, output_key="outline"),
    ],
    input_variables=["content", "style"],
    output_variables=["title", "outline"],
    verbose=True,
)

Chúng ta thấy, nếu như một chain trong SequentialChain có nhiều input hoặc nhiều output thì nó sẽ quy định bằng input_keysoutput_keys. Cả 1 chains lớn cũng sẽ quy định các tham số này. Chúng ta cùng chạy thử chain ở bên trên xem sao

video_outline = overall_chain(
    {"content": "Deep Learning in 1 minutes", "style": "funny"}
)
print(video_outline)

Kết quả như sau:

> Entering new SequentialChain chain...

> Finished chain.
{'content': 'Deep Learning in 1 minutes', 'style': 'funny', 'title': '\n"Deep Learning in 60 Seconds: A Hilarious Crash Course!"', 'outline': '\n• Introduction \n    - What is Deep Learning? \n    - What can Deep Learning do? \n• Deep Learning Basics \n    - What is a Neural Network? \n    - How does a Neural Network work? \n    - What are the different types of Neural Networks? \n• Applications of Deep Learning \n    - What are some of the most common applications of Deep Learning? \n    - How is Deep Learning used in the real world? \n• Conclusion \n    - Summary of Deep Learning \n    - Benefits of Deep Learning \n    - Final Thoughts'}

Ngoài ra có rất nhiều loại chains khác nhau tuỳ thuộc vào từng ứng dụng cụ thể mà chúng ta sẽ áp dụng khác nhau. Trong phạm vi bài viết này mình sẽ không thể liệt kê hết tất cả các thành phần của Chains trong Langchain được. Các bạn có thể tham khảo thêm tại đây giúp mình nhé.

Agents

Đây có lẽ là phần mà mình muốn nói nhất của Langchain. Vì thông thường trong các ứng dụng thực tế thì không phải lúc nào chúng ta cũng biết trước người dùng sẽ nhập vào nội dung gì, với mục đích gì để tiến hành tạo các chain riêng cho chúng. Thường thì tuỳ vào cái mà người dùng hỏi thì chúng ta sẽ cần quyết định xem nó thuộc vào chain nào. Đây là lúc chúng ta cần sử dụng agent. Tuỳ thuộc vào user input, agent sẽ quyết định xem cần sử dụng các công cụ nào cho các bước xử lý tiếp theo.

Một cách tổng quát chúng ta có thể hiểu luồng hoạt động chính của agent như sau:

  • Nhận vào user input
  • Agent quyết định xem sử dụng tool (nếu có sẵn) và quyết định xem input của các tool cần dùng là gì.
  • Các tool sẽ được chạy với các input cần thiết và output của tool sẽ được ghi lại
  • Các input, output và quá trình thực hiện của tool sẽ được truyền trở lại Agent. Agent sẽ quyết định các bước thực hiện tiếp theo
  • Lặp lại quá trình trên cho đến khi Agent tìm được kết quả cuối cùng để trả cho người dùng

Minh hoạ sử dụng tools

Khi bắt đầu khởi tạo một Agent, chúng ta cần truyền cho nó các tool mà nó có thể sử dụng trong ứng dụng của chúng ta. Một tool thường sẽ có các thành phần sau:

  • Name: yêu cầu bắt buộc khi định nghĩa một tool và nhận một giá trị duy nhất để phân biệt giữa các tool với nhau
  • Description: là phần mô hình của tool, có thể không cần nhưng langchain khuyến khích chúng ta viết rõ mô tả chức năng và cách thực hiện trong tool. Phần mô tả này rất hữu ích cho LLM để có thể định nghĩa được các tool nào cần sử dụng trong các bối cảnh cụ thể
  • args_schema: là các tham số bổ sung và được recommend sử dụng trong langchain, nó được sử dụng để cung cấp thêm nhiều information như các few-shot examples hoặc validate các expected parameters

Ở đây mình sẽ minh hoạ cách sử dụng tool để có thể thực hiện các công việc khác nhau như tìm kiếm, thực hiện các phép toán hay recommendation các bài post liên quan đến user như sau:

Đầu tiên là import các thư viện cần thiết

# agents-demo.py
import os
import requests
from apikey import OPENAI_API_KEY
from langchain.llms import OpenAI
from langchain.agents import tool

from langchain.agents import initialize_agent, AgentType

os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY
# Text model example

llm = OpenAI(temperature=0.1)

Tiếp theo là khai báo các tools cần sử dụng.


@tool("search", return_direct=True)
def search(query: str) -> str:
    """
    You call this function when user need search information for an input string (in variable query) and return the search results back to user
    """
    return f"Search API Results for {query}"


@tool("post-recommendation", return_direct=True)
def post_recommendation(user_id: str) -> dict:
    """
    You call this function when user want to provide the recommended posts related for user.
    This function will be call to backend API to do this recommendation logic and return most related posts for user
    """
    response = requests.get(
        "https://langchain-demo.free.mockoapp.net/post-recommendation"
    )
    return response.json()


@tool("add", return_direct=True)
def add(a: int, b: int) -> int:
    """
    You call this function when user want to add two number and return the result back to user
    """
    return a + b


@tool("subtract", return_direct=True)
def subtract(a: int, b: int) -> int:
    """
    You call this function when user want to substract two number and return the result back to user
    """
    return a - b


@tool("multiply", return_direct=True)
def multiply(a: int, b: int) -> int:
    """
    You call this function when user want to multiply two number and return the result back to user
    """
    return a * b

Các bạn có thể thấy trong từng docstrings của mỗi tool chúng ta mô tả mục đích và ý nghĩa của tool, do đó tuỳ thuộc vào yêu cầu của mô hình mà sẽ lựa chọn sử dụng tool cho phù hợp. Việc này được thực hiện hoàn toàn tự động bởi LLM. Tiếp theo là bước sử dụng tools với agent. Chúng ta thực hiện rất đơn giản như sau

tools = [multiply, add, subtract, search, post_recommendation]

agent = initialize_agent(
    tools,
    llm,
    agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True,
)

Các bạn lưu ý là phải sử dụng STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION thì Agent mới có thể nhận đầu vào là các tool có nhiều hơn 1 tham số.

Sau đó việc đơn giản là gọi agent thôi

command = "Give me the list of posts related to me"

result = agent.run(command)

print(result)

Kết quả sẽ như sau

> Entering new AgentExecutor chain...
Action:

{ "action": "post-recommendation", "action_input": "user_id" }


Observation: {'posts': [{'id': 1, 'title': 'Post 1'}, {'id': 2, 'title': 'Post 2'}]}

> Finished chain.
{'posts': [{'id': 1, 'title': 'Post 1'}, {'id': 2, 'title': 'Post 2'}]}

Đây chính là kết quả mà mình đã tạo ra danh sách bài viết trên API fake tại https://langchain-demo.free.mockoapp.net/post-recommendation. Các bạn hoàn toàn có thể tự deploy riêng một API cho ứng dụng của các bạn. Truy cập API trên bằng trình duyệt chúng ta thấy các bài post đã được recommend cho người dùng theo kết quả trả ra của APi

image.png

Kết luận

Trên đây mình có liệt kê qua một vài thành phần chính của Langchain. Cá nhân mình thấy đây là một framework rất hay để tận dụng sức mạnh của LLM vào trong ứng dụng của bạn. Tất nhiên có rất nhiều thành phần khác trong langchain nhưng mình xin phép dành cho các bài viết tiếp theo. Cảm ơn các bạn đã đọc đến dây và hẹn gặp lại trong các bài viết tiếp theo

Source code

Toàn bộ source code trong bài viết các bạn có thể tham khảo tạo đây


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí