Tùy chỉnh LLM

Trong lĩnh vực mô hình trí tuệ nhân tạo hiện tại, có rất nhiều mô hình khác nhau và tích hợp chính thức của LangChain không bao phủ tất cả các mô hình. Đôi khi bạn có thể cần tùy chỉnh một mô hình và tích hợp nó vào khung công việc của LangChain.

Chương này sẽ giới thiệu cách tạo một lớp bọc LLM tùy chỉnh, giúp bạn dễ dàng sử dụng mô hình riêng hoặc các mô hình không được hỗ trợ bởi LangChain.

Trong LangChain, nếu bạn muốn sử dụng LLM riêng hoặc một lớp bọc khác so với lớp bọc được hỗ trợ bởi LangChain, bạn có thể tạo một lớp bọc LLM tùy chỉnh. Một LLM tùy chỉnh chỉ cần thực hiện hai phương thức bắt buộc sau:

  • Một phương thức _call, nhận một chuỗi làm đầu vào, một số từ dừng tùy chọn và trả về một chuỗi, thực hiện việc gọi mô hình trong phương thức _call.
  • Một thuộc tính _llm_type, trả về một chuỗi biểu diễn tên mô hình, chỉ được sử dụng cho mục đích ghi nhật ký.

Ngoài các phương thức bắt buộc, một LLM tùy chỉnh cũng có thể thực hiện một phương thức tùy chọn:

  • Một thuộc tính _identifying_params, được sử dụng để giúp in ra lớp. Nó nên trả về một từ điển.

Thực hiện một LLM tùy chỉnh đơn giản

Hãy thực hiện một LLM tùy chỉnh rất đơn giản chỉ trả về n ký tự đầu tiên của đầu vào.

from typing import Any, List, Mapping, Optional

from langchain_core.callbacks.manager import CallbackManagerForLLMRun
from langchain_core.language_models.llms import LLM

class CustomLLM(LLM):
    n: int

    @property
    def _llm_type(self) -> str:
        return "tùy chỉnh"

    def _call(
        self,
        prompt: str,
        stop: Optional[List[str]] = None,
        run_manager: Optional[CallbackManagerForLLMRun] = None,
        **kwargs: Any,
    ) -> str:
        if stop is not None:
            raise ValueError("Tham số dừng không được phép.")
        return prompt[: self.n]

    @property
    def _identifying_params(self) -> Mapping[str, Any]:
        """Lấy các tham số xác định."""
        return {"n": self.n}

Bây giờ chúng ta có thể sử dụng LLM tùy chỉnh này giống như bất kỳ LLM nào khác.

Sử dụng LLM tùy chỉnh

Chúng ta có thể khởi tạo và sử dụng đối tượng LLM tùy chỉnh, làm thể nào để gọi LLM tùy chỉnh và tùy chỉnh kết quả in ra.

llm = CustomLLM(n=10)
llm.invoke("Đây là một cái gì đó")
'Đây là một '

Chúng ta cũng có thể in ra LLM và xem kết quả in ra được tùy chỉnh.

print(llm)
CustomLLM
Tham số: {'n': 10}

Tùy chỉnh Mô hình Trò chuyện

Ở đây chúng ta sẽ giải thích cách tùy chỉnh mô hình trò chuyện của LangChain.

Đầu vào và Đầu ra Tin nhắn

Trong mô hình trò chuyện, tin nhắn là trọng tâm của đầu vào và đầu ra. Một tin nhắn là nội dung được nhập bởi người dùng và phản hồi được tạo ra bởi mô hình.

Tin nhắn

Mô hình trò chuyện nhận tin nhắn làm đầu vào và sau đó tạo ra một hoặc nhiều tin nhắn làm đầu ra. Trong LangChain, có một số loại tin nhắn tích hợp sẵn, bao gồm:

  • SystemMessage: Được sử dụng để khởi tạo hành vi trí tuệ nhân tạo, thường được sử dụng như tin nhắn đầu tiên trong chuỗi các tin nhắn đầu vào.
  • HumanMessage: Đại diện cho sự tương tác của người dùng với mô hình trò chuyện.
  • AIMessage: Đại diện cho các tin nhắn từ mô hình trò chuyện, có thể là văn bản hoặc yêu cầu triệu hồi công cụ.
  • FunctionMessage / ToolMessage: Được sử dụng để truyền kết quả của việc triệu hồi công cụ trở lại mô hình.

Việc sử dụng các loại tin nhắn này có thể được mở rộng và tùy chỉnh theo yêu cầu cụ thể, chẳng hạn như điều chỉnh dựa trên các tham số hành độngcông cụ của OpenAI.

from langchain_core.messages import (
    AIMessage,
    BaseMessage,
    FunctionMessage,
    HumanMessage,
    SystemMessage,
)

Biến thể trôi chảy

Tất cả các tin nhắn trò chuyện đều có một biến thể trôi chảy với Chunk trong tên của chúng.

from langchain_core.messages import (
    AIMessageChunk,
    FunctionMessageChunk,
    HumanMessageChunk,
    SystemMessageChunk,
    ToolMessageChunk,
)

Các Chunk này được sử dụng khi truyền dữ liệu mô hình trò chuyện và mỗi trong số chúng định nghĩa một thuộc tính tích lũy!

Ví dụ

AIMessageChunk(content="Xin chào") + AIMessageChunk(content=" thế giới!")

Trả về

AIMessageChunk(content='Xin chào thế giới!')

Mô hình Chat Đơn Giản

Kế thừa từ SimpleChatModel cho phép triển khai một cách nhanh chóng một mô hình chat đơn giản.

Mặc dù có thể không tích hợp tất cả các chức năng cần thiết cho một mô hình chat, nó cung cấp một triển khai nhanh chóng. Nếu cần thêm tính năng, chuyển sang sử dụng BaseChatModel được mô tả bên dưới là có thể.

Kế thừa từ SimpleChatModel yêu cầu triển khai các giao diện sau:

  • Phương thức _call - triển khai cuộc gọi API mô hình bên ngoài.

Ngoài ra, có thể được xác định:

  • Thuộc tính _identifying_params - được sử dụng để ghi lại thông tin tham số hóa của mô hình.

Tùy chọn:

  • Phương thức _stream - được sử dụng để triển khai đầu ra lưu trữ.

Mô Hình Chat Cơ Bản

Kế thừa từ BaseChatModel yêu cầu triển khai phương pháp _generate và thuộc tính _llm_type. Tùy chọn, triển khai của _stream, _agenerate, _astream_identifying_params là có thể.

Ví dụ về Mô Hình Chat Tùy chỉnh

Trong phần này, chúng ta sẽ thể hiện việc triển khai mã của một mô hình chat tùy chỉnh được gọi là CustomChatModelAdvanced, bao gồm việc tạo kết quả chat, đầu ra lưu trữ và triển khai đầu ra lưu trữ không đồng bộ.

from typing import Any, AsyncIterator, Dict, Iterator, List, Optional

from langchain_core.callbacks import (
    AsyncCallbackManagerForLLMRun,
    CallbackManagerForLLMRun,
)
from langchain_core.language_models import BaseChatModel, SimpleChatModel
from langchain_core.messages import AIMessageChunk, BaseMessage, HumanMessage
from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, ChatResult
from langchain_core.runnables import run_in_executor


class CustomChatModelAdvanced(BaseChatModel):
    """Triển khai một mô hình chat tùy chỉnh trả về `n` ký tự đầu tiên của tin nhắn cuối cùng."""


    n: int
    """Tham số mô hình tùy chỉnh"""

    def _generate(
        self,
        messages: List[BaseMessage],
        stop: Optional[List[str]] = None,
        run_manager: Optional[CallbackManagerForLLMRun] = None,
        **kwargs: Any,
    ) -> ChatResult:
        """Ở đây, logic gọi mô hình được triển khai, thường bằng cách gọi API của một mô hình bên thứ ba, sau đó đóng gói kết quả trả về từ API vào một định dạng mà langchain có thể nhận dạng.
        Giải thích tham số chính:
            messages: Một danh sách các đầu vào bao gồm các tin nhắn
        """
        last_message = messages[-1]
        tokens = last_message.content[: self.n]
        message = AIMessage(content=tokens)
        generation = ChatGeneration(message=message)
        return ChatResult(generations=[generation])

    def _stream(
        self,
        messages: List[BaseMessage],
        stop: Optional[List[str]] = None,
        run_manager: Optional[CallbackManagerForLLMRun] = None,
        **kwargs: Any,
    ) -> Iterator[ChatGenerationChunk]:
        """Triển khai đầu ra lưu trữ mô hình, tương tự như phương thức _generate, nhưng với xử lý đầu ra lưu trữ."""
        last_message = messages[-1]
        tokens = last_message.content[: self.n]

        for token in tokens:
            chunk = ChatGenerationChunk(message=AIMessageChunk(content=token))

            if run_manager:
                run_manager.on_llm_new_token(token, chunk=chunk)

            yield chunk

    async def _astream(
        self,
        messages: List[BaseMessage],
        stop: Optional[List[str]] = None,
        run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
        **kwargs: Any,
    ) -> AsyncIterator[ChatGenerationChunk]:
        """Phiên bản không đồng bộ của phương thức `stream` được triển khai"""
        result = await run_in_executor(
            None,
            self._stream,
            messages,
            stop=stop,
            run_manager=run_manager.get_sync() if run_manager else None,
            **kwargs,
        )
        for chunk in result:
            yield chunk

    @property
    def _llm_type(self) -> str:
        """Trả về nhãn của mô hình tùy chỉnh"""
        return "mô-hình-chat-nâng-cao"

    @property
    def _identifying_params(self) -> Dict[str, Any]:
        """Trả về thông tin gỡ lỗi tùy chỉnh"""
        return {"n": self.n}

Kiểm thử Mô Hình Chat Tùy chỉnh

Hãy kiểm thử mô hình chat, bao gồm sử dụng các phương thức invoke, batch, stream, và triển khai đầu ra lưu trữ không đồng bộ.

model = CustomChatModelAdvanced(n=3)

model.invoke([HumanMessage(content="Xin chào!")])

model.invoke("Xin chào")

model.batch(["Xin chào", "Tạm biệt"])

for chunk in model.stream("mèo"):
    print(chunk.content, end="|")

async for chunk in model.astream("mèo"):
    print(chunk.content, end="|")

async for event in model.astream_events("mèo", version="v1"):
    print(event)