Ở cốt lõi của nó, LangChain là một khung sáng tạo được thiết kế để tạo các ứng dụng tận dụng khả năng của các mô hình ngôn ngữ. Đó là bộ công cụ được thiết kế dành cho các nhà phát triển để tạo ra các ứng dụng nhận biết ngữ cảnh và có khả năng suy luận phức tạp.
Điều này có nghĩa là các ứng dụng LangChain có thể hiểu ngữ cảnh, chẳng hạn như hướng dẫn nhanh chóng hoặc phản hồi căn bản về nội dung và sử dụng mô hình ngôn ngữ cho các nhiệm vụ lý luận phức tạp, như quyết định cách phản hồi hoặc hành động cần thực hiện. LangChain thể hiện một cách tiếp cận thống nhất để phát triển các ứng dụng thông minh, đơn giản hóa hành trình từ ý tưởng đến thực thi với các thành phần đa dạng của nó.
Hiểu LangChain
LangChain không chỉ là một khuôn khổ; đó là một hệ sinh thái hoàn chỉnh bao gồm nhiều phần không thể thiếu.
- Đầu tiên, có Thư viện LangChain, có sẵn bằng cả Python và JavaScript. Các thư viện này là xương sống của LangChain, cung cấp giao diện và tích hợp cho nhiều thành phần khác nhau. Chúng cung cấp thời gian chạy cơ bản để kết hợp các thành phần này thành các chuỗi và tác nhân gắn kết, cùng với các triển khai sẵn sàng để sử dụng ngay.
- Tiếp theo, chúng ta có Mẫu LangChain. Đây là tập hợp các kiến trúc tham chiếu có thể triển khai được thiết kế riêng cho nhiều nhiệm vụ. Cho dù bạn đang xây dựng một chatbot hay một công cụ phân tích phức tạp thì những mẫu này đều mang đến một điểm khởi đầu vững chắc.
- LangServe bước vào như một thư viện linh hoạt để triển khai chuỗi LangChain dưới dạng API REST. Công cụ này rất cần thiết để biến các dự án LangChain của bạn thành các dịch vụ web có thể truy cập và mở rộng.
- Cuối cùng, LangSmith đóng vai trò là nền tảng dành cho nhà phát triển. Nó được thiết kế để gỡ lỗi, kiểm tra, đánh giá và giám sát các chuỗi được xây dựng trên bất kỳ khung LLM nào. Việc tích hợp liền mạch với LangChain khiến nó trở thành công cụ không thể thiếu đối với các nhà phát triển muốn tinh chỉnh và hoàn thiện ứng dụng của họ.
Cùng với nhau, các thành phần này cho phép bạn phát triển, sản xuất và triển khai các ứng dụng một cách dễ dàng. Với LangChain, bạn bắt đầu bằng cách viết ứng dụng của mình bằng thư viện, tham khảo các mẫu để được hướng dẫn. Sau đó, LangSmith sẽ giúp bạn kiểm tra, thử nghiệm và giám sát dây chuyền của bạn, đảm bảo rằng các ứng dụng của bạn không ngừng cải tiến và sẵn sàng triển khai. Cuối cùng, với LangServe, bạn có thể dễ dàng chuyển đổi bất kỳ chuỗi nào thành API, giúp việc triển khai trở nên dễ dàng.
Trong các phần tiếp theo, chúng ta sẽ tìm hiểu sâu hơn về cách thiết lập LangChain và bắt đầu hành trình tạo các ứng dụng thông minh, dựa trên mô hình ngôn ngữ.
Tự động hóa các tác vụ và quy trình làm việc thủ công bằng trình tạo quy trình làm việc dựa trên AI của chúng tôi, được Nanonets thiết kế cho bạn và nhóm của bạn.
Cài đặt và thiết lập
Bạn đã sẵn sàng hòa mình vào thế giới của LangChain chưa? Việc thiết lập rất đơn giản và hướng dẫn này sẽ hướng dẫn bạn thực hiện quy trình theo từng bước.
Bước đầu tiên trong hành trình LangChain của bạn là cài đặt nó. Bạn có thể thực hiện việc này dễ dàng bằng cách sử dụng pip hoặc conda. Chạy lệnh sau trong terminal của bạn:
pip install langchain
Đối với những người thích các tính năng mới nhất và thoải mái phiêu lưu hơn một chút, bạn có thể cài đặt LangChain trực tiếp từ nguồn. Sao chép kho lưu trữ và điều hướng đến langchain/libs/langchain
danh mục. Sau đó chạy:
pip install -e .
Đối với các tính năng thử nghiệm, hãy cân nhắc việc cài đặt langchain-experimental
. Đó là một gói chứa mã tiên tiến và dành cho mục đích nghiên cứu và thử nghiệm. Cài đặt nó bằng cách sử dụng:
pip install langchain-experimental
LangChain CLI là một công cụ hữu ích để làm việc với các mẫu LangChain và dự án LangServe. Để cài đặt LangChain CLI, hãy sử dụng:
pip install langchain-cli
LangServe rất cần thiết để triển khai chuỗi LangChain của bạn dưới dạng API REST. Nó được cài đặt cùng với LangChain CLI.
LangChain thường yêu cầu tích hợp với các nhà cung cấp mô hình, kho dữ liệu, API, v.v. Trong ví dụ này, chúng tôi sẽ sử dụng API mô hình của OpenAI. Cài đặt gói OpenAI Python bằng cách sử dụng:
pip install openai
Để truy cập API, hãy đặt khóa API OpenAI của bạn làm biến môi trường:
export OPENAI_API_KEY="your_api_key"
Ngoài ra, hãy chuyển khóa trực tiếp vào môi trường python của bạn:
import os
os.environ['OPENAI_API_KEY'] = 'your_api_key'
LangChain cho phép tạo các ứng dụng mô hình ngôn ngữ thông qua các mô-đun. Các mô-đun này có thể độc lập hoặc được kết hợp cho các trường hợp sử dụng phức tạp. Các mô-đun này là -
- Mô hình I / O: Tạo điều kiện tương tác với các mô hình ngôn ngữ khác nhau, xử lý đầu vào và đầu ra của chúng một cách hiệu quả.
- Truy xuất: Cho phép truy cập và tương tác với dữ liệu dành riêng cho ứng dụng, rất quan trọng cho việc sử dụng dữ liệu động.
- Đại lý: Trao quyền cho ứng dụng để lựa chọn các công cụ phù hợp dựa trên chỉ thị cấp cao, nâng cao khả năng ra quyết định.
- Chains: Cung cấp các thành phần có thể tái sử dụng, được xác định trước, đóng vai trò là khối xây dựng để phát triển ứng dụng.
- Bộ nhớ: Duy trì trạng thái ứng dụng trong nhiều lần thực thi chuỗi, cần thiết cho các tương tác nhận biết ngữ cảnh.
Mỗi mô-đun nhắm đến các nhu cầu phát triển cụ thể, biến LangChain trở thành bộ công cụ toàn diện để tạo các ứng dụng mô hình ngôn ngữ nâng cao.
Ngoài các thành phần trên, ta còn có Ngôn ngữ biểu thức LangChain (LCEL), đây là một cách khai báo để dễ dàng kết hợp các mô-đun lại với nhau và điều này cho phép xâu chuỗi các thành phần bằng giao diện Runnable phổ quát.
LCEL trông giống như thế này –
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import BaseOutputParser # Example chain
chain = ChatPromptTemplate() | ChatOpenAI() | CustomOutputParser()
Bây giờ chúng ta đã đề cập đến những điều cơ bản, chúng ta sẽ tiếp tục:
- Tìm hiểu sâu hơn về từng mô-đun Langchain một cách chi tiết.
- Tìm hiểu cách sử dụng Ngôn ngữ biểu thức LangChain.
- Khám phá các trường hợp sử dụng phổ biến và triển khai chúng.
- Triển khai ứng dụng end-to-end với LangServe.
- Hãy xem LangSmith để biết cách gỡ lỗi, kiểm tra và giám sát.
Băt đâu nao!
Mô-đun I: Mô hình I/O
Trong LangChain, yếu tố cốt lõi của bất kỳ ứng dụng nào đều xoay quanh mô hình ngôn ngữ. Mô-đun này cung cấp các khối xây dựng thiết yếu để giao tiếp hiệu quả với bất kỳ mô hình ngôn ngữ nào, đảm bảo tích hợp và giao tiếp liền mạch.
Các thành phần chính của mô hình I/O
- LLM và Mô hình trò chuyện (được sử dụng thay thế cho nhau):
- LLM:
- Định nghĩa: Các mô hình hoàn thiện văn bản thuần túy.
- Đầu ra đầu vào: Lấy một chuỗi văn bản làm đầu vào và trả về một chuỗi văn bản làm đầu ra.
- Mô hình trò chuyện
- LLM:
- Định nghĩa: Các mô hình sử dụng mô hình ngôn ngữ làm cơ sở nhưng khác nhau về định dạng đầu vào và đầu ra.
- Đầu ra đầu vào: Chấp nhận danh sách tin nhắn trò chuyện làm đầu vào và trả về Tin nhắn trò chuyện.
- Prompt: Tạo khuôn mẫu, chọn động và quản lý đầu vào mô hình. Cho phép tạo lời nhắc linh hoạt và theo ngữ cảnh cụ thể để hướng dẫn phản hồi của mô hình ngôn ngữ.
- Trình phân tích cú pháp đầu ra: Trích xuất và định dạng thông tin từ đầu ra của mô hình. Hữu ích cho việc chuyển đổi đầu ra thô của mô hình ngôn ngữ thành dữ liệu có cấu trúc hoặc các định dạng cụ thể mà ứng dụng cần.
LLM
Sự tích hợp của LangChain với các Mô hình ngôn ngữ lớn (LLM) như OpenAI, Cohere và Hugging Face là một khía cạnh cơ bản trong chức năng của nó. Bản thân LangChain không lưu trữ LLM nhưng cung cấp giao diện thống nhất để tương tác với nhiều LLM khác nhau.
Phần này cung cấp thông tin tổng quan về cách sử dụng trình bao bọc OpenAI LLM trong LangChain, có thể áp dụng cho các loại LLM khác. Chúng tôi đã cài đặt tính năng này trong phần “Bắt đầu”. Hãy để chúng tôi khởi tạo LLM.
from langchain.llms import OpenAI
llm = OpenAI()
- LLM thực hiện Giao diện Runnable, khối xây dựng cơ bản của Ngôn ngữ biểu thức LangChain (LCEL). Điều này có nghĩa là họ hỗ trợ
invoke
,ainvoke
,stream
,astream
,batch
,abatch
,astream_log
cuộc gọi. - LLM chấp nhận dây làm đầu vào hoặc đối tượng có thể bị ép buộc phải tuân theo chuỗi lời nhắc, bao gồm
List[BaseMessage]
vàPromptValue
. (nhiều hơn về những điều này sau)
Chúng ta hãy xem xét một số ví dụ.
response = llm.invoke("List the seven wonders of the world.")
print(response)
Ngoài ra, bạn có thể gọi phương thức truyền phát để truyền phát phản hồi văn bản.
for chunk in llm.stream("Where were the 2012 Olympics held?"): print(chunk, end="", flush=True)
Mô hình trò chuyện
Việc tích hợp LangChain với các mô hình trò chuyện, một biến thể chuyên biệt của mô hình ngôn ngữ, là điều cần thiết để tạo các ứng dụng trò chuyện tương tác. Trong khi sử dụng các mô hình ngôn ngữ trong nội bộ, các mô hình trò chuyện trình bày một giao diện riêng biệt tập trung vào các tin nhắn trò chuyện làm đầu vào và đầu ra. Phần này cung cấp thông tin tổng quan chi tiết về cách sử dụng mô hình trò chuyện của OpenAI trong LangChain.
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI()
Các mô hình trò chuyện trong LangChain hoạt động với nhiều loại tin nhắn khác nhau như AIMessage
, HumanMessage
, SystemMessage
, FunctionMessage
và ChatMessage
(với một tham số vai trò tùy ý). Nói chung là, HumanMessage
, AIMessage
và SystemMessage
được sử dụng thường xuyên nhất.
Mô hình trò chuyện chủ yếu chấp nhận List[BaseMessage]
như đầu vào. Chuỗi có thể được chuyển đổi thành HumanMessage
và PromptValue
cũng được hỗ trợ.
from langchain.schema.messages import HumanMessage, SystemMessage
messages = [ SystemMessage(content="You are Micheal Jordan."), HumanMessage(content="Which shoe manufacturer are you associated with?"),
]
response = chat.invoke(messages)
print(response.content)
Prompt
Lời nhắc rất cần thiết trong việc hướng dẫn các mô hình ngôn ngữ để tạo ra kết quả đầu ra phù hợp và mạch lạc. Chúng có thể bao gồm từ các hướng dẫn đơn giản đến các ví dụ phức tạp về vài lần bắn. Trong LangChain, các lời nhắc xử lý có thể là một quy trình rất hợp lý nhờ có một số lớp và chức năng chuyên dụng.
LangChain's PromptTemplate
class là một công cụ linh hoạt để tạo các chuỗi nhắc nhở. Nó sử dụng Python str.format
cú pháp, cho phép tạo dấu nhắc động. Bạn có thể xác định mẫu bằng các phần giữ chỗ và điền vào chúng các giá trị cụ thể nếu cần.
from langchain.prompts import PromptTemplate # Simple prompt with placeholders
prompt_template = PromptTemplate.from_template( "Tell me a {adjective} joke about {content}."
) # Filling placeholders to create a prompt
filled_prompt = prompt_template.format(adjective="funny", content="robots")
print(filled_prompt)
Đối với mô hình trò chuyện, lời nhắc có cấu trúc chặt chẽ hơn, bao gồm các tin nhắn có vai trò cụ thể. Ưu đãi của LangChain ChatPromptTemplate
vì mục đích này.
from langchain.prompts import ChatPromptTemplate # Defining a chat prompt with various roles
chat_template = ChatPromptTemplate.from_messages( [ ("system", "You are a helpful AI bot. Your name is {name}."), ("human", "Hello, how are you doing?"), ("ai", "I'm doing well, thanks!"), ("human", "{user_input}"), ]
) # Formatting the chat prompt
formatted_messages = chat_template.format_messages(name="Bob", user_input="What is your name?")
for message in formatted_messages: print(message)
Cách tiếp cận này cho phép tạo ra các chatbot tương tác, hấp dẫn với các phản hồi động.
Cả hai PromptTemplate
và ChatPromptTemplate
tích hợp hoàn hảo với Ngôn ngữ biểu thức LangChain (LCEL), cho phép chúng trở thành một phần của quy trình công việc phức tạp, lớn hơn. Chúng ta sẽ thảo luận thêm về điều này sau.
Mẫu lời nhắc tùy chỉnh đôi khi rất cần thiết cho các tác vụ yêu cầu định dạng duy nhất hoặc hướng dẫn cụ thể. Việc tạo mẫu lời nhắc tùy chỉnh bao gồm việc xác định các biến đầu vào và phương thức định dạng tùy chỉnh. Tính linh hoạt này cho phép LangChain đáp ứng nhiều yêu cầu dành riêng cho ứng dụng. Đọc thêm ở đây.
LangChain cũng hỗ trợ nhắc nhở vài lần chụp, cho phép mô hình học hỏi từ các ví dụ. Tính năng này rất quan trọng đối với các nhiệm vụ đòi hỏi sự hiểu biết theo ngữ cảnh hoặc các mẫu cụ thể. Các mẫu lời nhắc vài cảnh quay có thể được xây dựng từ một tập hợp các ví dụ hoặc bằng cách sử dụng đối tượng Bộ chọn mẫu. Đọc thêm ở đây.
Trình phân tích cú pháp đầu ra
Trình phân tích cú pháp đầu ra đóng một vai trò quan trọng trong Langchain, cho phép người dùng cấu trúc các phản hồi do mô hình ngôn ngữ tạo ra. Trong phần này, chúng ta sẽ khám phá khái niệm về trình phân tích cú pháp đầu ra và cung cấp các ví dụ mã bằng cách sử dụng PydanticOutputParser, SimpleJsonOutputParser, CommaSeparatedListOutputParser, DatetimeOutputParser và XMLOutputParser của Langchain.
Trình phân tích cú pháp đầu ra Pydantic
Langchain cung cấp PydanticOutputParser để phân tích cú pháp phản hồi thành cấu trúc dữ liệu Pydantic. Dưới đây là ví dụ từng bước về cách sử dụng nó:
from typing import List
from langchain.llms import OpenAI
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import PromptTemplate
from langchain.pydantic_v1 import BaseModel, Field, validator # Initialize the language model
model = OpenAI(model_name="text-davinci-003", temperature=0.0) # Define your desired data structure using Pydantic
class Joke(BaseModel): setup: str = Field(description="question to set up a joke") punchline: str = Field(description="answer to resolve the joke") @validator("setup") def question_ends_with_question_mark(cls, field): if field[-1] != "?": raise ValueError("Badly formed question!") return field # Set up a PydanticOutputParser
parser = PydanticOutputParser(pydantic_object=Joke) # Create a prompt with format instructions
prompt = PromptTemplate( template="Answer the user query.n{format_instructions}n{query}n", input_variables=["query"], partial_variables={"format_instructions": parser.get_format_instructions()},
) # Define a query to prompt the language model
query = "Tell me a joke." # Combine prompt, model, and parser to get structured output
prompt_and_model = prompt | model
output = prompt_and_model.invoke({"query": query}) # Parse the output using the parser
parsed_result = parser.invoke(output) # The result is a structured object
print(parsed_result)
Đầu ra sẽ là:
SimpleJsonOutputParser
SimpleJsonOutputParser của Langchain được sử dụng khi bạn muốn phân tích các kết quả đầu ra giống JSON. Đây là một ví dụ:
from langchain.output_parsers.json import SimpleJsonOutputParser # Create a JSON prompt
json_prompt = PromptTemplate.from_template( "Return a JSON object with `birthdate` and `birthplace` key that answers the following question: {question}"
) # Initialize the JSON parser
json_parser = SimpleJsonOutputParser() # Create a chain with the prompt, model, and parser
json_chain = json_prompt | model | json_parser # Stream through the results
result_list = list(json_chain.stream({"question": "When and where was Elon Musk born?"})) # The result is a list of JSON-like dictionaries
print(result_list)
Dấu phẩySeparatedListOutputParser
CommaSeparatedListOutputParser rất hữu ích khi bạn muốn trích xuất các danh sách được phân tách bằng dấu phẩy từ các phản hồi của mô hình. Đây là một ví dụ:
from langchain.output_parsers import CommaSeparatedListOutputParser
from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI # Initialize the parser
output_parser = CommaSeparatedListOutputParser() # Create format instructions
format_instructions = output_parser.get_format_instructions() # Create a prompt to request a list
prompt = PromptTemplate( template="List five {subject}.n{format_instructions}", input_variables=["subject"], partial_variables={"format_instructions": format_instructions}
) # Define a query to prompt the model
query = "English Premier League Teams" # Generate the output
output = model(prompt.format(subject=query)) # Parse the output using the parser
parsed_result = output_parser.parse(output) # The result is a list of items
print(parsed_result)
Trình phân tích cú pháp đầu ra ngày giờ
DatetimeOutputParser của Langchain được thiết kế để phân tích thông tin ngày giờ. Đây là cách sử dụng nó:
from langchain.prompts import PromptTemplate
from langchain.output_parsers import DatetimeOutputParser
from langchain.chains import LLMChain
from langchain.llms import OpenAI # Initialize the DatetimeOutputParser
output_parser = DatetimeOutputParser() # Create a prompt with format instructions
template = """
Answer the user's question:
{question}
{format_instructions} """ prompt = PromptTemplate.from_template( template, partial_variables={"format_instructions": output_parser.get_format_instructions()},
) # Create a chain with the prompt and language model
chain = LLMChain(prompt=prompt, llm=OpenAI()) # Define a query to prompt the model
query = "when did Neil Armstrong land on the moon in terms of GMT?" # Run the chain
output = chain.run(query) # Parse the output using the datetime parser
parsed_result = output_parser.parse(output) # The result is a datetime object
print(parsed_result)
Những ví dụ này cho thấy cách sử dụng trình phân tích cú pháp đầu ra của Langchain để cấu trúc các loại phản hồi mô hình khác nhau, làm cho chúng phù hợp với các ứng dụng và định dạng khác nhau. Trình phân tích cú pháp đầu ra là một công cụ có giá trị để nâng cao khả năng sử dụng và khả năng diễn giải của đầu ra mô hình ngôn ngữ trong Langchain.
Tự động hóa các tác vụ và quy trình làm việc thủ công bằng trình tạo quy trình làm việc dựa trên AI của chúng tôi, được Nanonets thiết kế cho bạn và nhóm của bạn.
Mô-đun II: Truy xuất
Việc truy xuất trong LangChain đóng vai trò quan trọng trong các ứng dụng yêu cầu dữ liệu dành riêng cho người dùng, không có trong tập huấn luyện của mô hình. Quá trình này, được gọi là Tạo tăng cường truy xuất (RAG), bao gồm việc tìm nạp dữ liệu bên ngoài và tích hợp nó vào quy trình tạo của mô hình ngôn ngữ. LangChain cung cấp một bộ công cụ và chức năng toàn diện để hỗ trợ quá trình này, phục vụ cho cả ứng dụng đơn giản và phức tạp.
LangChain đạt được khả năng truy xuất thông qua một loạt các thành phần mà chúng ta sẽ thảo luận từng thành phần một.
Bộ nạp tài liệu
Trình tải tài liệu trong LangChain cho phép trích xuất dữ liệu từ nhiều nguồn khác nhau. Với hơn 100 trình tải có sẵn, chúng hỗ trợ nhiều loại tài liệu, ứng dụng và nguồn (nhóm s3 riêng tư, trang web công cộng, cơ sở dữ liệu).
Bạn có thể chọn trình tải tài liệu dựa trên yêu cầu của bạn tại đây.
Tất cả các trình tải này nhập dữ liệu vào Tài liệu các lớp học. Chúng ta sẽ tìm hiểu cách sử dụng dữ liệu được nhập vào các lớp Tài liệu sau.
Trình tải tệp văn bản: Tải một cách đơn giản .txt
tập tin vào một tài liệu.
from langchain.document_loaders import TextLoader loader = TextLoader("./sample.txt")
document = loader.load()
Trình tải CSV: Tải tệp CSV vào tài liệu.
from langchain.document_loaders.csv_loader import CSVLoader loader = CSVLoader(file_path='./example_data/sample.csv')
documents = loader.load()
Chúng ta có thể chọn tùy chỉnh phân tích cú pháp bằng cách chỉ định tên trường -
loader = CSVLoader(file_path='./example_data/mlb_teams_2012.csv', csv_args={ 'delimiter': ',', 'quotechar': '"', 'fieldnames': ['MLB Team', 'Payroll in millions', 'Wins']
})
documents = loader.load()
Trình tải PDF: Trình tải PDF trong LangChain cung cấp nhiều phương pháp khác nhau để phân tích và trích xuất nội dung từ tệp PDF. Mỗi trình tải đáp ứng các yêu cầu khác nhau và sử dụng các thư viện cơ bản khác nhau. Dưới đây là ví dụ chi tiết cho từng bộ nạp.
PyPDFLoader được sử dụng để phân tích cú pháp PDF cơ bản.
from langchain.document_loaders import PyPDFLoader loader = PyPDFLoader("example_data/layout-parser-paper.pdf")
pages = loader.load_and_split()
MathPixLoader lý tưởng để trích xuất nội dung và sơ đồ toán học.
from langchain.document_loaders import MathpixPDFLoader loader = MathpixPDFLoader("example_data/math-content.pdf")
data = loader.load()
PyMuPDFLoader nhanh và bao gồm trích xuất siêu dữ liệu chi tiết.
from langchain.document_loaders import PyMuPDFLoader loader = PyMuPDFLoader("example_data/layout-parser-paper.pdf")
data = loader.load() # Optionally pass additional arguments for PyMuPDF's get_text() call
data = loader.load(option="text")
Trình tải PDFMiner được sử dụng để kiểm soát chi tiết hơn việc trích xuất văn bản.
from langchain.document_loaders import PDFMinerLoader loader = PDFMinerLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
AmazonTextractPDFParser sử dụng AWS Textract cho OCR và các tính năng phân tích cú pháp PDF nâng cao khác.
from langchain.document_loaders import AmazonTextractPDFLoader # Requires AWS account and configuration
loader = AmazonTextractPDFLoader("example_data/complex-layout.pdf")
documents = loader.load()
PDFMinerPDFasHTMLLoader tạo HTML từ PDF để phân tích cú pháp ngữ nghĩa.
from langchain.document_loaders import PDFMinerPDFasHTMLLoader loader = PDFMinerPDFasHTMLLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
PDFPlumberLoader cung cấp siêu dữ liệu chi tiết và hỗ trợ một tài liệu trên mỗi trang.
from langchain.document_loaders import PDFPlumberLoader loader = PDFPlumberLoader("example_data/layout-parser-paper.pdf")
data = loader.load()
Bộ tải tích hợp: LangChain cung cấp nhiều trình tải tùy chỉnh để tải trực tiếp dữ liệu từ ứng dụng của bạn (chẳng hạn như Slack, Sigma, Notion, Confluence, Google Drive, v.v.) cũng như cơ sở dữ liệu và sử dụng chúng trong các ứng dụng LLM.
Danh sách đầy đủ là tại đây.
Dưới đây là một vài ví dụ để minh họa điều này –
Ví dụ I – Slack
Slack, một nền tảng nhắn tin tức thời được sử dụng rộng rãi, có thể được tích hợp vào các ứng dụng và quy trình làm việc LLM.
- Chuyển đến trang Quản lý không gian làm việc Slack của bạn.
- Hướng đến
{your_slack_domain}.slack.com/services/export
. - Chọn phạm vi ngày mong muốn và bắt đầu xuất.
- Slack thông báo qua email và DM khi quá trình xuất đã sẵn sàng.
- Kết quả xuất khẩu mang lại một
.zip
tệp nằm trong thư mục Tải xuống hoặc đường dẫn tải xuống được chỉ định của bạn. - Chỉ định đường dẫn của tệp đã tải xuống
.zip
tập tin đểLOCAL_ZIPFILE
. - Sử dụng
SlackDirectoryLoader
từlangchain.document_loaders
Gói.
from langchain.document_loaders import SlackDirectoryLoader SLACK_WORKSPACE_URL = "https://xxx.slack.com" # Replace with your Slack URL
LOCAL_ZIPFILE = "" # Path to the Slack zip file loader = SlackDirectoryLoader(LOCAL_ZIPFILE, SLACK_WORKSPACE_URL)
docs = loader.load()
print(docs)
Ví dụ II – Figma
Figma, một công cụ phổ biến để thiết kế giao diện, cung cấp API REST để tích hợp dữ liệu.
- Lấy khóa tệp Figma từ định dạng URL:
https://www.figma.com/file/{filekey}/sampleFilename
. - ID nút được tìm thấy trong tham số URL
?node-id={node_id}
. - Tạo mã thông báo truy cập theo hướng dẫn tại Trung tâm trợ giúp Figma.
- Sản phẩm
FigmaFileLoader
lớp học từlangchain.document_loaders.figma
được sử dụng để tải dữ liệu Figma. - Các mô-đun LangChain khác nhau như
CharacterTextSplitter
,ChatOpenAI
, v.v., được sử dụng để xử lý.
import os
from langchain.document_loaders.figma import FigmaFileLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.chat_models import ChatOpenAI
from langchain.indexes import VectorstoreIndexCreator
from langchain.chains import ConversationChain, LLMChain
from langchain.memory import ConversationBufferWindowMemory
from langchain.prompts.chat import ChatPromptTemplate, SystemMessagePromptTemplate, AIMessagePromptTemplate, HumanMessagePromptTemplate figma_loader = FigmaFileLoader( os.environ.get("ACCESS_TOKEN"), os.environ.get("NODE_IDS"), os.environ.get("FILE_KEY"),
) index = VectorstoreIndexCreator().from_loaders([figma_loader])
figma_doc_retriever = index.vectorstore.as_retriever()
- Sản phẩm
generate_code
Hàm sử dụng dữ liệu Figma để tạo mã HTML/CSS. - Nó sử dụng cuộc trò chuyện theo khuôn mẫu với mô hình dựa trên GPT.
def generate_code(human_input): # Template for system and human prompts system_prompt_template = "Your coding instructions..." human_prompt_template = "Code the {text}. Ensure it's mobile responsive" # Creating prompt templates system_message_prompt = SystemMessagePromptTemplate.from_template(system_prompt_template) human_message_prompt = HumanMessagePromptTemplate.from_template(human_prompt_template) # Setting up the AI model gpt_4 = ChatOpenAI(temperature=0.02, model_name="gpt-4") # Retrieving relevant documents relevant_nodes = figma_doc_retriever.get_relevant_documents(human_input) # Generating and formatting the prompt conversation = [system_message_prompt, human_message_prompt] chat_prompt = ChatPromptTemplate.from_messages(conversation) response = gpt_4(chat_prompt.format_prompt(context=relevant_nodes, text=human_input).to_messages()) return response # Example usage
response = generate_code("page top header")
print(response.content)
- Sản phẩm
generate_code
khi được thực thi, hàm sẽ trả về mã HTML/CSS dựa trên đầu vào thiết kế Figma.
Bây giờ chúng ta hãy sử dụng kiến thức của mình để tạo một vài bộ tài liệu.
Trước tiên, chúng tôi tải bản PDF, báo cáo phát triển bền vững hàng năm của BCG.
Chúng tôi sử dụng PyPDFLoader cho việc này.
from langchain.document_loaders import PyPDFLoader loader = PyPDFLoader("bcg-2022-annual-sustainability-report-apr-2023.pdf")
pdfpages = loader.load_and_split()
Chúng tôi sẽ nhập dữ liệu từ Airtable ngay bây giờ. Chúng tôi có Airtable chứa thông tin về các mô hình trích xuất dữ liệu và OCR khác nhau –
Hãy để chúng tôi sử dụng AirtableLoader cho việc này, được tìm thấy trong danh sách các trình tải tích hợp.
from langchain.document_loaders import AirtableLoader api_key = "XXXXX"
base_id = "XXXXX"
table_id = "XXXXX" loader = AirtableLoader(api_key, table_id, base_id)
airtabledocs = loader.load()
Bây giờ chúng ta hãy tiến hành và tìm hiểu cách sử dụng các lớp tài liệu này.
Máy biến áp tài liệu
Bộ chuyển đổi tài liệu trong LangChain là những công cụ thiết yếu được thiết kế để thao tác với các tài liệu mà chúng tôi đã tạo trong tiểu mục trước.
Chúng được sử dụng cho các tác vụ như chia tài liệu dài thành các phần nhỏ hơn, kết hợp và lọc, những công việc này rất quan trọng để điều chỉnh tài liệu cho phù hợp với cửa sổ ngữ cảnh của mô hình hoặc đáp ứng các nhu cầu ứng dụng cụ thể.
Một công cụ như vậy là RecursiveCharacterTextSplitter, một bộ chia văn bản linh hoạt sử dụng danh sách ký tự để phân tách. Nó cho phép các tham số như kích thước khối, chồng chéo và chỉ mục bắt đầu. Đây là một ví dụ về cách nó được sử dụng trong Python:
from langchain.text_splitter import RecursiveCharacterTextSplitter state_of_the_union = "Your long text here..." text_splitter = RecursiveCharacterTextSplitter( chunk_size=100, chunk_overlap=20, length_function=len, add_start_index=True,
) texts = text_splitter.create_documents([state_of_the_union])
print(texts[0])
print(texts[1])
Một công cụ khác là CharacterTextSplitter, giúp phân tách văn bản dựa trên một ký tự được chỉ định và bao gồm các điều khiển về kích thước đoạn và sự chồng chéo:
from langchain.text_splitter import CharacterTextSplitter text_splitter = CharacterTextSplitter( separator="nn", chunk_size=1000, chunk_overlap=200, length_function=len, is_separator_regex=False,
) texts = text_splitter.create_documents([state_of_the_union])
print(texts[0])
HTMLHeaderTextSplitter được thiết kế để phân chia nội dung HTML dựa trên các thẻ tiêu đề, giữ nguyên cấu trúc ngữ nghĩa:
from langchain.text_splitter import HTMLHeaderTextSplitter html_string = "Your HTML content here..."
headers_to_split_on = [("h1", "Header 1"), ("h2", "Header 2")] html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
html_header_splits = html_splitter.split_text(html_string)
print(html_header_splits[0])
Bạn có thể thực hiện thao tác phức tạp hơn bằng cách kết hợp HTMLHeaderTextSplitter với một bộ chia khác, như Pipeline Splitter:
from langchain.text_splitter import HTMLHeaderTextSplitter, RecursiveCharacterTextSplitter url = "https://example.com"
headers_to_split_on = [("h1", "Header 1"), ("h2", "Header 2")]
html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
html_header_splits = html_splitter.split_text_from_url(url) chunk_size = 500
text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size)
splits = text_splitter.split_documents(html_header_splits)
print(splits[0])
LangChain cũng cung cấp các bộ chia cụ thể cho các ngôn ngữ lập trình khác nhau, như Bộ tách mã Python và Bộ tách mã JavaScript:
from langchain.text_splitter import RecursiveCharacterTextSplitter, Language python_code = """
def hello_world(): print("Hello, World!")
hello_world() """ python_splitter = RecursiveCharacterTextSplitter.from_language( language=Language.PYTHON, chunk_size=50
)
python_docs = python_splitter.create_documents([python_code])
print(python_docs[0]) js_code = """
function helloWorld() { console.log("Hello, World!");
}
helloWorld(); """ js_splitter = RecursiveCharacterTextSplitter.from_language( language=Language.JS, chunk_size=60
)
js_docs = js_splitter.create_documents([js_code])
print(js_docs[0])
Để phân tách văn bản dựa trên số lượng mã thông báo, rất hữu ích cho các mô hình ngôn ngữ có giới hạn mã thông báo, TokenTextSplitter được sử dụng:
from langchain.text_splitter import TokenTextSplitter text_splitter = TokenTextSplitter(chunk_size=10)
texts = text_splitter.split_text(state_of_the_union)
print(texts[0])
Cuối cùng, LongContextReorder sắp xếp lại các tài liệu để ngăn chặn tình trạng suy giảm hiệu suất trong các mô hình do ngữ cảnh dài:
from langchain.document_transformers import LongContextReorder reordering = LongContextReorder()
reordered_docs = reordering.transform_documents(docs)
print(reordered_docs[0])
Những công cụ này thể hiện nhiều cách khác nhau để chuyển đổi tài liệu trong LangChain, từ phân tách văn bản đơn giản đến sắp xếp lại phức tạp và phân tách theo ngôn ngữ cụ thể. Để biết thêm các trường hợp sử dụng cụ thể và chuyên sâu, nên tham khảo phần Tài liệu và Tích hợp LangChain.
Trong ví dụ của chúng tôi, trình tải đã tạo các tài liệu được phân đoạn cho chúng tôi và phần này đã được xử lý.
Mô hình nhúng văn bản
Các mô hình nhúng văn bản trong LangChain cung cấp giao diện được tiêu chuẩn hóa cho nhiều nhà cung cấp mô hình nhúng khác nhau như OpenAI, Cohere và Hugging Face. Các mô hình này chuyển đổi văn bản thành biểu diễn vectơ, cho phép thực hiện các hoạt động như tìm kiếm ngữ nghĩa thông qua tính tương tự của văn bản trong không gian vectơ.
Để bắt đầu với mô hình nhúng văn bản, thông thường bạn cần cài đặt các gói cụ thể và thiết lập khóa API. Chúng tôi đã làm điều này cho OpenAI
Trong LangChain, embed_documents
phương pháp được sử dụng để nhúng nhiều văn bản, cung cấp danh sách các biểu diễn vectơ. Ví dụ:
from langchain.embeddings import OpenAIEmbeddings # Initialize the model
embeddings_model = OpenAIEmbeddings() # Embed a list of texts
embeddings = embeddings_model.embed_documents( ["Hi there!", "Oh, hello!", "What's your name?", "My friends call me World", "Hello World!"]
)
print("Number of documents embedded:", len(embeddings))
print("Dimension of each embedding:", len(embeddings[0]))
Để nhúng một văn bản, chẳng hạn như truy vấn tìm kiếm, embed_query
phương pháp được sử dụng. Điều này hữu ích khi so sánh một truy vấn với một tập hợp các phần nhúng tài liệu. Ví dụ:
from langchain.embeddings import OpenAIEmbeddings # Initialize the model
embeddings_model = OpenAIEmbeddings() # Embed a single query
embedded_query = embeddings_model.embed_query("What was the name mentioned in the conversation?")
print("First five dimensions of the embedded query:", embedded_query[:5])
Hiểu những nhúng này là rất quan trọng. Mỗi đoạn văn bản được chuyển đổi thành một vectơ, kích thước của nó phụ thuộc vào mô hình được sử dụng. Chẳng hạn, các mô hình OpenAI thường tạo ra các vectơ 1536 chiều. Những phần nhúng này sau đó được sử dụng để truy xuất thông tin liên quan.
Chức năng nhúng của LangChain không giới hạn ở OpenAI mà được thiết kế để hoạt động với nhiều nhà cung cấp khác nhau. Việc thiết lập và sử dụng có thể hơi khác nhau tùy thuộc vào nhà cung cấp, nhưng khái niệm cốt lõi về việc nhúng văn bản vào không gian vectơ vẫn giống nhau. Để biết cách sử dụng chi tiết, bao gồm các cấu hình nâng cao và tích hợp với các nhà cung cấp mô hình nhúng khác nhau, tài liệu LangChain trong phần Tích hợp là một tài nguyên quý giá.
Cửa hàng véc tơ
Các cửa hàng vectơ trong LangChain hỗ trợ lưu trữ và tìm kiếm hiệu quả các phần nhúng văn bản. LangChain tích hợp với hơn 50 cửa hàng vector, cung cấp giao diện chuẩn hóa để dễ sử dụng.
Ví dụ: Lưu trữ và tìm kiếm các phần nhúng
Sau khi nhúng văn bản, chúng ta có thể lưu trữ chúng trong kho vector như Chroma
và thực hiện tìm kiếm tương tự:
from langchain.vectorstores import Chroma db = Chroma.from_texts(embedded_texts)
similar_texts = db.similarity_search("search query")
Ngoài ra, chúng ta hãy sử dụng kho vectơ FAISS để tạo chỉ mục cho tài liệu của mình.
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS pdfstore = FAISS.from_documents(pdfpages, embedding=OpenAIEmbeddings()) airtablestore = FAISS.from_documents(airtabledocs, embedding=OpenAIEmbeddings())
Truy xuất
Công cụ truy xuất trong LangChain là các giao diện trả về tài liệu để phản hồi một truy vấn phi cấu trúc. Chúng tổng quát hơn các cửa hàng vector, tập trung vào việc truy xuất hơn là lưu trữ. Mặc dù các cửa hàng vectơ có thể được sử dụng làm xương sống của chó tha mồi, nhưng cũng có những loại chó tha mồi khác.
Để thiết lập trình truy xuất Chroma, trước tiên bạn cài đặt nó bằng cách sử dụng pip install chromadb
. Sau đó, bạn tải, phân tách, nhúng và truy xuất tài liệu bằng một loạt lệnh Python. Đây là ví dụ về mã để thiết lập trình truy xuất Chroma:
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma full_text = open("state_of_the_union.txt", "r").read()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
texts = text_splitter.split_text(full_text) embeddings = OpenAIEmbeddings()
db = Chroma.from_texts(texts, embeddings)
retriever = db.as_retriever() retrieved_docs = retriever.invoke("What did the president say about Ketanji Brown Jackson?")
print(retrieved_docs[0].page_content)
MultiQueryRetriever tự động điều chỉnh lời nhắc bằng cách tạo nhiều truy vấn cho một truy vấn đầu vào của người dùng và kết hợp các kết quả. Đây là một ví dụ về cách sử dụng đơn giản của nó:
from langchain.chat_models import ChatOpenAI
from langchain.retrievers.multi_query import MultiQueryRetriever question = "What are the approaches to Task Decomposition?"
llm = ChatOpenAI(temperature=0)
retriever_from_llm = MultiQueryRetriever.from_llm( retriever=db.as_retriever(), llm=llm
) unique_docs = retriever_from_llm.get_relevant_documents(query=question)
print("Number of unique documents:", len(unique_docs))
Nén theo ngữ cảnh trong LangChain nén các tài liệu được truy xuất bằng cách sử dụng ngữ cảnh của truy vấn, đảm bảo chỉ trả về thông tin có liên quan. Điều này liên quan đến việc giảm nội dung và lọc ra các tài liệu ít liên quan hơn. Ví dụ mã sau đây cho thấy cách sử dụng Trình truy xuất nén theo ngữ cảnh:
from langchain.llms import OpenAI
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor llm = OpenAI(temperature=0)
compressor = LLMChainExtractor.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(base_compressor=compressor, base_retriever=retriever) compressed_docs = compression_retriever.get_relevant_documents("What did the president say about Ketanji Jackson Brown")
print(compressed_docs[0].page_content)
EnsembleRetriever kết hợp các thuật toán truy xuất khác nhau để đạt được hiệu suất tốt hơn. Một ví dụ về việc kết hợp BM25 và FAISS Retrievers được hiển thị trong đoạn mã sau:
from langchain.retrievers import BM25Retriever, EnsembleRetriever
from langchain.vectorstores import FAISS bm25_retriever = BM25Retriever.from_texts(doc_list).set_k(2)
faiss_vectorstore = FAISS.from_texts(doc_list, OpenAIEmbeddings())
faiss_retriever = faiss_vectorstore.as_retriever(search_kwargs={"k": 2}) ensemble_retriever = EnsembleRetriever( retrievers=[bm25_retriever, faiss_retriever], weights=[0.5, 0.5]
) docs = ensemble_retriever.get_relevant_documents("apples")
print(docs[0].page_content)
MultiVector Retriever trong LangChain cho phép truy vấn các tài liệu có nhiều vectơ trên mỗi tài liệu, rất hữu ích để nắm bắt các khía cạnh ngữ nghĩa khác nhau trong tài liệu. Các phương pháp tạo nhiều vectơ bao gồm chia thành các phần nhỏ hơn, tóm tắt hoặc tạo các câu hỏi giả định. Để chia tài liệu thành các phần nhỏ hơn, có thể sử dụng mã Python sau:
python
from langchain.retrievers.multi_vector import MultiVectorRetriever
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.storage import InMemoryStore
from langchain.document_loaders from TextLoader
import uuid loaders = [TextLoader("file1.txt"), TextLoader("file2.txt")]
docs = [doc for loader in loaders for doc in loader.load()]
text_splitter = RecursiveCharacterTextSplitter(chunk_size=10000)
docs = text_splitter.split_documents(docs) vectorstore = Chroma(collection_name="full_documents", embedding_function=OpenAIEmbeddings())
store = InMemoryStore()
id_key = "doc_id"
retriever = MultiVectorRetriever(vectorstore=vectorstore, docstore=store, id_key=id_key) doc_ids = [str(uuid.uuid4()) for _ in docs]
child_text_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
sub_docs = [sub_doc for doc in docs for sub_doc in child_text_splitter.split_documents([doc])]
for sub_doc in sub_docs: sub_doc.metadata[id_key] = doc_ids[sub_docs.index(sub_doc)] retriever.vectorstore.add_documents(sub_docs)
retriever.docstore.mset(list(zip(doc_ids, docs)))
Tạo các bản tóm tắt để truy xuất tốt hơn do trình bày nội dung tập trung hơn là một phương pháp khác. Đây là một ví dụ về tạo bản tóm tắt:
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.document import Document chain = (lambda x: x.page_content) | ChatPromptTemplate.from_template("Summarize the following document:nn{doc}") | ChatOpenAI(max_retries=0) | StrOutputParser()
summaries = chain.batch(docs, {"max_concurrency": 5}) summary_docs = [Document(page_content=s, metadata={id_key: doc_ids[i]}) for i, s in enumerate(summaries)]
retriever.vectorstore.add_documents(summary_docs)
retriever.docstore.mset(list(zip(doc_ids, docs)))
Tạo các câu hỏi giả định liên quan đến từng tài liệu bằng LLM là một cách tiếp cận khác. Điều này có thể được thực hiện với đoạn mã sau:
functions = [{"name": "hypothetical_questions", "parameters": {"questions": {"type": "array", "items": {"type": "string"}}}}]
from langchain.output_parsers.openai_functions import JsonKeyOutputFunctionsParser chain = (lambda x: x.page_content) | ChatPromptTemplate.from_template("Generate 3 hypothetical questions:nn{doc}") | ChatOpenAI(max_retries=0).bind(functions=functions, function_call={"name": "hypothetical_questions"}) | JsonKeyOutputFunctionsParser(key_name="questions")
hypothetical_questions = chain.batch(docs, {"max_concurrency": 5}) question_docs = [Document(page_content=q, metadata={id_key: doc_ids[i]}) for i, questions in enumerate(hypothetical_questions) for q in questions]
retriever.vectorstore.add_documents(question_docs)
retriever.docstore.mset(list(zip(doc_ids, docs)))
Công cụ truy xuất tài liệu gốc là một công cụ truy xuất khác giúp cân bằng giữa độ chính xác khi nhúng và khả năng lưu giữ ngữ cảnh bằng cách lưu trữ các đoạn nhỏ và truy xuất các tài liệu gốc lớn hơn của chúng. Việc thực hiện nó như sau:
from langchain.retrievers import ParentDocumentRetriever loaders = [TextLoader("file1.txt"), TextLoader("file2.txt")]
docs = [doc for loader in loaders for doc in loader.load()] child_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
vectorstore = Chroma(collection_name="full_documents", embedding_function=OpenAIEmbeddings())
store = InMemoryStore()
retriever = ParentDocumentRetriever(vectorstore=vectorstore, docstore=store, child_splitter=child_splitter) retriever.add_documents(docs, ids=None) retrieved_docs = retriever.get_relevant_documents("query")
Trình truy xuất tự truy vấn xây dựng các truy vấn có cấu trúc từ đầu vào ngôn ngữ tự nhiên và áp dụng chúng cho VectorStore cơ bản của nó. Việc thực hiện nó được hiển thị trong đoạn mã sau:
from langchain.chat_models from ChatOpenAI
from langchain.chains.query_constructor.base from AttributeInfo
from langchain.retrievers.self_query.base from SelfQueryRetriever metadata_field_info = [AttributeInfo(name="genre", description="...", type="string"), ...]
document_content_description = "Brief summary of a movie"
llm = ChatOpenAI(temperature=0) retriever = SelfQueryRetriever.from_llm(llm, vectorstore, document_content_description, metadata_field_info) retrieved_docs = retriever.invoke("query")
WebResearchRetriever thực hiện nghiên cứu web dựa trên một truy vấn nhất định –
from langchain.retrievers.web_research import WebResearchRetriever # Initialize components
llm = ChatOpenAI(temperature=0)
search = GoogleSearchAPIWrapper()
vectorstore = Chroma(embedding_function=OpenAIEmbeddings()) # Instantiate WebResearchRetriever
web_research_retriever = WebResearchRetriever.from_llm(vectorstore=vectorstore, llm=llm, search=search) # Retrieve documents
docs = web_research_retriever.get_relevant_documents("query")
Đối với các ví dụ của chúng tôi, chúng tôi cũng có thể sử dụng trình truy xuất tiêu chuẩn đã được triển khai như một phần của đối tượng lưu trữ vectơ như sau –
Bây giờ chúng ta có thể truy vấn những người truy vấn. Đầu ra của truy vấn của chúng tôi sẽ là các đối tượng tài liệu có liên quan đến truy vấn. Những điều này cuối cùng sẽ được sử dụng để tạo ra các phản hồi có liên quan trong các phần tiếp theo.
Tự động hóa các tác vụ và quy trình làm việc thủ công bằng trình tạo quy trình làm việc dựa trên AI của chúng tôi, được Nanonets thiết kế cho bạn và nhóm của bạn.
Học phần III: Đại lý
LangChain giới thiệu một khái niệm mạnh mẽ có tên là “Đại lý” đưa ý tưởng về chuỗi lên một tầm cao hoàn toàn mới. Nhân viên tận dụng các mô hình ngôn ngữ để xác định một cách linh hoạt các chuỗi hành động cần thực hiện, khiến chúng trở nên cực kỳ linh hoạt và có khả năng thích ứng. Không giống như các chuỗi truyền thống, nơi các hành động được mã hóa cứng bằng mã, các tác nhân sử dụng các mô hình ngôn ngữ làm công cụ suy luận để quyết định hành động nào sẽ thực hiện và theo thứ tự nào.
Đại lý là thành phần cốt lõi chịu trách nhiệm đưa ra quyết định. Nó khai thác sức mạnh của mô hình ngôn ngữ và lời nhắc để xác định các bước tiếp theo nhằm đạt được mục tiêu cụ thể. Đầu vào của một tác nhân thường bao gồm:
- Công cụ: Mô tả các công cụ có sẵn (sẽ nói thêm về điều này sau).
- Đầu vào của người dùng: Mục tiêu hoặc truy vấn cấp cao từ người dùng.
- Các bước trung gian: Lịch sử của các cặp (hành động, đầu ra dao) được thực thi để đạt được đầu vào hiện tại của người dùng.
Đầu ra của một tác nhân có thể là đầu ra tiếp theo hoạt động thực hiện hành động (Đại lýHành động) hoặc cuối cùng phản ứng để gửi cho người dùng (Đại lýKết thúc). Một hoạt động chỉ định một công cụ và đầu vào cho công cụ đó.
CÔNG CỤ
Công cụ là các giao diện mà một tác nhân có thể sử dụng để tương tác với thế giới. Chúng cho phép các tác nhân thực hiện nhiều tác vụ khác nhau, chẳng hạn như tìm kiếm trên web, chạy lệnh shell hoặc truy cập các API bên ngoài. Trong LangChain, các công cụ rất cần thiết để mở rộng khả năng của các tác nhân và cho phép họ hoàn thành các nhiệm vụ đa dạng.
Để sử dụng các công cụ trong LangChain, bạn có thể tải chúng bằng đoạn mã sau:
from langchain.agents import load_tools tool_names = [...]
tools = load_tools(tool_names)
Một số công cụ có thể yêu cầu Mô hình ngôn ngữ cơ bản (LLM) để khởi tạo. Trong những trường hợp như vậy, bạn cũng có thể vượt qua LLM:
from langchain.agents import load_tools tool_names = [...]
llm = ...
tools = load_tools(tool_names, llm=llm)
Thiết lập này cho phép bạn truy cập nhiều công cụ khác nhau và tích hợp chúng vào quy trình làm việc của đại lý. Danh sách đầy đủ các công cụ có tài liệu sử dụng là tại đây.
Chúng ta hãy xem xét một số ví dụ về Công cụ.
DuckDuckGo
Công cụ DuckDuckGo cho phép bạn thực hiện tìm kiếm trên web bằng công cụ tìm kiếm của nó. Đây là cách sử dụng nó:
from langchain.tools import DuckDuckGoSearchRun
search = DuckDuckGoSearchRun()
search.run("manchester united vs luton town match summary")
Dữ liệuForSeo
Bộ công cụ DataForSeo cho phép bạn lấy kết quả của công cụ tìm kiếm bằng API DataForSeo. Để sử dụng bộ công cụ này, bạn cần thiết lập thông tin xác thực API của mình. Dưới đây là cách định cấu hình thông tin xác thực:
import os os.environ["DATAFORSEO_LOGIN"] = "<your_api_access_username>"
os.environ["DATAFORSEO_PASSWORD"] = "<your_api_access_password>"
Sau khi thông tin đăng nhập của bạn được thiết lập, bạn có thể tạo một DataForSeoAPIWrapper
công cụ để truy cập API:
from langchain.utilities.dataforseo_api_search import DataForSeoAPIWrapper wrapper = DataForSeoAPIWrapper() result = wrapper.run("Weather in Los Angeles")
Sản phẩm DataForSeoAPIWrapper
công cụ lấy kết quả của công cụ tìm kiếm từ nhiều nguồn khác nhau.
Bạn có thể tùy chỉnh loại kết quả và trường được trả về trong phản hồi JSON. Ví dụ: bạn có thể chỉ định loại kết quả, trường và đặt số lượng tối đa cho số lượng kết quả hàng đầu sẽ trả về:
json_wrapper = DataForSeoAPIWrapper( json_result_types=["organic", "knowledge_graph", "answer_box"], json_result_fields=["type", "title", "description", "text"], top_count=3,
) json_result = json_wrapper.results("Bill Gates")
Ví dụ này tùy chỉnh phản hồi JSON bằng cách chỉ định loại kết quả, trường và giới hạn số lượng kết quả.
Bạn cũng có thể chỉ định vị trí và ngôn ngữ cho kết quả tìm kiếm của mình bằng cách chuyển các tham số bổ sung tới trình bao bọc API:
customized_wrapper = DataForSeoAPIWrapper( top_count=10, json_result_types=["organic", "local_pack"], json_result_fields=["title", "description", "type"], params={"location_name": "Germany", "language_code": "en"},
) customized_result = customized_wrapper.results("coffee near me")
Bằng cách cung cấp thông số vị trí và ngôn ngữ, bạn có thể điều chỉnh kết quả tìm kiếm của mình cho phù hợp với các vùng và ngôn ngữ cụ thể.
Bạn có thể linh hoạt chọn công cụ tìm kiếm bạn muốn sử dụng. Chỉ cần chỉ định công cụ tìm kiếm mong muốn:
customized_wrapper = DataForSeoAPIWrapper( top_count=10, json_result_types=["organic", "local_pack"], json_result_fields=["title", "description", "type"], params={"location_name": "Germany", "language_code": "en", "se_name": "bing"},
) customized_result = customized_wrapper.results("coffee near me")
Trong ví dụ này, tìm kiếm được tùy chỉnh để sử dụng Bing làm công cụ tìm kiếm.
Trình bao bọc API cũng cho phép bạn chỉ định loại tìm kiếm bạn muốn thực hiện. Chẳng hạn, bạn có thể thực hiện tìm kiếm bản đồ:
maps_search = DataForSeoAPIWrapper( top_count=10, json_result_fields=["title", "value", "address", "rating", "type"], params={ "location_coordinate": "52.512,13.36,12z", "language_code": "en", "se_type": "maps", },
) maps_search_result = maps_search.results("coffee near me")
Điều này tùy chỉnh tìm kiếm để truy xuất thông tin liên quan đến bản đồ.
Vỏ (bash)
Bộ công cụ Shell cung cấp cho các tác nhân quyền truy cập vào môi trường shell, cho phép chúng thực thi các lệnh shell. Tính năng này rất mạnh mẽ nhưng cần thận trọng khi sử dụng, đặc biệt là trong môi trường hộp cát. Đây là cách bạn có thể sử dụng công cụ Shell:
from langchain.tools import ShellTool shell_tool = ShellTool() result = shell_tool.run({"commands": ["echo 'Hello World!'", "time"]})
Trong ví dụ này, công cụ Shell chạy hai lệnh shell: lặp lại “Xin chào thế giới!” và hiển thị thời gian hiện tại.
Bạn có thể cung cấp công cụ Shell cho tác nhân để thực hiện các tác vụ phức tạp hơn. Dưới đây là ví dụ về tác nhân tìm nạp liên kết từ một trang web bằng công cụ Shell:
from langchain.agents import AgentType, initialize_agent
from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(temperature=0.1) shell_tool.description = shell_tool.description + f"args {shell_tool.args}".replace( "{", "{{"
).replace("}", "}}")
self_ask_with_search = initialize_agent( [shell_tool], llm, agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)
self_ask_with_search.run( "Download the langchain.com webpage and grep for all urls. Return only a sorted list of them. Be sure to use double quotes."
)
Trong trường hợp này, tác nhân sử dụng công cụ Shell để thực thi một chuỗi lệnh nhằm tìm nạp, lọc và sắp xếp URL từ một trang web.
Các ví dụ được cung cấp minh họa một số công cụ có sẵn trong LangChain. Cuối cùng, những công cụ này sẽ mở rộng khả năng của tổng đài viên (được khám phá trong tiểu mục tiếp theo) và trao quyền cho họ thực hiện các nhiệm vụ khác nhau một cách hiệu quả. Tùy thuộc vào yêu cầu của mình, bạn có thể chọn các công cụ và bộ công cụ phù hợp nhất với nhu cầu dự án của mình và tích hợp chúng vào quy trình làm việc của đại lý.
Quay lại Đại lý
Bây giờ hãy chuyển sang các đại lý.
AgentExecutor là môi trường thời gian chạy cho một tác nhân. Nó chịu trách nhiệm gọi tác nhân, thực hiện các hành động mà nó chọn, chuyển các đầu ra hành động trở lại tác nhân và lặp lại quy trình cho đến khi tác nhân kết thúc. Trong mã giả, AgentExecutor có thể trông giống như thế này:
next_action = agent.get_action(...)
while next_action != AgentFinish: observation = run(next_action) next_action = agent.get_action(..., next_action, observation)
return next_action
AgentExecutor xử lý nhiều vấn đề phức tạp khác nhau, chẳng hạn như xử lý các trường hợp trong đó tác nhân chọn một công cụ không tồn tại, xử lý lỗi công cụ, quản lý kết quả đầu ra do tác nhân tạo ra cũng như cung cấp khả năng ghi nhật ký và quan sát ở mọi cấp độ.
Mặc dù lớp AgentExecutor là thời gian chạy tác nhân chính trong LangChain, nhưng vẫn có các thời gian chạy thử nghiệm khác được hỗ trợ, bao gồm:
- Đại lý lập kế hoạch và thực hiện
- bé AGI
- GPT tự động
Để hiểu rõ hơn về khung tác nhân, chúng ta hãy xây dựng một tác nhân cơ bản từ đầu, sau đó chuyển sang khám phá các tác nhân được tạo sẵn.
Trước khi đi sâu vào xây dựng tác nhân, điều cần thiết là phải xem lại một số thuật ngữ và lược đồ chính:
- Tác nhânHành động: Đây là lớp dữ liệu đại diện cho hành động mà tác nhân nên thực hiện. Nó bao gồm một
tool
thuộc tính (tên của công cụ cần gọi) và mộttool_input
thuộc tính (đầu vào cho công cụ đó). - Đại lýFinish: Lớp dữ liệu này cho biết rằng tác nhân đã hoàn thành nhiệm vụ của mình và sẽ trả về phản hồi cho người dùng. Nó thường bao gồm một từ điển các giá trị trả về, thường có một “đầu ra” chính chứa văn bản phản hồi.
- Các bước trung gian: Đây là bản ghi về các hành động của tác nhân trước đó và kết quả đầu ra tương ứng. Chúng rất quan trọng để chuyển ngữ cảnh tới các lần lặp lại trong tương lai của tác nhân.
Trong ví dụ của chúng tôi, chúng tôi sẽ sử dụng Gọi hàm OpenAI để tạo tác nhân của mình. Cách tiếp cận này đáng tin cậy cho việc tạo tác nhân. Chúng ta sẽ bắt đầu bằng cách tạo một công cụ đơn giản để tính toán độ dài của một từ. Công cụ này rất hữu ích vì các mô hình ngôn ngữ đôi khi có thể mắc lỗi do mã hóa khi đếm độ dài từ.
Trước tiên, hãy tải mô hình ngôn ngữ mà chúng tôi sẽ sử dụng để điều khiển tác nhân:
from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
Hãy kiểm tra mô hình bằng phép tính độ dài từ:
llm.invoke("how many letters in the word educa?")
Câu trả lời phải cho biết số lượng chữ cái trong từ “educa”.
Tiếp theo, chúng ta sẽ định nghĩa một hàm Python đơn giản để tính độ dài của một từ:
from langchain.agents import tool @tool
def get_word_length(word: str) -> int: """Returns the length of a word.""" return len(word)
Chúng tôi đã tạo một công cụ có tên get_word_length
lấy một từ làm đầu vào và trả về độ dài của nó.
Bây giờ, hãy tạo lời nhắc cho tác nhân. Lời nhắc sẽ hướng dẫn tác nhân cách suy luận và định dạng đầu ra. Trong trường hợp của chúng tôi, chúng tôi đang sử dụng Gọi hàm OpenAI, yêu cầu hướng dẫn tối thiểu. Chúng tôi sẽ xác định lời nhắc bằng các phần giữ chỗ cho thông tin đầu vào của người dùng và bảng ghi chú tác nhân:
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder prompt = ChatPromptTemplate.from_messages( [ ( "system", "You are a very powerful assistant but not great at calculating word lengths.", ), ("user", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]
)
Bây giờ, làm thế nào để tác nhân biết nó có thể sử dụng công cụ nào? Chúng tôi đang dựa vào các mô hình ngôn ngữ gọi hàm OpenAI, vốn yêu cầu các hàm phải được truyền riêng biệt. Để cung cấp các công cụ của chúng tôi cho tác nhân, chúng tôi sẽ định dạng chúng dưới dạng lệnh gọi hàm OpenAI:
from langchain.tools.render import format_tool_to_openai_function llm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools])
Bây giờ, chúng ta có thể tạo tác nhân bằng cách xác định ánh xạ đầu vào và kết nối các thành phần:
Đây là ngôn ngữ LCEL. Chúng ta sẽ thảo luận chi tiết về vấn đề này sau.
from langchain.agents.format_scratchpad import format_to_openai_function_messages
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai _function_messages( x["intermediate_steps"] ), } | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser()
)
Chúng tôi đã tạo tác nhân của mình, hiểu được đầu vào của người dùng, sử dụng các công cụ có sẵn và định dạng đầu ra. Bây giờ, hãy tương tác với nó:
agent.invoke({"input": "how many letters in the word educa?", "intermediate_steps": []})
Tác nhân phải phản hồi bằng AgentAction, cho biết hành động tiếp theo cần thực hiện.
Chúng ta đã tạo xong tác nhân nhưng bây giờ chúng ta cần viết thời gian chạy cho nó. Thời gian chạy đơn giản nhất là thời gian chạy liên tục gọi tác nhân, thực hiện các hành động và lặp lại cho đến khi tác nhân kết thúc. Đây là một ví dụ:
from langchain.schema.agent import AgentFinish user_input = "how many letters in the word educa?"
intermediate_steps = [] while True: output = agent.invoke( { "input": user_input, "intermediate_steps": intermediate_steps, } ) if isinstance(output, AgentFinish): final_result = output.return_values["output"] break else: print(f"TOOL NAME: {output.tool}") print(f"TOOL INPUT: {output.tool_input}") tool = {"get_word_length": get_word_length}[output.tool] observation = tool.run(output.tool_input) intermediate_steps.append((output, observation)) print(final_result)
Trong vòng lặp này, chúng tôi liên tục gọi tác nhân, thực hiện các hành động và cập nhật các bước trung gian cho đến khi tác nhân kết thúc. Chúng tôi cũng xử lý các tương tác công cụ trong vòng lặp.
Để đơn giản hóa quy trình này, LangChain cung cấp lớp AgentExecutor, lớp này gói gọn việc thực thi tác nhân và cung cấp khả năng xử lý lỗi, dừng sớm, theo dõi và các cải tiến khác. Hãy sử dụng AgentExecutor để tương tác với tác nhân:
from langchain.agents import AgentExecutor agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) agent_executor.invoke({"input": "how many letters in the word educa?"})
AgentExecutor đơn giản hóa quy trình thực thi và cung cấp một cách thuận tiện để tương tác với tác nhân.
Trí nhớ cũng sẽ được thảo luận chi tiết sau.
Tác nhân mà chúng tôi đã tạo cho đến nay không có trạng thái, nghĩa là nó không nhớ các tương tác trước đó. Để kích hoạt các câu hỏi và cuộc trò chuyện tiếp theo, chúng ta cần thêm bộ nhớ cho tác nhân. Điều này bao gồm hai bước:
- Thêm biến bộ nhớ vào lời nhắc để lưu trữ lịch sử trò chuyện.
- Theo dõi lịch sử trò chuyện trong quá trình tương tác.
Hãy bắt đầu bằng cách thêm phần giữ chỗ bộ nhớ vào lời nhắc:
from langchain.prompts import MessagesPlaceholder MEMORY_KEY = "chat_history"
prompt = ChatPromptTemplate.from_messages( [ ( "system", "You are a very powerful assistant but not great at calculating word lengths.", ), MessagesPlaceholder(variable_name=MEMORY_KEY), ("user", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]
)
Bây giờ, hãy tạo danh sách để theo dõi lịch sử trò chuyện:
from langchain.schema.messages import HumanMessage, AIMessage chat_history = []
Trong bước tạo tác nhân, chúng tôi cũng sẽ bao gồm bộ nhớ:
agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai_function_messages( x["intermediate_steps"] ), "chat_history": lambda x: x["chat_history"], } | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser()
)
Bây giờ, khi chạy tác nhân, hãy đảm bảo cập nhật lịch sử trò chuyện:
input1 = "how many letters in the word educa?"
result = agent_executor.invoke({"input": input1, "chat_history": chat_history})
chat_history.extend([ HumanMessage(content=input1), AIMessage(content=result["output"]),
])
agent_executor.invoke({"input": "is that a real word?", "chat_history": chat_history})
Điều này cho phép tổng đài viên duy trì lịch sử cuộc trò chuyện và trả lời các câu hỏi tiếp theo dựa trên các tương tác trước đó.
Chúc mừng! Bạn đã tạo và thực thi thành công tác nhân đầu cuối đầu tiên của mình trong LangChain. Để tìm hiểu sâu hơn về khả năng của LangChain, bạn có thể khám phá:
- Các loại đại lý khác nhau được hỗ trợ.
- Đại lý được xây dựng trước
- Cách làm việc với các công cụ và tích hợp công cụ.
Các loại đại lý
LangChain cung cấp nhiều loại đại lý khác nhau, mỗi loại phù hợp với các trường hợp sử dụng cụ thể. Dưới đây là một số đại lý có sẵn:
- Phản ứng không bắn: Tác nhân này sử dụng khung ReAct để chọn các công cụ chỉ dựa trên mô tả của chúng. Nó yêu cầu mô tả cho từng công cụ và rất linh hoạt.
- ReAct đầu vào có cấu trúc: Tác nhân này xử lý các công cụ đa đầu vào và phù hợp với các tác vụ phức tạp như điều hướng trình duyệt web. Nó sử dụng lược đồ đối số của công cụ cho đầu vào có cấu trúc.
- Chức năng OpenAI: Được thiết kế đặc biệt cho các mẫu được tinh chỉnh để gọi chức năng, tác nhân này tương thích với các mẫu như gpt-3.5-turbo-0613 và gpt-4-0613. Chúng tôi đã sử dụng điều này để tạo tác nhân đầu tiên ở trên.
- Đối thoại: Được thiết kế cho cài đặt đàm thoại, tác nhân này sử dụng ReAct để chọn công cụ và sử dụng bộ nhớ để ghi nhớ các tương tác trước đó.
- Tự hỏi với tìm kiếm: Nhân viên này dựa vào một công cụ duy nhất, “Câu trả lời trung gian”, tìm kiếm câu trả lời thực tế cho các câu hỏi. Nó tương đương với bản tự hỏi ban đầu bằng giấy tìm kiếm.
- Kho tài liệu ReAct: Tác nhân này tương tác với kho lưu trữ tài liệu bằng khung ReAct. Nó yêu cầu các công cụ “Tìm kiếm” và “Tra cứu” và tương tự như ví dụ Wikipedia gốc của bài báo ReAct.
Khám phá các loại đại lý này để tìm loại phù hợp nhất với nhu cầu của bạn trong LangChain. Các tác nhân này cho phép bạn liên kết bộ công cụ bên trong chúng để xử lý các hành động và tạo phản hồi. Tìm hiểu thêm trên cách xây dựng đại lý của riêng bạn bằng các công cụ tại đây.
Đại lý dựng sẵn
Hãy tiếp tục khám phá các tác nhân, tập trung vào các tác nhân dựng sẵn có sẵn trong LangChain.
Gmail
LangChain cung cấp bộ công cụ Gmail cho phép bạn kết nối email LangChain của mình với API Gmail. Để bắt đầu, bạn cần thiết lập thông tin đăng nhập của mình, thông tin này được giải thích trong tài liệu API của Gmail. Một khi bạn đã tải xuống credentials.json
tệp, bạn có thể tiếp tục sử dụng API Gmail. Ngoài ra, bạn sẽ cần cài đặt một số thư viện cần thiết bằng các lệnh sau:
pip install --upgrade google-api-python-client > /dev/null
pip install --upgrade google-auth-oauthlib > /dev/null
pip install --upgrade google-auth-httplib2 > /dev/null
pip install beautifulsoup4 > /dev/null # Optional for parsing HTML messages
Bạn có thể tạo bộ công cụ Gmail như sau:
from langchain.agents.agent_toolkits import GmailToolkit toolkit = GmailToolkit()
Bạn cũng có thể tùy chỉnh xác thực theo nhu cầu của mình. Phía sau, tài nguyên googleapi được tạo bằng các phương pháp sau:
from langchain.tools.gmail.utils import build_resource_service, get_gmail_credentials credentials = get_gmail_credentials( token_file="token.json", scopes=["https://mail.google.com/"], client_secrets_file="credentials.json",
)
api_resource = build_resource_service(credentials=credentials)
toolkit = GmailToolkit(api_resource=api_resource)
Bộ công cụ này cung cấp nhiều công cụ khác nhau có thể được sử dụng trong một tổng đài viên, bao gồm:
GmailCreateDraft
: Tạo email nháp với các trường thông báo được chỉ định.GmailSendMessage
: Gửi tin nhắn email.GmailSearch
: Tìm kiếm tin nhắn email hoặc chủ đề.GmailGetMessage
: Tìm nạp email theo ID tin nhắn.GmailGetThread
: Tìm kiếm tin nhắn email.
Để sử dụng các công cụ này trong một tác nhân, bạn có thể khởi tạo tác nhân như sau:
from langchain.llms import OpenAI
from langchain.agents import initialize_agent, AgentType llm = OpenAI(temperature=0)
agent = initialize_agent( tools=toolkit.get_tools(), llm=llm, agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
)
Dưới đây là một số ví dụ về cách sử dụng các công cụ này:
- Tạo bản nháp Gmail để chỉnh sửa:
agent.run( "Create a gmail draft for me to edit of a letter from the perspective of a sentient parrot " "who is looking to collaborate on some research with her estranged friend, a cat. " "Under no circumstances may you send the message, however."
)
- Tìm kiếm email mới nhất trong bản nháp của bạn:
agent.run("Could you search in my drafts for the latest email?")
Những ví dụ này thể hiện khả năng của bộ công cụ Gmail của LangChain trong một tác nhân, cho phép bạn tương tác với Gmail theo chương trình.
Tác nhân cơ sở dữ liệu SQL
Phần này cung cấp cái nhìn tổng quan về một tác nhân được thiết kế để tương tác với cơ sở dữ liệu SQL, đặc biệt là cơ sở dữ liệu Chinook. Tác nhân này có thể trả lời các câu hỏi chung về cơ sở dữ liệu và khôi phục sau lỗi. Xin lưu ý rằng nó vẫn đang được phát triển và không phải tất cả các câu trả lời đều đúng. Hãy thận trọng khi chạy nó trên dữ liệu nhạy cảm vì nó có thể thực hiện các câu lệnh DML trên cơ sở dữ liệu của bạn.
Để sử dụng tác nhân này, bạn có thể khởi tạo nó như sau:
from langchain.agents import create_sql_agent
from langchain.agents.agent_toolkits import SQLDatabaseToolkit
from langchain.sql_database import SQLDatabase
from langchain.llms.openai import OpenAI
from langchain.agents import AgentExecutor
from langchain.agents.agent_types import AgentType
from langchain.chat_models import ChatOpenAI db = SQLDatabase.from_uri("sqlite:///../../../../../notebooks/Chinook.db")
toolkit = SQLDatabaseToolkit(db=db, llm=OpenAI(temperature=0)) agent_executor = create_sql_agent( llm=OpenAI(temperature=0), toolkit=toolkit, verbose=True, agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
)
Tác nhân này có thể được khởi tạo bằng cách sử dụng ZERO_SHOT_REACT_DESCRIPTION
loại đại lý. Nó được thiết kế để trả lời các câu hỏi và cung cấp mô tả. Ngoài ra, bạn có thể khởi tạo tác nhân bằng cách sử dụng OPENAI_FUNCTIONS
loại tác nhân với mô hình GPT-3.5-turbo của OpenAI mà chúng tôi đã sử dụng trong ứng dụng khách trước đây của mình.
Từ chối trách nhiệm
- Chuỗi truy vấn có thể tạo ra các truy vấn chèn/cập nhật/xóa. Hãy thận trọng và sử dụng lời nhắc tùy chỉnh hoặc tạo người dùng SQL mà không có quyền ghi nếu cần.
- Xin lưu ý rằng việc chạy một số truy vấn nhất định, chẳng hạn như “chạy truy vấn lớn nhất có thể” có thể làm quá tải cơ sở dữ liệu SQL của bạn, đặc biệt nếu nó chứa hàng triệu hàng.
- Cơ sở dữ liệu định hướng kho dữ liệu thường hỗ trợ hạn ngạch ở cấp độ người dùng để hạn chế việc sử dụng tài nguyên.
Bạn có thể yêu cầu nhân viên mô tả một bảng, chẳng hạn như bảng “danh sách phát”. Đây là một ví dụ về cách thực hiện:
agent_executor.run("Describe the playlisttrack table")
Tác nhân sẽ cung cấp thông tin về lược đồ của bảng và các hàng mẫu.
Nếu bạn hỏi nhầm về một bảng không tồn tại, nhân viên có thể khôi phục và cung cấp thông tin về bảng trùng khớp nhất. Ví dụ:
agent_executor.run("Describe the playlistsong table")
Đại lý sẽ tìm bảng phù hợp gần nhất và cung cấp thông tin về nó.
Bạn cũng có thể yêu cầu đại lý chạy truy vấn trên cơ sở dữ liệu. Ví dụ:
agent_executor.run("List the total sales per country. Which country's customers spent the most?")
Đại lý sẽ thực hiện truy vấn và cung cấp kết quả, chẳng hạn như quốc gia có tổng doanh số cao nhất.
Để biết tổng số bản nhạc trong mỗi danh sách phát, bạn có thể sử dụng truy vấn sau:
agent_executor.run("Show the total number of tracks in each playlist. The Playlist name should be included in the result.")
Tác nhân sẽ trả về tên danh sách phát cùng với tổng số bản nhạc tương ứng.
Trong trường hợp tác nhân gặp lỗi, nó có thể khôi phục và đưa ra phản hồi chính xác. Ví dụ:
agent_executor.run("Who are the top 3 best selling artists?")
Ngay cả khi gặp sai sót ban đầu, người đại diện sẽ điều chỉnh và đưa ra câu trả lời chính xác, trong trường hợp này là top 3 nghệ sĩ bán chạy nhất.
Đại lý khung dữ liệu Pandas
Phần này giới thiệu một tác nhân được thiết kế để tương tác với Pandas DataFrames nhằm mục đích trả lời câu hỏi. Xin lưu ý rằng tác nhân này sử dụng tác nhân Python dưới lớp vỏ bọc để thực thi mã Python được tạo bởi mô hình ngôn ngữ (LLM). Hãy thận trọng khi sử dụng tác nhân này để ngăn chặn tác hại tiềm tàng từ mã Python độc hại do LLM tạo ra.
Bạn có thể khởi tạo tác nhân Pandas DataFrame như sau:
from langchain_experimental.agents.agent_toolkits import create_pandas_dataframe_agent
from langchain.chat_models import ChatOpenAI
from langchain.agents.agent_types import AgentType from langchain.llms import OpenAI
import pandas as pd df = pd.read_csv("titanic.csv") # Using ZERO_SHOT_REACT_DESCRIPTION agent type
agent = create_pandas_dataframe_agent(OpenAI(temperature=0), df, verbose=True) # Alternatively, using OPENAI_FUNCTIONS agent type
# agent = create_pandas_dataframe_agent(
# ChatOpenAI(temperature=0, model="gpt-3.5-turbo-0613"),
# df,
# verbose=True,
# agent_type=AgentType.OPENAI_FUNCTIONS,
# )
Bạn có thể yêu cầu tác nhân đếm số hàng trong DataFrame:
agent.run("how many rows are there?")
Tác nhân sẽ thực thi mã df.shape[0]
và đưa ra câu trả lời, chẳng hạn như “Có 891 hàng trong khung dữ liệu”.
Bạn cũng có thể yêu cầu tổng đài viên lọc các hàng dựa trên tiêu chí cụ thể, chẳng hạn như tìm số người có nhiều hơn 3 anh chị em:
agent.run("how many people have more than 3 siblings")
Tác nhân sẽ thực thi mã df[df['SibSp'] > 3].shape[0]
và đưa ra câu trả lời, chẳng hạn như “30 người có nhiều hơn 3 anh chị em”.
Nếu muốn tính căn bậc hai của độ tuổi trung bình, bạn có thể hỏi người đại diện:
agent.run("whats the square root of the average age?")
Đại lý sẽ tính toán độ tuổi trung bình bằng cách sử dụng df['Age'].mean()
và sau đó tính căn bậc hai bằng cách sử dụng math.sqrt()
. Nó sẽ cung cấp câu trả lời, chẳng hạn như “Căn bậc hai của độ tuổi trung bình là 5.449689683556195”.
Hãy tạo một bản sao của DataFrame và các giá trị độ tuổi bị thiếu sẽ được điền vào độ tuổi trung bình:
df1 = df.copy()
df1["Age"] = df1["Age"].fillna(df1["Age"].mean())
Sau đó, bạn có thể khởi tạo tác nhân bằng cả hai DataFrames và đặt câu hỏi cho tác nhân:
agent = create_pandas_dataframe_agent(OpenAI(temperature=0), [df, df1], verbose=True)
agent.run("how many rows in the age column are different?")
Tác nhân sẽ so sánh các cột tuổi trong cả hai DataFrame và đưa ra câu trả lời, chẳng hạn như “177 hàng trong cột tuổi là khác nhau”.
Bộ công cụ Jira
Phần này giải thích cách sử dụng bộ công cụ Jira, cho phép các tác nhân tương tác với một phiên bản Jira. Bạn có thể thực hiện nhiều hành động khác nhau như tìm kiếm sự cố và tạo sự cố bằng bộ công cụ này. Nó sử dụng thư viện atlassian-python-api. Để sử dụng bộ công cụ này, bạn cần đặt các biến môi trường cho phiên bản Jira của mình, bao gồm JIRA_API_TOKEN, JIRA_USERNAME và JIRA_INSTANCE_URL. Ngoài ra, bạn có thể cần đặt khóa API OpenAI làm biến môi trường.
Để bắt đầu, hãy cài đặt thư viện atlassian-python-api và đặt các biến môi trường cần thiết:
%pip install atlassian-python-api import os
from langchain.agents import AgentType
from langchain.agents import initialize_agent
from langchain.agents.agent_toolkits.jira.toolkit import JiraToolkit
from langchain.llms import OpenAI
from langchain.utilities.jira import JiraAPIWrapper os.environ["JIRA_API_TOKEN"] = "abc"
os.environ["JIRA_USERNAME"] = "123"
os.environ["JIRA_INSTANCE_URL"] = "https://jira.atlassian.com"
os.environ["OPENAI_API_KEY"] = "xyz" llm = OpenAI(temperature=0)
jira = JiraAPIWrapper()
toolkit = JiraToolkit.from_jira_api_wrapper(jira)
agent = initialize_agent( toolkit.get_tools(), llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)
Bạn có thể hướng dẫn nhân viên tạo một vấn đề mới trong một dự án cụ thể bằng bản tóm tắt và mô tả:
agent.run("make a new issue in project PW to remind me to make more fried rice")
Nhân viên hỗ trợ sẽ thực hiện các hành động cần thiết để tạo ra vấn đề và đưa ra phản hồi, chẳng hạn như “Một vấn đề mới đã được tạo trong dự án PW với phần tóm tắt 'Làm thêm cơm chiên' và mô tả 'Nhắc nhở làm thêm cơm chiên'."
Điều này cho phép bạn tương tác với phiên bản Jira của mình bằng cách sử dụng hướng dẫn ngôn ngữ tự nhiên và bộ công cụ Jira.
Tự động hóa các tác vụ và quy trình làm việc thủ công bằng trình tạo quy trình làm việc dựa trên AI của chúng tôi, được Nanonets thiết kế cho bạn và nhóm của bạn.
Học phần IV: Dây xích
LangChain là một công cụ được thiết kế để sử dụng Mô hình ngôn ngữ lớn (LLM) trong các ứng dụng phức tạp. Nó cung cấp các khuôn khổ để tạo chuỗi thành phần, bao gồm LLM và các loại thành phần khác. Hai khung chính
- Ngôn ngữ biểu thức LangChain (LCEL)
- Giao diện chuỗi kế thừa
Ngôn ngữ biểu thức LangChain (LCEL) là một cú pháp cho phép cấu thành các chuỗi một cách trực quan. Nó hỗ trợ các tính năng nâng cao như phát trực tuyến, cuộc gọi không đồng bộ, tạo khối, song song hóa, thử lại, dự phòng và theo dõi. Ví dụ: bạn có thể soạn một trình phân tích cú pháp lời nhắc, mô hình và đầu ra trong LCEL như trong mã sau:
from langchain.prompts import ChatPromptTemplate
from langchain.schema import StrOutputParser model = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
prompt = ChatPromptTemplate.from_messages([ ("system", "You're a very knowledgeable historian who provides accurate and eloquent answers to historical questions."), ("human", "{question}")
])
runnable = prompt | model | StrOutputParser() for chunk in runnable.stream({"question": "What are the seven wonders of the world"}): print(chunk, end="", flush=True)
Ngoài ra, LLMChain là một tùy chọn tương tự LCEL để soạn thảo các thành phần. Ví dụ LLMChain như sau:
from langchain.chains import LLMChain chain = LLMChain(llm=model, prompt=prompt, output_parser=StrOutputParser())
chain.run(question="What are the seven wonders of the world")
Các chuỗi trong LangChain cũng có thể có trạng thái bằng cách kết hợp đối tượng Bộ nhớ. Điều này cho phép duy trì dữ liệu qua các cuộc gọi, như trong ví dụ này:
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory conversation = ConversationChain(llm=chat, memory=ConversationBufferMemory())
conversation.run("Answer briefly. What are the first 3 colors of a rainbow?")
conversation.run("And the next 4?")
LangChain cũng hỗ trợ tích hợp với các API gọi hàm của OpenAI, rất hữu ích để thu được các kết quả đầu ra có cấu trúc và thực thi các chức năng trong một chuỗi. Để nhận được kết quả đầu ra có cấu trúc, bạn có thể chỉ định chúng bằng cách sử dụng các lớp Pydantic hoặc JsonSchema, như minh họa bên dưới:
from langchain.pydantic_v1 import BaseModel, Field
from langchain.chains.openai_functions import create_structured_output_runnable
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate class Person(BaseModel): name: str = Field(..., description="The person's name") age: int = Field(..., description="The person's age") fav_food: Optional[str] = Field(None, description="The person's favorite food") llm = ChatOpenAI(model="gpt-4", temperature=0)
prompt = ChatPromptTemplate.from_messages([ # Prompt messages here
]) runnable = create_structured_output_runnable(Person, llm, prompt)
runnable.invoke({"input": "Sally is 13"})
Đối với các kết quả đầu ra có cấu trúc, cũng có sẵn một cách tiếp cận cũ sử dụng LLMChain:
from langchain.chains.openai_functions import create_structured_output_chain class Person(BaseModel): name: str = Field(..., description="The person's name") age: int = Field(..., description="The person's age") chain = create_structured_output_chain(Person, llm, prompt, verbose=True)
chain.run("Sally is 13")
LangChain tận dụng các chức năng OpenAI để tạo ra nhiều chuỗi cụ thể khác nhau cho các mục đích khác nhau. Chúng bao gồm các chuỗi trích xuất, gắn thẻ, OpenAPI và QA kèm theo các trích dẫn.
Trong bối cảnh trích xuất, quy trình này tương tự như chuỗi đầu ra có cấu trúc nhưng tập trung vào việc trích xuất thông tin hoặc thực thể. Để gắn thẻ, ý tưởng là gắn nhãn tài liệu với các lớp như tình cảm, ngôn ngữ, phong cách, chủ đề được đề cập hoặc xu hướng chính trị.
Một ví dụ về cách gắn thẻ hoạt động trong LangChain có thể được minh họa bằng mã Python. Quá trình bắt đầu bằng việc cài đặt các gói cần thiết và thiết lập môi trường:
pip install langchain openai
# Set env var OPENAI_API_KEY or load from a .env file:
# import dotenv
# dotenv.load_dotenv() from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.chains import create_tagging_chain, create_tagging_chain_pydantic
Lược đồ để gắn thẻ được xác định, chỉ định các thuộc tính và loại dự kiến của chúng:
schema = { "properties": { "sentiment": {"type": "string"}, "aggressiveness": {"type": "integer"}, "language": {"type": "string"}, }
} llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo-0613")
chain = create_tagging_chain(schema, llm)
Ví dụ về việc chạy chuỗi gắn thẻ với các đầu vào khác nhau cho thấy khả năng diễn giải cảm xúc, ngôn ngữ và tính hung hăng của mô hình:
inp = "Estoy increiblemente contento de haberte conocido! Creo que seremos muy buenos amigos!"
chain.run(inp)
# {'sentiment': 'positive', 'language': 'Spanish'} inp = "Estoy muy enojado con vos! Te voy a dar tu merecido!"
chain.run(inp)
# {'sentiment': 'enojado', 'aggressiveness': 1, 'language': 'es'}
Để kiểm soát tốt hơn, lược đồ có thể được xác định cụ thể hơn, bao gồm các giá trị, mô tả và thuộc tính bắt buộc có thể có. Một ví dụ về điều khiển nâng cao này được hiển thị bên dưới:
schema = { "properties": { # Schema definitions here }, "required": ["language", "sentiment", "aggressiveness"],
} chain = create_tagging_chain(schema, llm)
Các lược đồ Pydantic cũng có thể được sử dụng để xác định tiêu chí gắn thẻ, cung cấp cách Pythonic để chỉ định các thuộc tính và loại được yêu cầu:
from enum import Enum
from pydantic import BaseModel, Field class Tags(BaseModel): # Class fields here chain = create_tagging_chain_pydantic(Tags, llm)
Ngoài ra, bộ chuyển đổi tài liệu gắn thẻ siêu dữ liệu của LangChain có thể được sử dụng để trích xuất siêu dữ liệu từ Tài liệu LangChain, cung cấp chức năng tương tự cho chuỗi gắn thẻ nhưng được áp dụng cho Tài liệu LangChain.
Trích dẫn các nguồn truy xuất là một tính năng khác của LangChain, sử dụng các hàm OpenAI để trích xuất các trích dẫn từ văn bản. Điều này được thể hiện trong đoạn mã sau:
from langchain.chains import create_citation_fuzzy_match_chain
from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo-0613")
chain = create_citation_fuzzy_match_chain(llm)
# Further code for running the chain and displaying results
Trong LangChain, việc xâu chuỗi trong các ứng dụng Mô hình ngôn ngữ lớn (LLM) thường liên quan đến việc kết hợp mẫu lời nhắc với LLM và tùy chọn trình phân tích cú pháp đầu ra. Cách được khuyến nghị để thực hiện việc này là thông qua Ngôn ngữ biểu thức LangChain (LCEL), mặc dù phương pháp LLMChain cũ cũng được hỗ trợ.
Khi sử dụng LCEL, BasePromptTemplate, BaseLanguageModel và BaseOutputParser đều triển khai giao diện Runnable và có thể dễ dàng kết nối với nhau. Đây là một ví dụ chứng minh điều này:
from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.schema import StrOutputParser prompt = PromptTemplate.from_template( "What is a good name for a company that makes {product}?"
)
runnable = prompt | ChatOpenAI() | StrOutputParser()
runnable.invoke({"product": "colorful socks"})
# Output: 'VibrantSocks'
Định tuyến trong LangChain cho phép tạo các chuỗi không xác định trong đó đầu ra của bước trước sẽ xác định bước tiếp theo. Điều này giúp cấu trúc và duy trì tính nhất quán trong tương tác với LLM. Ví dụ: nếu bạn có hai mẫu được tối ưu hóa cho các loại câu hỏi khác nhau, bạn có thể chọn mẫu dựa trên thông tin đầu vào của người dùng.
Đây là cách bạn có thể đạt được điều này bằng cách sử dụng LCEL với RunnableBranch, được khởi tạo với danh sách các cặp (điều kiện, có thể chạy được) và một có thể chạy được mặc định:
from langchain.chat_models import ChatOpenAI
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnableBranch
# Code for defining physics_prompt and math_prompt general_prompt = PromptTemplate.from_template( "You are a helpful assistant. Answer the question as accurately as you can.nn{input}"
)
prompt_branch = RunnableBranch( (lambda x: x["topic"] == "math", math_prompt), (lambda x: x["topic"] == "physics", physics_prompt), general_prompt,
) # More code for setting up the classifier and final chain
Sau đó, chuỗi cuối cùng được xây dựng bằng cách sử dụng nhiều thành phần khác nhau, chẳng hạn như trình phân loại chủ đề, nhánh nhắc và trình phân tích cú pháp đầu ra, để xác định luồng dựa trên chủ đề của đầu vào:
from operator import itemgetter
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough final_chain = ( RunnablePassthrough.assign(topic=itemgetter("input") | classifier_chain) | prompt_branch | ChatOpenAI() | StrOutputParser()
) final_chain.invoke( { "input": "What is the first prime number greater than 40 such that one plus the prime number is divisible by 3?" }
)
# Output: Detailed answer to the math question
Cách tiếp cận này thể hiện tính linh hoạt và sức mạnh của LangChain trong việc xử lý các truy vấn phức tạp và định tuyến chúng một cách thích hợp dựa trên đầu vào.
Trong lĩnh vực mô hình ngôn ngữ, một phương pháp phổ biến là nối tiếp lệnh gọi ban đầu bằng một loạt lệnh gọi tiếp theo, sử dụng đầu ra của một lệnh gọi làm đầu vào cho lệnh gọi tiếp theo. Cách tiếp cận tuần tự này đặc biệt có lợi khi bạn muốn xây dựng dựa trên thông tin được tạo ra trong các tương tác trước đó. Mặc dù Ngôn ngữ biểu thức LangChain (LCEL) là phương pháp được đề xuất để tạo các chuỗi này, nhưng phương pháp SequentialChain vẫn được ghi lại về khả năng tương thích ngược của nó.
Để minh họa điều này, hãy xem xét một tình huống trong đó trước tiên chúng tôi tạo bản tóm tắt vở kịch và sau đó đánh giá dựa trên bản tóm tắt đó. Sử dụng Python langchain.prompts
, chúng tôi tạo ra hai PromptTemplate
trường hợp: một cho bản tóm tắt và một cho phần đánh giá. Đây là mã để thiết lập các mẫu này:
from langchain.prompts import PromptTemplate synopsis_prompt = PromptTemplate.from_template( "You are a playwright. Given the title of play, it is your job to write a synopsis for that title.nnTitle: {title}nPlaywright: This is a synopsis for the above play:"
) review_prompt = PromptTemplate.from_template( "You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.nnPlay Synopsis:n{synopsis}nReview from a New York Times play critic of the above play:"
)
Theo phương pháp LCEL, chúng tôi xâu chuỗi những lời nhắc này với ChatOpenAI
và StrOutputParser
để tạo một trình tự đầu tiên tạo ra bản tóm tắt và sau đó là phần đánh giá. Đoạn mã như sau:
from langchain.chat_models import ChatOpenAI
from langchain.schema import StrOutputParser llm = ChatOpenAI()
chain = ( {"synopsis": synopsis_prompt | llm | StrOutputParser()} | review_prompt | llm | StrOutputParser()
)
chain.invoke({"title": "Tragedy at sunset on the beach"})
Nếu chúng ta cần cả bản tóm tắt và phần đánh giá, chúng ta có thể sử dụng RunnablePassthrough
để tạo một chuỗi riêng cho từng chuỗi và sau đó kết hợp chúng:
from langchain.schema.runnable import RunnablePassthrough synopsis_chain = synopsis_prompt | llm | StrOutputParser()
review_chain = review_prompt | llm | StrOutputParser()
chain = {"synopsis": synopsis_chain} | RunnablePassthrough.assign(review=review_chain)
chain.invoke({"title": "Tragedy at sunset on the beach"})
Đối với các kịch bản liên quan đến trình tự phức tạp hơn, SequentialChain
phương pháp phát huy tác dụng. Điều này cho phép nhiều đầu vào và đầu ra. Hãy xem xét trường hợp chúng ta cần một bản tóm tắt dựa trên tiêu đề và thời đại của vở kịch. Đây là cách chúng ta có thể thiết lập nó:
from langchain.llms import OpenAI
from langchain.chains import LLMChain, SequentialChain
from langchain.prompts import PromptTemplate llm = OpenAI(temperature=0.7) synopsis_template = "You are a playwright. Given the title of play and the era it is set in, it is your job to write a synopsis for that title.nnTitle: {title}nEra: {era}nPlaywright: This is a synopsis for the above play:"
synopsis_prompt_template = PromptTemplate(input_variables=["title", "era"], template=synopsis_template)
synopsis_chain = LLMChain(llm=llm, prompt=synopsis_prompt_template, output_key="synopsis") review_template = "You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.nnPlay Synopsis:n{synopsis}nReview from a New York Times play critic of the above play:"
prompt_template = PromptTemplate(input_variables=["synopsis"], template=review_template)
review_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="review") overall_chain = SequentialChain( chains=[synopsis_chain, review_chain], input_variables=["era", "title"], output_variables=["synopsis", "review"], verbose=True,
) overall_chain({"title": "Tragedy at sunset on the beach", "era": "Victorian England"})
Trong các trường hợp bạn muốn duy trì bối cảnh trong toàn bộ chuỗi hoặc cho phần sau của chuỗi, SimpleMemory
có thể được sử dụng. Điều này đặc biệt hữu ích để quản lý các mối quan hệ đầu vào/đầu ra phức tạp. Ví dụ: trong trường hợp chúng tôi muốn tạo bài đăng trên mạng xã hội dựa trên tiêu đề, thời đại, tóm tắt và bài đánh giá của một vở kịch, SimpleMemory
có thể giúp quản lý các biến này:
from langchain.memory import SimpleMemory
from langchain.chains import SequentialChain template = "You are a social media manager for a theater company. Given the title of play, the era it is set in, the date, time and location, the synopsis of the play, and the review of the play, it is your job to write a social media post for that play.nnHere is some context about the time and location of the play:nDate and Time: {time}nLocation: {location}nnPlay Synopsis:n{synopsis}nReview from a New York Times play critic of the above play:n{review}nnSocial Media Post:"
prompt_template = PromptTemplate(input_variables=["synopsis", "review", "time", "location"], template=template)
social_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="social_post_text") overall_chain = SequentialChain( memory=SimpleMemory(memories={"time": "December 25th, 8pm PST", "location": "Theater in the Park"}), chains=[synopsis_chain, review_chain, social_chain], input_variables=["era", "title"], output_variables=["social_post_text"], verbose=True,
) overall_chain({"title": "Tragedy at sunset on the beach", "era": "Victorian England"})
Ngoài các chuỗi tuần tự, còn có các chuỗi chuyên dụng để làm việc với tài liệu. Mỗi chuỗi này phục vụ một mục đích khác nhau, từ việc kết hợp các tài liệu đến tinh chỉnh các câu trả lời dựa trên phân tích tài liệu lặp đi lặp lại, đến việc ánh xạ và giảm bớt nội dung tài liệu để tóm tắt hoặc xếp hạng lại dựa trên các câu trả lời được chấm điểm. Các chuỗi này có thể được tạo lại bằng LCEL để tăng thêm tính linh hoạt và tùy chỉnh.
-
StuffDocumentsChain
kết hợp danh sách tài liệu vào một dấu nhắc duy nhất được chuyển tới LLM. -
RefineDocumentsChain
cập nhật câu trả lời lặp đi lặp lại cho từng tài liệu, phù hợp với các tác vụ mà tài liệu vượt quá khả năng ngữ cảnh của mô hình. -
MapReduceDocumentsChain
áp dụng một chuỗi cho từng tài liệu riêng lẻ và sau đó kết hợp các kết quả. -
MapRerankDocumentsChain
chấm điểm từng câu trả lời dựa trên tài liệu và chọn câu trả lời có điểm cao nhất.
Đây là một ví dụ về cách bạn có thể thiết lập một MapReduceDocumentsChain
sử dụng LCEL:
from functools import partial
from langchain.chains.combine_documents import collapse_docs, split_list_of_docs
from langchain.schema import Document, StrOutputParser
from langchain.schema.prompt_template import format_document
from langchain.schema.runnable import RunnableParallel, RunnablePassthrough llm = ChatAnthropic()
document_prompt = PromptTemplate.from_template("{page_content}")
partial_format_document = partial(format_document, prompt=document_prompt) map_chain = ( {"context": partial_format_document} | PromptTemplate.from_template("Summarize this content:nn{context}") | llm | StrOutputParser()
) map_as_doc_chain = ( RunnableParallel({"doc": RunnablePassthrough(), "content": map_chain}) | (lambda x: Document(page_content=x["content"], metadata=x["doc"].metadata))
).with_config(run_name="Summarize (return doc)") def format_docs(docs): return "nn".join(partial_format_document(doc) for doc in docs) collapse_chain = ( {"context": format_docs} | PromptTemplate.from_template("Collapse this content:nn{context}") | llm | StrOutputParser()
) reduce_chain = ( {"context": format_docs} | PromptTemplate.from_template("Combine these summaries:nn{context}") | llm | StrOutputParser()
).with_config(run_name="Reduce") map_reduce = (map_as_doc_chain.map() | collapse | reduce_chain).with_config(run_name="Map reduce")
Cấu hình này cho phép phân tích chi tiết và toàn diện nội dung tài liệu, tận dụng điểm mạnh của LCEL và mô hình ngôn ngữ cơ bản.
Tự động hóa các tác vụ và quy trình làm việc thủ công bằng trình tạo quy trình làm việc dựa trên AI của chúng tôi, được Nanonets thiết kế cho bạn và nhóm của bạn.
Mô-đun V: Bộ nhớ
Trong LangChain, bộ nhớ là một khía cạnh cơ bản của giao diện đàm thoại, cho phép các hệ thống tham chiếu các tương tác trong quá khứ. Điều này đạt được thông qua việc lưu trữ và truy vấn thông tin, với hai hành động chính: đọc và viết. Hệ thống bộ nhớ tương tác với chuỗi hai lần trong quá trình chạy, tăng cường đầu vào của người dùng và lưu trữ đầu vào và đầu ra để tham khảo trong tương lai.
Xây dựng bộ nhớ thành một hệ thống
- Lưu trữ tin nhắn trò chuyện: Mô-đun bộ nhớ LangChain tích hợp nhiều phương pháp khác nhau để lưu trữ tin nhắn trò chuyện, từ danh sách trong bộ nhớ đến cơ sở dữ liệu. Điều này đảm bảo rằng tất cả các tương tác trò chuyện đều được ghi lại để tham khảo trong tương lai.
- Truy vấn tin nhắn trò chuyện: Ngoài việc lưu trữ tin nhắn trò chuyện, LangChain còn sử dụng các cấu trúc dữ liệu và thuật toán để tạo ra chế độ xem hữu ích cho những tin nhắn này. Các hệ thống bộ nhớ đơn giản có thể trả về các tin nhắn gần đây, trong khi các hệ thống tiên tiến hơn có thể tóm tắt các tương tác trong quá khứ hoặc tập trung vào các thực thể được đề cập trong tương tác hiện tại.
Để chứng minh cách sử dụng bộ nhớ trong LangChain, hãy xem xét ConversationBufferMemory
class, một dạng bộ nhớ đơn giản lưu trữ các tin nhắn trò chuyện trong bộ đệm. Đây là một ví dụ:
from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory()
memory.chat_memory.add_user_message("Hello!")
memory.chat_memory.add_ai_message("How can I assist you?")
Khi tích hợp bộ nhớ vào một chuỗi, điều quan trọng là phải hiểu các biến được trả về từ bộ nhớ và cách chúng được sử dụng trong chuỗi. Ví dụ, load_memory_variables
phương pháp giúp căn chỉnh các biến được đọc từ bộ nhớ với mong đợi của chuỗi.
Ví dụ từ đầu đến cuối với LangChain
Cân nhắc sử dụng ConversationBufferMemory
trong một LLMChain
. Chuỗi kết hợp với mẫu lời nhắc thích hợp và bộ nhớ sẽ mang lại trải nghiệm đàm thoại liền mạch. Đây là một ví dụ đơn giản:
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory llm = OpenAI(temperature=0)
template = "Your conversation template here..."
prompt = PromptTemplate.from_template(template)
memory = ConversationBufferMemory(memory_key="chat_history")
conversation = LLMChain(llm=llm, prompt=prompt, memory=memory) response = conversation({"question": "What's the weather like?"})
Ví dụ này minh họa cách hệ thống bộ nhớ của LangChain tích hợp với các chuỗi của nó để mang lại trải nghiệm đàm thoại mạch lạc và nhận biết theo ngữ cảnh.
Các loại bộ nhớ trong Langchain
Langchain cung cấp nhiều loại bộ nhớ khác nhau có thể được sử dụng để tăng cường tương tác với các mô hình AI. Mỗi loại bộ nhớ có các tham số và kiểu trả về riêng, giúp chúng phù hợp với các tình huống khác nhau. Hãy cùng khám phá một số loại bộ nhớ có sẵn trong Langchain cùng với các ví dụ về mã.
1. Bộ nhớ đệm hội thoại
Loại bộ nhớ này cho phép bạn lưu trữ và trích xuất tin nhắn từ các cuộc hội thoại. Bạn có thể trích xuất lịch sử dưới dạng chuỗi hoặc dưới dạng danh sách tin nhắn.
from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory()
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.load_memory_variables({}) # Extract history as a string
{'history': 'Human: hinAI: whats up'} # Extract history as a list of messages
{'history': [HumanMessage(content='hi', additional_kwargs={}), AIMessage(content='whats up', additional_kwargs={})]}
Bạn cũng có thể sử dụng Bộ nhớ đệm hội thoại trong chuỗi để tương tác giống như trò chuyện.
2. Bộ nhớ cửa sổ đệm hội thoại
Loại bộ nhớ này giữ một danh sách các tương tác gần đây và sử dụng K tương tác cuối cùng, ngăn không cho bộ đệm trở nên quá lớn.
from langchain.memory import ConversationBufferWindowMemory memory = ConversationBufferWindowMemory(k=1)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context({"input": "not much you"}, {"output": "not much"})
memory.load_memory_variables({}) {'history': 'Human: not much younAI: not much'}
Giống như Bộ nhớ đệm hội thoại, bạn cũng có thể sử dụng loại bộ nhớ này trong chuỗi cho các tương tác giống như trò chuyện.
3. Bộ nhớ thực thể hội thoại
Loại bộ nhớ này ghi nhớ sự thật về các thực thể cụ thể trong cuộc trò chuyện và trích xuất thông tin bằng LLM.
from langchain.memory import ConversationEntityMemory
from langchain.llms import OpenAI llm = OpenAI(temperature=0)
memory = ConversationEntityMemory(llm=llm)
_input = {"input": "Deven & Sam are working on a hackathon project"}
memory.load_memory_variables(_input)
memory.save_context( _input, {"output": " That sounds like a great project! What kind of project are they working on?"}
)
memory.load_memory_variables({"input": 'who is Sam'}) {'history': 'Human: Deven & Sam are working on a hackathon projectnAI: That sounds like a great project! What kind of project are they working on?', 'entities': {'Sam': 'Sam is working on a hackathon project with Deven.'}}
4. Bộ nhớ sơ đồ tri thức hội thoại
Loại bộ nhớ này sử dụng biểu đồ tri thức để tạo lại bộ nhớ. Bạn có thể trích xuất các thực thể hiện tại và bộ ba kiến thức từ tin nhắn.
from langchain.memory import ConversationKGMemory
from langchain.llms import OpenAI llm = OpenAI(temperature=0)
memory = ConversationKGMemory(llm=llm)
memory.save_context({"input": "say hi to sam"}, {"output": "who is sam"})
memory.save_context({"input": "sam is a friend"}, {"output": "okay"})
memory.load_memory_variables({"input": "who is sam"}) {'history': 'On Sam: Sam is friend.'}
Bạn cũng có thể sử dụng loại bộ nhớ này trong chuỗi để truy xuất kiến thức dựa trên hội thoại.
5. Bộ nhớ tóm tắt cuộc hội thoại
Loại bộ nhớ này tạo ra bản tóm tắt cuộc trò chuyện theo thời gian, hữu ích cho việc cô đọng thông tin từ các cuộc trò chuyện dài hơn.
from langchain.memory import ConversationSummaryMemory
from langchain.llms import OpenAI llm = OpenAI(temperature=0)
memory = ConversationSummaryMemory(llm=llm)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.load_memory_variables({}) {'history': 'nThe human greets the AI, to which the AI responds.'}
6. Bộ nhớ đệm tóm tắt cuộc hội thoại
Loại bộ nhớ này kết hợp bản tóm tắt cuộc trò chuyện và bộ đệm, duy trì sự cân bằng giữa các tương tác gần đây và bản tóm tắt. Nó sử dụng độ dài mã thông báo để xác định thời điểm xóa các tương tác.
from langchain.memory import ConversationSummaryBufferMemory
from langchain.llms import OpenAI llm = OpenAI()
memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=10)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context({"input": "not much you"}, {"output": "not much"})
memory.load_memory_variables({}) {'history': 'System: nThe human says "hi", and the AI responds with "whats up".nHuman: not much younAI: not much'}
Bạn có thể sử dụng các loại bộ nhớ này để nâng cao khả năng tương tác của mình với các mô hình AI trong Langchain. Mỗi loại bộ nhớ phục vụ một mục đích cụ thể và có thể được lựa chọn dựa trên yêu cầu của bạn.
7. Bộ nhớ đệm mã thông báo hội thoại
ConversationTokenBufferMemory là một loại bộ nhớ khác lưu giữ bộ đệm các tương tác gần đây trong bộ nhớ. Không giống như các loại bộ nhớ trước đó tập trung vào số lượng tương tác, loại bộ nhớ này sử dụng độ dài mã thông báo để xác định thời điểm xóa các tương tác.
Sử dụng bộ nhớ với LLM:
from langchain.memory import ConversationTokenBufferMemory
from langchain.llms import OpenAI llm = OpenAI() memory = ConversationTokenBufferMemory(llm=llm, max_token_limit=10)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context({"input": "not much you"}, {"output": "not much"}) memory.load_memory_variables({}) {'history': 'Human: not much younAI: not much'}
Trong ví dụ này, bộ nhớ được đặt để giới hạn các tương tác dựa trên độ dài mã thông báo thay vì số lượng tương tác.
Bạn cũng có thể lấy lịch sử dưới dạng danh sách tin nhắn khi sử dụng loại bộ nhớ này.
memory = ConversationTokenBufferMemory( llm=llm, max_token_limit=10, return_messages=True
)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context({"input": "not much you"}, {"output": "not much"})
Sử dụng trong một chuỗi:
Bạn có thể sử dụng ConversationTokenBufferMemory trong chuỗi để tăng cường tương tác với mô hình AI.
from langchain.chains import ConversationChain conversation_with_summary = ConversationChain( llm=llm, # We set a very low max_token_limit for the purposes of testing. memory=ConversationTokenBufferMemory(llm=OpenAI(), max_token_limit=60), verbose=True,
)
conversation_with_summary.predict(input="Hi, what's up?")
Trong ví dụ này, ConversationTokenBufferMemory được sử dụng trong ConversationChain để quản lý cuộc trò chuyện và giới hạn các tương tác dựa trên độ dài mã thông báo.
8. VectorStoreRetrieverBộ nhớ
VectorStoreRetrieverMemory lưu trữ các ký ức trong kho lưu trữ vectơ và truy vấn các tài liệu “nổi bật” nhất trong top-K mỗi khi nó được gọi. Loại bộ nhớ này không theo dõi rõ ràng thứ tự tương tác nhưng sử dụng truy xuất vectơ để tìm nạp các ký ức liên quan.
from datetime import datetime
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.llms import OpenAI
from langchain.memory import VectorStoreRetrieverMemory
from langchain.chains import ConversationChain
from langchain.prompts import PromptTemplate # Initialize your vector store (specifics depend on the chosen vector store)
import faiss
from langchain.docstore import InMemoryDocstore
from langchain.vectorstores import FAISS embedding_size = 1536 # Dimensions of the OpenAIEmbeddings
index = faiss.IndexFlatL2(embedding_size)
embedding_fn = OpenAIEmbeddings().embed_query
vectorstore = FAISS(embedding_fn, index, InMemoryDocstore({}), {}) # Create your VectorStoreRetrieverMemory
retriever = vectorstore.as_retriever(search_kwargs=dict(k=1))
memory = VectorStoreRetrieverMemory(retriever=retriever) # Save context and relevant information to the memory
memory.save_context({"input": "My favorite food is pizza"}, {"output": "that's good to know"})
memory.save_context({"input": "My favorite sport is soccer"}, {"output": "..."})
memory.save_context({"input": "I don't like the Celtics"}, {"output": "ok"}) # Retrieve relevant information from memory based on a query
print(memory.load_memory_variables({"prompt": "what sport should i watch?"})["history"])
Trong ví dụ này, VectorStoreRetrieverMemory được sử dụng để lưu trữ và truy xuất thông tin liên quan từ một cuộc hội thoại dựa trên truy xuất vectơ.
Bạn cũng có thể sử dụng VectorStoreRetrieverMemory trong một chuỗi để truy xuất kiến thức dựa trên hội thoại, như minh họa trong các ví dụ trước.
Các loại bộ nhớ khác nhau này trong Langchain cung cấp nhiều cách khác nhau để quản lý và truy xuất thông tin từ các cuộc hội thoại, nâng cao khả năng của các mô hình AI trong việc hiểu và phản hồi các truy vấn cũng như bối cảnh của người dùng. Mỗi loại bộ nhớ có thể được chọn dựa trên yêu cầu cụ thể của ứng dụng của bạn.
Bây giờ chúng ta sẽ tìm hiểu cách sử dụng bộ nhớ với LLMChain. Bộ nhớ trong LLMChain cho phép mô hình ghi nhớ các tương tác và bối cảnh trước đó để cung cấp các phản hồi mạch lạc và nhận biết ngữ cảnh hơn.
Để thiết lập bộ nhớ trong LLMChain, bạn cần tạo một lớp bộ nhớ, chẳng hạn như ConversationBufferMemory. Đây là cách bạn có thể thiết lập nó:
from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.memory import ConversationBufferMemory
from langchain.prompts import PromptTemplate template = """You are a chatbot having a conversation with a human. {chat_history}
Human: {human_input}
Chatbot:""" prompt = PromptTemplate( input_variables=["chat_history", "human_input"], template=template
)
memory = ConversationBufferMemory(memory_key="chat_history") llm = OpenAI()
llm_chain = LLMChain( llm=llm, prompt=prompt, verbose=True, memory=memory,
) llm_chain.predict(human_input="Hi there my friend")
Trong ví dụ này, ConversationBufferMemory được sử dụng để lưu trữ lịch sử hội thoại. Các memory_key
tham số chỉ định khóa được sử dụng để lưu trữ lịch sử hội thoại.
Nếu bạn đang sử dụng mô hình trò chuyện thay vì mô hình kiểu hoàn thành, bạn có thể cấu trúc lời nhắc của mình theo cách khác để sử dụng bộ nhớ tốt hơn. Dưới đây là ví dụ về cách thiết lập LLMChain dựa trên mô hình trò chuyện bằng bộ nhớ:
from langchain.chat_models import ChatOpenAI
from langchain.schema import SystemMessage
from langchain.prompts import ( ChatPromptTemplate, HumanMessagePromptTemplate, MessagesPlaceholder,
) # Create a ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages( [ SystemMessage( content="You are a chatbot having a conversation with a human." ), # The persistent system prompt MessagesPlaceholder( variable_name="chat_history" ), # Where the memory will be stored. HumanMessagePromptTemplate.from_template( "{human_input}" ), # Where the human input will be injected ]
) memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True) llm = ChatOpenAI() chat_llm_chain = LLMChain( llm=llm, prompt=prompt, verbose=True, memory=memory,
) chat_llm_chain.predict(human_input="Hi there my friend")
Trong ví dụ này, ChatPromptTemplate được dùng để cấu trúc lời nhắc và ConversationBufferMemory được dùng để lưu trữ và truy xuất lịch sử hội thoại. Cách tiếp cận này đặc biệt hữu ích cho các cuộc trò chuyện kiểu trò chuyện trong đó bối cảnh và lịch sử đóng vai trò quan trọng.
Bộ nhớ cũng có thể được thêm vào chuỗi có nhiều đầu vào, chẳng hạn như chuỗi câu hỏi/trả lời. Dưới đây là ví dụ về cách thiết lập bộ nhớ trong chuỗi câu hỏi/trả lời:
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.embeddings.cohere import CohereEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores.elastic_vector_search import ElasticVectorSearch
from langchain.vectorstores import Chroma
from langchain.docstore.document import Document
from langchain.chains.question_answering import load_qa_chain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
from langchain.memory import ConversationBufferMemory # Split a long document into smaller chunks
with open("../../state_of_the_union.txt") as f: state_of_the_union = f.read()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_text(state_of_the_union) # Create an ElasticVectorSearch instance to index and search the document chunks
embeddings = OpenAIEmbeddings()
docsearch = Chroma.from_texts( texts, embeddings, metadatas=[{"source": i} for i in range(len(texts))]
) # Perform a question about the document
query = "What did the president say about Justice Breyer"
docs = docsearch.similarity_search(query) # Set up a prompt for the question-answering chain with memory
template = """You are a chatbot having a conversation with a human. Given the following extracted parts of a long document and a question, create a final answer. {context} {chat_history}
Human: {human_input}
Chatbot:""" prompt = PromptTemplate( input_variables=["chat_history", "human_input", "context"], template=template
)
memory = ConversationBufferMemory(memory_key="chat_history", input_key="human_input")
chain = load_qa_chain( OpenAI(temperature=0), chain_type="stuff", memory=memory, prompt=prompt
) # Ask the question and retrieve the answer
query = "What did the president say about Justice Breyer"
result = chain({"input_documents": docs, "human_input": query}, return_only_outputs=True) print(result)
print(chain.memory.buffer)
Trong ví dụ này, một câu hỏi được trả lời bằng cách chia tài liệu thành các phần nhỏ hơn. ConversationBufferMemory được sử dụng để lưu trữ và truy xuất lịch sử hội thoại, cho phép mô hình cung cấp các câu trả lời theo ngữ cảnh.
Việc thêm bộ nhớ vào một tác nhân cho phép nó ghi nhớ và sử dụng các tương tác trước đó để trả lời các câu hỏi và cung cấp các phản hồi nhận biết ngữ cảnh. Đây là cách bạn có thể thiết lập bộ nhớ trong một tác nhân:
from langchain.agents import ZeroShotAgent, Tool, AgentExecutor
from langchain.memory import ConversationBufferMemory
from langchain.llms import OpenAI
from langchain.chains import LLMChain
from langchain.utilities import GoogleSearchAPIWrapper # Create a tool for searching
search = GoogleSearchAPIWrapper()
tools = [ Tool( name="Search", func=search.run, description="useful for when you need to answer questions about current events", )
] # Create a prompt with memory
prefix = """Have a conversation with a human, answering the following questions as best you can. You have access to the following tools:"""
suffix = """Begin!" {chat_history}
Question: {input}
{agent_scratchpad}""" prompt = ZeroShotAgent.create_prompt( tools, prefix=prefix, suffix=suffix, input_variables=["input", "chat_history", "agent_scratchpad"],
)
memory = ConversationBufferMemory(memory_key="chat_history") # Create an LLMChain with memory
llm_chain = LLMChain(llm=OpenAI(temperature=0), prompt=prompt)
agent = ZeroShotAgent(llm_chain=llm_chain, tools=tools, verbose=True)
agent_chain = AgentExecutor.from_agent_and_tools( agent=agent, tools=tools, verbose=True, memory=memory
) # Ask a question and retrieve the answer
response = agent_chain.run(input="How many people live in Canada?")
print(response) # Ask a follow-up question
response = agent_chain.run(input="What is their national anthem called?")
print(response)
Trong ví dụ này, bộ nhớ được thêm vào một tổng đài viên, cho phép nó ghi nhớ lịch sử cuộc trò chuyện trước đó và cung cấp các câu trả lời nhận biết ngữ cảnh. Điều này cho phép nhân viên trả lời các câu hỏi tiếp theo một cách chính xác dựa trên thông tin được lưu trữ trong bộ nhớ.
Ngôn ngữ biểu thức LangChain
Trong thế giới xử lý ngôn ngữ tự nhiên và học máy, việc tạo ra các chuỗi hoạt động phức tạp có thể là một nhiệm vụ khó khăn. May mắn thay, Ngôn ngữ biểu thức LangChain (LCEL) đã ra tay giải cứu, cung cấp một cách khai báo và hiệu quả để xây dựng và triển khai các quy trình xử lý ngôn ngữ phức tạp. LCEL được thiết kế để đơn giản hóa quá trình tạo chuỗi, giúp có thể chuyển từ tạo mẫu sang sản xuất một cách dễ dàng. Trong blog này, chúng ta sẽ khám phá LCEL là gì và tại sao bạn có thể muốn sử dụng nó, cùng với các ví dụ mã thực tế để minh họa các khả năng của nó.
LCEL, hay Ngôn ngữ biểu thức LangChain, là một công cụ mạnh mẽ để soạn thảo chuỗi xử lý ngôn ngữ. Nó được xây dựng có mục đích để hỗ trợ quá trình chuyển đổi từ nguyên mẫu sang sản xuất một cách liền mạch mà không yêu cầu thay đổi mã rộng rãi. Cho dù bạn đang xây dựng một chuỗi “prompt + LLM” đơn giản hay một quy trình phức tạp với hàng trăm bước, LCEL đều có thể hỗ trợ bạn.
Dưới đây là một số lý do để sử dụng LCEL trong các dự án xử lý ngôn ngữ của bạn:
- Truyền mã thông báo nhanh: LCEL phân phối mã thông báo từ Mô hình ngôn ngữ đến trình phân tích cú pháp đầu ra trong thời gian thực, cải thiện khả năng phản hồi và hiệu quả.
- API linh hoạt: LCEL hỗ trợ cả API đồng bộ và không đồng bộ để tạo mẫu và sử dụng sản xuất, xử lý nhiều yêu cầu một cách hiệu quả.
- Song song hóa tự động: LCEL tối ưu hóa việc thực thi song song khi có thể, giảm độ trễ ở cả giao diện đồng bộ hóa và không đồng bộ.
- Cấu hình đáng tin cậy: Định cấu hình số lần thử lại và dự phòng để nâng cao độ tin cậy của chuỗi trên quy mô lớn, với sự hỗ trợ phát trực tuyến trong quá trình phát triển.
- Truyền kết quả trung gian: Truy cập các kết quả trung gian trong quá trình xử lý cho mục đích cập nhật hoặc gỡ lỗi của người dùng.
- Tạo lược đồ: LCEL tạo các lược đồ Pydantic và JSONSchema để xác thực đầu vào và đầu ra.
- Theo dõi toàn diện: LangSmith tự động theo dõi tất cả các bước trong chuỗi phức tạp để có thể quan sát và gỡ lỗi.
- Triển khai dễ dàng: Triển khai các chuỗi do LCEL tạo một cách dễ dàng bằng LangServe.
Bây giờ, hãy đi sâu vào các ví dụ mã thực tế chứng minh sức mạnh của LCEL. Chúng ta sẽ khám phá các nhiệm vụ và tình huống phổ biến trong đó LCEL tỏa sáng.
Lời nhắc + LLM
Thành phần cơ bản nhất bao gồm việc kết hợp lời nhắc và mô hình ngôn ngữ để tạo ra một chuỗi lấy dữ liệu đầu vào của người dùng, thêm nó vào lời nhắc, chuyển nó đến một mô hình và trả về đầu ra mô hình thô. Đây là một ví dụ:
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI prompt = ChatPromptTemplate.from_template("tell me a joke about {foo}")
model = ChatOpenAI()
chain = prompt | model result = chain.invoke({"foo": "bears"})
print(result)
Trong ví dụ này, chuỗi tạo ra một trò đùa về gấu.
Bạn có thể đính kèm chuỗi dừng vào chuỗi của mình để kiểm soát cách xử lý văn bản. Ví dụ:
chain = prompt | model.bind(stop=["n"])
result = chain.invoke({"foo": "bears"})
print(result)
Cấu hình này dừng việc tạo văn bản khi gặp ký tự dòng mới.
LCEL hỗ trợ đính kèm thông tin cuộc gọi chức năng vào chuỗi của bạn. Đây là một ví dụ:
functions = [ { "name": "joke", "description": "A joke", "parameters": { "type": "object", "properties": { "setup": {"type": "string", "description": "The setup for the joke"}, "punchline": { "type": "string", "description": "The punchline for the joke", }, }, "required": ["setup", "punchline"], }, }
]
chain = prompt | model.bind(function_call={"name": "joke"}, functions=functions)
result = chain.invoke({"foo": "bears"}, config={})
print(result)
Ví dụ này đính kèm thông tin lệnh gọi hàm để tạo ra một trò đùa.
Lời nhắc + LLM + Trình phân tích đầu ra
Bạn có thể thêm trình phân tích cú pháp đầu ra để chuyển đổi đầu ra của mô hình thô sang định dạng khả thi hơn. Đây là cách bạn có thể làm điều đó:
from langchain.schema.output_parser import StrOutputParser chain = prompt | model | StrOutputParser()
result = chain.invoke({"foo": "bears"})
print(result)
Đầu ra hiện ở định dạng chuỗi, thuận tiện hơn cho các tác vụ tiếp theo.
Khi chỉ định một hàm trả về, bạn có thể phân tích hàm đó trực tiếp bằng LCEL. Ví dụ:
from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser chain = ( prompt | model.bind(function_call={"name": "joke"}, functions=functions) | JsonOutputFunctionsParser()
)
result = chain.invoke({"foo": "bears"})
print(result)
Ví dụ này phân tích cú pháp trực tiếp đầu ra của hàm “joke”.
Đây chỉ là một vài ví dụ về cách LCEL đơn giản hóa các tác vụ xử lý ngôn ngữ phức tạp. Cho dù bạn đang xây dựng chatbot, tạo nội dung hay thực hiện các chuyển đổi văn bản phức tạp, LCEL có thể hợp lý hóa quy trình làm việc của bạn và giúp mã của bạn dễ bảo trì hơn.
RAG (Thế hệ tăng cường truy xuất)
LCEL có thể được sử dụng để tạo chuỗi thế hệ tăng cường truy xuất, kết hợp các bước truy xuất và tạo ngôn ngữ. Đây là một ví dụ:
from operator import itemgetter from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough, RunnableLambda
from langchain.vectorstores import FAISS # Create a vector store and retriever
vectorstore = FAISS.from_texts( ["harrison worked at kensho"], embedding=OpenAIEmbeddings()
)
retriever = vectorstore.as_retriever() # Define templates for prompts
template = """Answer the question based only on the following context:
{context} Question: {question} """
prompt = ChatPromptTemplate.from_template(template) model = ChatOpenAI() # Create a retrieval-augmented generation chain
chain = ( {"context": retriever, "question": RunnablePassthrough()} | prompt | model | StrOutputParser()
) result = chain.invoke("where did harrison work?")
print(result)
Trong ví dụ này, chuỗi lấy thông tin liên quan từ ngữ cảnh và tạo ra câu trả lời cho câu hỏi.
Chuỗi truy xuất hội thoại
Bạn có thể dễ dàng thêm lịch sử hội thoại vào chuỗi của mình. Đây là một ví dụ về chuỗi truy xuất hội thoại:
from langchain.schema.runnable import RunnableMap
from langchain.schema import format_document from langchain.prompts.prompt import PromptTemplate # Define templates for prompts
_template = """Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question, in its original language. Chat History:
{chat_history}
Follow Up Input: {question}
Standalone question:"""
CONDENSE_QUESTION_PROMPT = PromptTemplate.from_template(_template) template = """Answer the question based only on the following context:
{context} Question: {question} """
ANSWER_PROMPT = ChatPromptTemplate.from_template(template) # Define input map and context
_inputs = RunnableMap( standalone_question=RunnablePassthrough.assign( chat_history=lambda x: _format_chat_history(x["chat_history"]) ) | CONDENSE_QUESTION_PROMPT | ChatOpenAI(temperature=0) | StrOutputParser(),
)
_context = { "context": itemgetter("standalone_question") | retriever | _combine_documents, "question": lambda x: x["standalone_question"],
}
conversational_qa_chain = _inputs | _context | ANSWER_PROMPT | ChatOpenAI() result = conversational_qa_chain.invoke( { "question": "where did harrison work?", "chat_history": [], }
)
print(result)
Trong ví dụ này, chuỗi xử lý câu hỏi tiếp theo trong bối cảnh hội thoại.
Với bộ nhớ và tài liệu nguồn trả về
LCEL cũng hỗ trợ bộ nhớ và trả về tài liệu nguồn. Đây là cách bạn có thể sử dụng bộ nhớ trong một chuỗi:
from operator import itemgetter
from langchain.memory import ConversationBufferMemory # Create a memory instance
memory = ConversationBufferMemory( return_messages=True, output_key="answer", input_key="question"
) # Define steps for the chain
loaded_memory = RunnablePassthrough.assign( chat_history=RunnableLambda(memory.load_memory_variables) | itemgetter("history"),
) standalone_question = { "standalone_question": { "question": lambda x: x["question"], "chat_history": lambda x: _format_chat_history(x["chat_history"]), } | CONDENSE_QUESTION_PROMPT | ChatOpenAI(temperature=0) | StrOutputParser(),
} retrieved_documents = { "docs": itemgetter("standalone_question") | retriever, "question": lambda x: x["standalone_question"],
} final_inputs = { "context": lambda x: _combine_documents(x["docs"]), "question": itemgetter("question"),
} answer = { "answer": final_inputs | ANSWER_PROMPT | ChatOpenAI(), "docs": itemgetter("docs"),
} # Create the final chain by combining the steps
final_chain = loaded_memory | standalone_question | retrieved_documents | answer inputs = {"question": "where did harrison work?"}
result = final_chain.invoke(inputs)
print(result)
Trong ví dụ này, bộ nhớ được sử dụng để lưu trữ và truy xuất lịch sử hội thoại cũng như tài liệu nguồn.
Nhiều chuỗi
Bạn có thể xâu chuỗi nhiều chuỗi lại với nhau bằng Runnables. Đây là một ví dụ:
from operator import itemgetter from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import StrOutputParser prompt1 = ChatPromptTemplate.from_template("what is the city {person} is from?")
prompt2 = ChatPromptTemplate.from_template( "what country is the city {city} in? respond in {language}"
) model = ChatOpenAI() chain1 = prompt1 | model | StrOutputParser() chain2 = ( {"city": chain1, "language": itemgetter("language")} | prompt2 | model | StrOutputParser()
) result = chain2.invoke({"person": "obama", "language": "spanish"})
print(result)
Trong ví dụ này, hai chuỗi được kết hợp để tạo ra thông tin về một thành phố và quốc gia của nó bằng một ngôn ngữ cụ thể.
Phân nhánh và Hợp nhất
LCEL cho phép bạn phân tách và hợp nhất các chuỗi bằng RunnableMaps. Đây là một ví dụ về phân nhánh và hợp nhất:
from operator import itemgetter from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import StrOutputParser planner = ( ChatPromptTemplate.from_template("Generate an argument about: {input}") | ChatOpenAI() | StrOutputParser() | {"base_response": RunnablePassthrough()}
) arguments_for = ( ChatPromptTemplate.from_template( "List the pros or positive aspects of {base_response}" ) | ChatOpenAI() | StrOutputParser()
)
arguments_against = ( ChatPromptTemplate.from_template( "List the cons or negative aspects of {base_response}" ) | ChatOpenAI() | StrOutputParser()
) final_responder = ( ChatPromptTemplate.from_messages( [ ("ai", "{original_response}"), ("human", "Pros:n{results_1}nnCons:n{results_2}"), ("system", "Generate a final response given the critique"), ] ) | ChatOpenAI() | StrOutputParser()
) chain = ( planner | { "results_1": arguments_for, "results_2": arguments_against, "original_response": itemgetter("base_response"), } | final_responder
) result = chain.invoke({"input": "scrum"})
print(result)
Trong ví dụ này, chuỗi phân nhánh và hợp nhất được sử dụng để tạo đối số và đánh giá ưu và nhược điểm của nó trước khi tạo phản hồi cuối cùng.
Viết mã Python với LCEL
Một trong những ứng dụng mạnh mẽ của Ngôn ngữ biểu thức LangChain (LCEL) là viết mã Python để giải quyết các vấn đề của người dùng. Dưới đây là ví dụ về cách sử dụng LCEL để viết mã Python:
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain_experimental.utilities import PythonREPL template = """Write some python code to solve the user's problem. Return only python code in Markdown format, e.g.: ```python
....
```"""
prompt = ChatPromptTemplate.from_messages([("system", template), ("human", "{input}")]) model = ChatOpenAI() def _sanitize_output(text: str): _, after = text.split("```python") return after.split("```")[0] chain = prompt | model | StrOutputParser() | _sanitize_output | PythonREPL().run result = chain.invoke({"input": "what's 2 plus 2"})
print(result)
Trong ví dụ này, người dùng cung cấp thông tin đầu vào và LCEL tạo mã Python để giải quyết vấn đề. Sau đó, mã này được thực thi bằng Python REPL và mã Python kết quả được trả về ở định dạng Markdown.
Xin lưu ý rằng việc sử dụng REPL của Python có thể thực thi mã tùy ý, vì vậy hãy thận trọng khi sử dụng nó.
Thêm bộ nhớ vào chuỗi
Bộ nhớ rất cần thiết trong nhiều ứng dụng AI đàm thoại. Đây là cách thêm bộ nhớ vào chuỗi tùy ý:
from operator import itemgetter
from langchain.chat_models import ChatOpenAI
from langchain.memory import ConversationBufferMemory
from langchain.schema.runnable import RunnablePassthrough, RunnableLambda
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder model = ChatOpenAI()
prompt = ChatPromptTemplate.from_messages( [ ("system", "You are a helpful chatbot"), MessagesPlaceholder(variable_name="history"), ("human", "{input}"), ]
) memory = ConversationBufferMemory(return_messages=True) # Initialize memory
memory.load_memory_variables({}) chain = ( RunnablePassthrough.assign( history=RunnableLambda(memory.load_memory_variables) | itemgetter("history") ) | prompt | model
) inputs = {"input": "hi, I'm Bob"}
response = chain.invoke(inputs)
response # Save the conversation in memory
memory.save_context(inputs, {"output": response.content}) # Load memory to see the conversation history
memory.load_memory_variables({})
Trong ví dụ này, bộ nhớ được sử dụng để lưu trữ và truy xuất lịch sử hội thoại, cho phép chatbot duy trì ngữ cảnh và phản hồi phù hợp.
Sử dụng các công cụ bên ngoài với Runnables
LCEL cho phép bạn tích hợp liền mạch các công cụ bên ngoài với Runnables. Dưới đây là ví dụ sử dụng công cụ DuckDuckGo Search:
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.tools import DuckDuckGoSearchRun search = DuckDuckGoSearchRun() template = """Turn the following user input into a search query for a search engine: {input}"""
prompt = ChatPromptTemplate.from_template(template) model = ChatOpenAI() chain = prompt | model | StrOutputParser() | search search_result = chain.invoke({"input": "I'd like to figure out what games are tonight"})
print(search_result)
Trong ví dụ này, LCEL tích hợp công cụ DuckDuckGo Search vào chuỗi, cho phép nó tạo truy vấn tìm kiếm từ dữ liệu đầu vào của người dùng và truy xuất kết quả tìm kiếm.
Tính linh hoạt của LCEL giúp bạn dễ dàng kết hợp nhiều công cụ và dịch vụ bên ngoài khác nhau vào quy trình xử lý ngôn ngữ của mình, nâng cao khả năng và chức năng của chúng.
Thêm kiểm duyệt vào ứng dụng LLM
Để đảm bảo rằng ứng dụng LLM của bạn tuân thủ các chính sách nội dung và bao gồm các biện pháp bảo vệ kiểm duyệt, bạn có thể tích hợp kiểm tra kiểm duyệt vào chuỗi của mình. Dưới đây là cách thêm kiểm duyệt bằng LangChain:
from langchain.chains import OpenAIModerationChain
from langchain.llms import OpenAI
from langchain.prompts import ChatPromptTemplate moderate = OpenAIModerationChain() model = OpenAI()
prompt = ChatPromptTemplate.from_messages([("system", "repeat after me: {input}")]) chain = prompt | model # Original response without moderation
response_without_moderation = chain.invoke({"input": "you are stupid"})
print(response_without_moderation) moderated_chain = chain | moderate # Response after moderation
response_after_moderation = moderated_chain.invoke({"input": "you are stupid"})
print(response_after_moderation)
Trong ví dụ này, OpenAIModerationChain
được sử dụng để thêm kiểm duyệt cho phản hồi do LLM tạo ra. Chuỗi kiểm duyệt kiểm tra phản hồi đối với nội dung vi phạm chính sách nội dung của OpenAI. Nếu phát hiện bất kỳ vi phạm nào, nó sẽ gắn cờ phản hồi tương ứng.
Định tuyến theo sự tương đồng về ngữ nghĩa
LCEL cho phép bạn triển khai logic định tuyến tùy chỉnh dựa trên sự giống nhau về ngữ nghĩa của đầu vào của người dùng. Dưới đây là ví dụ về cách xác định động logic chuỗi dựa trên đầu vào của người dùng:
from langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.prompts import PromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnableLambda, RunnablePassthrough
from langchain.utils.math import cosine_similarity physics_template = """You are a very smart physics professor. You are great at answering questions about physics in a concise and easy to understand manner. When you don't know the answer to a question you admit that you don't know. Here is a question:
{query}""" math_template = """You are a very good mathematician. You are great at answering math questions. You are so good because you are able to break down hard problems into their component parts, answer the component parts, and then put them together to answer the broader question. Here is a question:
{query}""" embeddings = OpenAIEmbeddings()
prompt_templates = [physics_template, math_template]
prompt_embeddings = embeddings.embed_documents(prompt_templates) def prompt_router(input): query_embedding = embeddings.embed_query(input["query"]) similarity = cosine_similarity([query_embedding], prompt_embeddings)[0] most_similar = prompt_templates[similarity.argmax()] print("Using MATH" if most_similar == math_template else "Using PHYSICS") return PromptTemplate.from_template(most_similar) chain = ( {"query": RunnablePassthrough()} | RunnableLambda(prompt_router) | ChatOpenAI() | StrOutputParser()
) print(chain.invoke({"query": "What's a black hole"}))
print(chain.invoke({"query": "What's a path integral"}))
Trong ví dụ này, prompt_router
hàm tính toán độ tương tự cosin giữa thông tin đầu vào của người dùng và các mẫu lời nhắc được xác định trước cho các câu hỏi vật lý và toán học. Dựa trên điểm tương đồng, chuỗi sẽ tự động chọn mẫu lời nhắc phù hợp nhất, đảm bảo chatbot phản hồi phù hợp với câu hỏi của người dùng.
Sử dụng Tác nhân và Runnables
LangChain cho phép bạn tạo tác nhân bằng cách kết hợp Runnables, lời nhắc, mô hình và công cụ. Đây là một ví dụ về việc xây dựng một tác nhân và sử dụng nó:
from langchain.agents import XMLAgent, tool, AgentExecutor
from langchain.chat_models import ChatAnthropic model = ChatAnthropic(model="claude-2") @tool
def search(query: str) -> str: """Search things about current events.""" return "32 degrees" tool_list = [search] # Get prompt to use
prompt = XMLAgent.get_default_prompt() # Logic for going from intermediate steps to a string to pass into the model
def convert_intermediate_steps(intermediate_steps): log = "" for action, observation in intermediate_steps: log += ( f"<tool>{action.tool}</tool><tool_input>{action.tool_input}" f"</tool_input><observation>{observation}</observation>" ) return log # Logic for converting tools to a string to go in the prompt
def convert_tools(tools): return "n".join([f"{tool.name}: {tool.description}" for tool in tools]) agent = ( { "question": lambda x: x["question"], "intermediate_steps": lambda x: convert_intermediate_steps( x["intermediate_steps"] ), } | prompt.partial(tools=convert_tools(tool_list)) | model.bind(stop=["</tool_input>", "</final_answer>"]) | XMLAgent.get_default_output_parser()
) agent_executor = AgentExecutor(agent=agent, tools=tool_list, verbose=True) result = agent_executor.invoke({"question": "What's the weather in New York?"})
print(result)
Trong ví dụ này, tác nhân được tạo bằng cách kết hợp mô hình, công cụ, lời nhắc và logic tùy chỉnh cho các bước trung gian và chuyển đổi công cụ. Tác nhân sau đó được thực thi, cung cấp phản hồi cho truy vấn của người dùng.
Truy vấn cơ sở dữ liệu SQL
Bạn có thể sử dụng LangChain để truy vấn cơ sở dữ liệu SQL và tạo truy vấn SQL dựa trên câu hỏi của người dùng. Đây là một ví dụ:
from langchain.prompts import ChatPromptTemplate template = """Based on the table schema below, write a SQL query that would answer the user's question:
{schema} Question: {question}
SQL Query:"""
prompt = ChatPromptTemplate.from_template(template) from langchain.utilities import SQLDatabase # Initialize the database (you'll need the Chinook sample DB for this example)
db = SQLDatabase.from_uri("sqlite:///./Chinook.db") def get_schema(_): return db.get_table_info() def run_query(query): return db.run(query) from langchain.chat_models import ChatOpenAI
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough model = ChatOpenAI() sql_response = ( RunnablePassthrough.assign(schema=get_schema) | prompt | model.bind(stop=["nSQLResult:"]) | StrOutputParser()
) result = sql_response.invoke({"question": "How many employees are there?"})
print(result) template = """Based on the table schema below, question, SQL query, and SQL response, write a natural language response:
{schema} Question: {question}
SQL Query: {query}
SQL Response: {response}"""
prompt_response = ChatPromptTemplate.from_template(template) full_chain = ( RunnablePassthrough.assign(query=sql_response) | RunnablePassthrough.assign( schema=get_schema, response=lambda x: db.run(x["query"]), ) | prompt_response | model
) response = full_chain.invoke({"question": "How many employees are there?"})
print(response)
Trong ví dụ này, LangChain được sử dụng để tạo các truy vấn SQL dựa trên câu hỏi của người dùng và truy xuất câu trả lời từ cơ sở dữ liệu SQL. Lời nhắc và phản hồi được định dạng để cung cấp các tương tác ngôn ngữ tự nhiên với cơ sở dữ liệu.
Tự động hóa các tác vụ và quy trình làm việc thủ công bằng trình tạo quy trình làm việc dựa trên AI của chúng tôi, được Nanonets thiết kế cho bạn và nhóm của bạn.
LangServe & LangSmith
LangServe giúp các nhà phát triển triển khai các chuỗi và chuỗi chạy LangChain dưới dạng API REST. Thư viện này được tích hợp với FastAPI và sử dụng pydantic để xác thực dữ liệu. Ngoài ra, nó còn cung cấp một ứng dụng khách có thể được sử dụng để gọi các runnable được triển khai trên máy chủ và ứng dụng khách JavaScript có sẵn trong LangChainJS.
Tính năng
- Các lược đồ đầu vào và đầu ra được tự động suy ra từ đối tượng LangChain của bạn và được thực thi trên mọi lệnh gọi API, kèm theo nhiều thông báo lỗi.
- Trang tài liệu API có JSONSchema và Swagger có sẵn.
- Các điểm cuối /gọi, /batch và /stream hiệu quả với sự hỗ trợ cho nhiều yêu cầu đồng thời trên một máy chủ.
- /stream_log điểm cuối để truyền trực tuyến tất cả (hoặc một số) bước trung gian từ chuỗi/đại lý của bạn.
- Trang sân chơi tại /playground với đầu ra phát trực tuyến và các bước trung gian.
- Tích hợp sẵn (tùy chọn) truy tìm LangSmith; chỉ cần thêm khóa API của bạn (xem Hướng dẫn).
- Tất cả đều được xây dựng bằng các thư viện Python nguồn mở đã được thử nghiệm trong trận chiến như FastAPI, Pydantic, uvloop và asyncio.
Hạn chế
- Lệnh gọi lại máy khách chưa được hỗ trợ cho các sự kiện bắt nguồn trên máy chủ.
- Tài liệu OpenAPI sẽ không được tạo khi sử dụng Pydantic V2. FastAPI không hỗ trợ trộn các không gian tên pydantic v1 và v2. Xem phần dưới đây để biết thêm chi tiết.
Sử dụng LangChain CLI để khởi động dự án LangServe một cách nhanh chóng. Để sử dụng langchain CLI, hãy đảm bảo rằng bạn đã cài đặt phiên bản langchain-cli gần đây. Bạn có thể cài đặt nó bằng pip install -U langchain-cli.
langchain app new ../path/to/directory
Bắt đầu phiên bản LangServe của bạn một cách nhanh chóng với Mẫu LangChain. Để biết thêm ví dụ, hãy xem chỉ mục mẫu hoặc thư mục ví dụ.
Đây là máy chủ triển khai mô hình trò chuyện OpenAI, mô hình trò chuyện Anthropic và chuỗi sử dụng mô hình Anthropic để kể chuyện cười về một chủ đề.
#!/usr/bin/env python
from fastapi import FastAPI
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatAnthropic, ChatOpenAI
from langserve import add_routes app = FastAPI( title="LangChain Server", version="1.0", description="A simple api server using Langchain's Runnable interfaces",
) add_routes( app, ChatOpenAI(), path="/openai",
) add_routes( app, ChatAnthropic(), path="/anthropic",
) model = ChatAnthropic()
prompt = ChatPromptTemplate.from_template("tell me a joke about {topic}")
add_routes( app, prompt | model, path="/chain",
) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="localhost", port=8000)
Sau khi triển khai máy chủ ở trên, bạn có thể xem tài liệu OpenAPI được tạo bằng cách sử dụng:
curl localhost:8000/docs
Đảm bảo thêm hậu tố /docs.
from langchain.schema import SystemMessage, HumanMessage
from langchain.prompts import ChatPromptTemplate
from langchain.schema.runnable import RunnableMap
from langserve import RemoteRunnable openai = RemoteRunnable("http://localhost:8000/openai/")
anthropic = RemoteRunnable("http://localhost:8000/anthropic/")
joke_chain = RemoteRunnable("http://localhost:8000/chain/") joke_chain.invoke({"topic": "parrots"}) # or async
await joke_chain.ainvoke({"topic": "parrots"}) prompt = [ SystemMessage(content='Act like either a cat or a parrot.'), HumanMessage(content='Hello!')
] # Supports astream
async for msg in anthropic.astream(prompt): print(msg, end="", flush=True) prompt = ChatPromptTemplate.from_messages( [("system", "Tell me a long story about {topic}")]
) # Can define custom chains
chain = prompt | RunnableMap({ "openai": openai, "anthropic": anthropic,
}) chain.batch([{ "topic": "parrots" }, { "topic": "cats" }])
Trong TypeScript (yêu cầu LangChain.js phiên bản 0.0.166 trở lên):
import { RemoteRunnable } from "langchain/runnables/remote"; const chain = new RemoteRunnable({ url: `http://localhost:8000/chain/invoke/`,
});
const result = await chain.invoke({ topic: "cats",
});
Python sử dụng các yêu cầu:
import requests
response = requests.post( "http://localhost:8000/chain/invoke/", json={'input': {'topic': 'cats'}}
)
response.json()
Bạn cũng có thể sử dụng cuộn tròn:
curl --location --request POST 'http://localhost:8000/chain/invoke/' --header 'Content-Type: application/json' --data-raw '{ "input": { "topic": "cats" } }'
Đoạn mã sau:
...
add_routes( app, runnable, path="/my_runnable",
)
thêm các điểm cuối này vào máy chủ:
- POST /my_runnable/invoke – gọi runnable trên một đầu vào
- POST /my_runnable/batch – gọi runnable trên một loạt dữ liệu đầu vào
- POST /my_runnable/stream – gọi trên một đầu vào và truyền phát đầu ra
- POST /my_runnable/stream_log – gọi trên một đầu vào duy nhất và truyền phát đầu ra, bao gồm đầu ra của các bước trung gian khi nó được tạo
- GET /my_runnable/input_schema – lược đồ json để nhập vào runnable
- GET /my_runnable/output_schema – lược đồ json cho đầu ra của runnable
- GET /my_runnable/config_schema – lược đồ json cho cấu hình của runnable
Bạn có thể tìm thấy trang sân chơi cho trò chơi có thể chạy của mình tại /my_runnable/playground. Điều này hiển thị một giao diện người dùng đơn giản để định cấu hình và gọi khả năng chạy của bạn với đầu ra phát trực tuyến và các bước trung gian.
Đối với cả máy khách và máy chủ:
pip install "langserve[all]"
hoặc pip install “langserve[client]” cho mã máy khách và pip install “langserve[server]” cho mã máy chủ.
Nếu bạn cần thêm xác thực vào máy chủ của mình, vui lòng tham khảo tài liệu bảo mật và tài liệu phần mềm trung gian của FastAPI.
Bạn có thể triển khai lên GCP Cloud Run bằng lệnh sau:
gcloud run deploy [your-service-name] --source . --port 8001 --allow-unauthenticated --region us-central1 --set-env-vars=OPENAI_API_KEY=your_key
LangServe cung cấp hỗ trợ cho Pydantic 2 với một số hạn chế. Tài liệu OpenAPI sẽ không được tạo cho lệnh gọi/batch/stream/stream_log khi sử dụng Pydantic V2. API nhanh không hỗ trợ trộn các không gian tên pydantic v1 và v2. LangChain sử dụng không gian tên v1 trong Pydantic v2. Vui lòng đọc các hướng dẫn sau để đảm bảo khả năng tương thích với LangChain. Ngoại trừ những hạn chế này, chúng tôi hy vọng các điểm cuối API, sân chơi và mọi tính năng khác sẽ hoạt động như mong đợi.
Các ứng dụng LLM thường xử lý các tập tin. Có nhiều kiến trúc khác nhau có thể được tạo ra để thực hiện xử lý tệp; ở một cấp độ cao:
- Tệp có thể được tải lên máy chủ thông qua điểm cuối chuyên dụng và được xử lý bằng điểm cuối riêng.
- Tệp có thể được tải lên theo giá trị (byte tệp) hoặc tham chiếu (ví dụ: url s3 tới nội dung tệp).
- Điểm cuối xử lý có thể bị chặn hoặc không chặn.
- Nếu cần xử lý đáng kể, quá trình xử lý có thể được chuyển sang nhóm quy trình chuyên dụng.
Bạn nên xác định đâu là kiến trúc phù hợp cho ứng dụng của mình. Hiện tại, để tải tệp theo giá trị lên tệp có thể chạy được, hãy sử dụng mã hóa base64 cho tệp (nhiều phần/dữ liệu biểu mẫu chưa được hỗ trợ).
Đây là một ví dụ hướng dẫn cách sử dụng mã hóa base64 để gửi tệp đến một thiết bị có thể chạy được từ xa. Hãy nhớ rằng, bạn luôn có thể tải tệp lên theo tham chiếu (ví dụ: url s3) hoặc tải chúng dưới dạng nhiều phần/dữ liệu biểu mẫu lên điểm cuối chuyên dụng.
Các loại đầu vào và đầu ra được xác định trên tất cả các runnable. Bạn có thể truy cập chúng thông qua các thuộc tính input_schema và out_schema. LangServe sử dụng các loại này để xác nhận và ghi tài liệu. Nếu bạn muốn ghi đè các loại được suy luận mặc định, bạn có thể sử dụng phương thức with_types.
Đây là một ví dụ đồ chơi để minh họa ý tưởng:
from typing import Any
from fastapi import FastAPI
from langchain.schema.runnable import RunnableLambda app = FastAPI() def func(x: Any) -> int: """Mistyped function that should accept an int but accepts anything.""" return x + 1 runnable = RunnableLambda(func).with_types( input_schema=int,
) add_routes(app, runnable)
Kế thừa từ CustomUserType nếu bạn muốn dữ liệu được giải tuần tự hóa thành mô hình pydantic thay vì biểu diễn chính tả tương đương. Hiện tại, loại này chỉ hoạt động ở phía máy chủ và được sử dụng để chỉ định hành vi giải mã mong muốn. Nếu kế thừa từ loại này, máy chủ sẽ giữ loại được giải mã dưới dạng mô hình pydantic thay vì chuyển đổi thành dict.
from fastapi import FastAPI
from langchain.schema.runnable import RunnableLambda
from langserve import add_routes
from langserve.schema import CustomUserType app = FastAPI() class Foo(CustomUserType): bar: int def func(foo: Foo) -> int: """Sample function that expects a Foo type which is a pydantic model""" assert isinstance(foo, Foo) return foo.bar add_routes(app, RunnableLambda(func), path="/foo")
Sân chơi cho phép bạn xác định các tiện ích tùy chỉnh cho khả năng chạy của bạn từ phần phụ trợ. Tiện ích được chỉ định ở cấp trường và được gửi dưới dạng một phần của lược đồ JSON của loại đầu vào. Một tiện ích phải chứa một khóa được gọi là loại với giá trị là một trong danh sách các tiện ích phổ biến. Các khóa tiện ích khác sẽ được liên kết với các giá trị mô tả đường dẫn trong đối tượng JSON.
Lược đồ chung:
type JsonPath = number | string | (number | string)[];
type NameSpacedPath = { title: string; path: JsonPath }; // Using title to mimic json schema, but can use namespace
type OneOfPath = { oneOf: JsonPath[] }; type Widget = { type: string // Some well-known type (e.g., base64file, chat, etc.) [key: string]: JsonPath | NameSpacedPath | OneOfPath;
};
Cho phép tạo đầu vào tải tệp lên trong sân chơi giao diện người dùng cho các tệp được tải lên dưới dạng chuỗi được mã hóa base64. Đây là ví dụ đầy đủ.
try: from pydantic.v1 import Field
except ImportError: from pydantic import Field from langserve import CustomUserType # ATTENTION: Inherit from CustomUserType instead of BaseModel otherwise
# the server will decode it into a dict instead of a pydantic model.
class FileProcessingRequest(CustomUserType): """Request including a base64 encoded file.""" # The extra field is used to specify a widget for the playground UI. file: str = Field(..., extra={"widget": {"type": "base64file"}}) num_chars: int = 100
Tự động hóa các tác vụ và quy trình làm việc thủ công bằng trình tạo quy trình làm việc dựa trên AI của chúng tôi, được Nanonets thiết kế cho bạn và nhóm của bạn.
Giới thiệu về LangSmith
LangChain giúp dễ dàng tạo nguyên mẫu cho các ứng dụng và Đại lý LLM. Tuy nhiên, việc đưa các ứng dụng LLM vào sản xuất có thể rất khó khăn. Bạn có thể sẽ phải tùy chỉnh và lặp lại rất nhiều lời nhắc, chuỗi và các thành phần khác để tạo ra sản phẩm chất lượng cao.
Để hỗ trợ quá trình này, LangSmith đã được giới thiệu, một nền tảng hợp nhất để gỡ lỗi, kiểm tra và giám sát các ứng dụng LLM của bạn.
Khi nào điều này có thể có ích? Bạn có thể thấy nó hữu ích khi muốn gỡ lỗi nhanh chóng một chuỗi, tác nhân hoặc bộ công cụ mới, trực quan hóa cách các thành phần (chuỗi, llms, công cụ truy xuất, v.v.) liên quan và được sử dụng, đánh giá các lời nhắc và LLM khác nhau cho một thành phần duy nhất, chạy một chuỗi nhất định nhiều lần trên một tập dữ liệu để đảm bảo chuỗi đó luôn đáp ứng tiêu chuẩn chất lượng hoặc ghi lại dấu vết sử dụng và sử dụng LLM hoặc quy trình phân tích để tạo ra thông tin chi tiết.
Điều kiện tiên quyết:
- Tạo tài khoản LangSmith và tạo khóa API (xem góc dưới bên trái).
- Làm quen với nền tảng này bằng cách xem qua tài liệu.
Bây giờ, hãy bắt đâù!
Trước tiên, hãy định cấu hình các biến môi trường của bạn để yêu cầu LangChain ghi lại dấu vết. Điều này được thực hiện bằng cách đặt biến môi trường LANGCHAIN_TRACING_V2 thành true. Bạn có thể cho LangChain biết cần đăng nhập vào dự án nào bằng cách đặt biến môi trường LANGCHAIN_PROJECT (nếu không đặt biến này, các lần chạy sẽ được ghi vào dự án mặc định). Điều này sẽ tự động tạo dự án cho bạn nếu nó không tồn tại. Bạn cũng phải đặt các biến môi trường LANGCHAIN_ENDPOINT và LANGCHAIN_API_KEY.
LƯU Ý: Bạn cũng có thể sử dụng trình quản lý bối cảnh trong python để ghi lại dấu vết bằng cách sử dụng:
from langchain.callbacks.manager import tracing_v2_enabled with tracing_v2_enabled(project_name="My Project"): agent.run("How many people live in canada as of 2023?")
Tuy nhiên, trong ví dụ này, chúng tôi sẽ sử dụng các biến môi trường.
%pip install openai tiktoken pandas duckduckgo-search --quiet import os
from uuid import uuid4 unique_id = uuid4().hex[0:8]
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_PROJECT"] = f"Tracing Walkthrough - {unique_id}"
os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"
os.environ["LANGCHAIN_API_KEY"] = "<YOUR-API-KEY>" # Update to your API key # Used by the agent in this tutorial
os.environ["OPENAI_API_KEY"] = "<YOUR-OPENAI-API-KEY>"
Tạo ứng dụng khách LangSmith để tương tác với API:
from langsmith import Client client = Client()
Tạo thành phần LangChain và nhật ký chạy trên nền tảng. Trong ví dụ này, chúng tôi sẽ tạo một tác nhân kiểu ReAct có quyền truy cập vào công cụ tìm kiếm chung (DuckDuckGo). Lời nhắc của đại lý có thể được xem trong Hub tại đây:
from langchain import hub
from langchain.agents import AgentExecutor
from langchain.agents.format_scratchpad import format_to_openai_function_messages
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser
from langchain.chat_models import ChatOpenAI
from langchain.tools import DuckDuckGoSearchResults
from langchain.tools.render import format_tool_to_openai_function # Fetches the latest version of this prompt
prompt = hub.pull("wfh/langsmith-agent-prompt:latest") llm = ChatOpenAI( model="gpt-3.5-turbo-16k", temperature=0,
) tools = [ DuckDuckGoSearchResults( name="duck_duck_go" ), # General internet search using DuckDuckGo
] llm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools]) runnable_agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai_function_messages( x["intermediate_steps"] ), } | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser()
) agent_executor = AgentExecutor( agent=runnable_agent, tools=tools, handle_parsing_errors=True
)
Chúng tôi đang chạy tác nhân đồng thời trên nhiều đầu vào để giảm độ trễ. Các lần chạy được ghi vào LangSmith ở chế độ nền nên độ trễ thực thi không bị ảnh hưởng:
inputs = [ "What is LangChain?", "What's LangSmith?", "When was Llama-v2 released?", "What is the langsmith cookbook?", "When did langchain first announce the hub?",
] results = agent_executor.batch([{"input": x} for x in inputs], return_exceptions=True) results[:2]
Giả sử bạn đã thiết lập thành công môi trường của mình, dấu vết tác nhân của bạn sẽ hiển thị trong phần Dự án trong ứng dụng. Chúc mừng!
Tuy nhiên, có vẻ như nhân viên hỗ trợ đang sử dụng các công cụ này không hiệu quả. Hãy đánh giá điều này để chúng ta có đường cơ sở.
Ngoài việc ghi nhật ký, LangSmith còn cho phép bạn kiểm tra và đánh giá các ứng dụng LLM của mình.
Trong phần này, bạn sẽ tận dụng LangSmith để tạo tập dữ liệu điểm chuẩn và chạy các công cụ đánh giá được AI hỗ trợ trên một tác nhân. Bạn sẽ làm như vậy trong một vài bước:
- Tạo bộ dữ liệu LangSmith:
Dưới đây, chúng tôi sử dụng ứng dụng khách LangSmith để tạo tập dữ liệu từ các câu hỏi đầu vào ở trên và nhãn danh sách. Sau này, bạn sẽ sử dụng những thông tin này để đo lường hiệu suất của một tổng đài viên mới. Tập dữ liệu là một tập hợp các ví dụ, không gì khác hơn là các cặp đầu vào-đầu ra mà bạn có thể sử dụng làm trường hợp thử nghiệm cho ứng dụng của mình:
outputs = [ "LangChain is an open-source framework for building applications using large language models. It is also the name of the company building LangSmith.", "LangSmith is a unified platform for debugging, testing, and monitoring language model applications and agents powered by LangChain", "July 18, 2023", "The langsmith cookbook is a github repository containing detailed examples of how to use LangSmith to debug, evaluate, and monitor large language model-powered applications.", "September 5, 2023",
] dataset_name = f"agent-qa-{unique_id}" dataset = client.create_dataset( dataset_name, description="An example dataset of questions over the LangSmith documentation.",
) for query, answer in zip(inputs, outputs): client.create_example( inputs={"input": query}, outputs={"output": answer}, dataset_id=dataset.id )
- Khởi tạo một tác nhân mới để chuẩn:
LangSmith cho phép bạn đánh giá bất kỳ LLM, chuỗi, đại lý hoặc thậm chí là chức năng tùy chỉnh nào. Tác nhân đàm thoại có trạng thái (chúng có bộ nhớ); để đảm bảo rằng trạng thái này không được chia sẻ giữa các lần chạy tập dữ liệu, chúng tôi sẽ chuyển vào chain_factory (
hay còn gọi là hàm tạo) để khởi tạo cho mỗi lệnh gọi:
# Since chains can be stateful (e.g. they can have memory), we provide
# a way to initialize a new chain for each row in the dataset. This is done
# by passing in a factory function that returns a new chain for each row.
def agent_factory(prompt): llm_with_tools = llm.bind( functions=[format_tool_to_openai_function(t) for t in tools] ) runnable_agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai_function_messages( x["intermediate_steps"] ), } | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser() ) return AgentExecutor(agent=runnable_agent, tools=tools, handle_parsing_errors=True)
- Cấu hình đánh giá:
Việc so sánh thủ công kết quả của các chuỗi trong giao diện người dùng có hiệu quả nhưng có thể tốn thời gian. Có thể hữu ích khi sử dụng các số liệu tự động và phản hồi được hỗ trợ bởi AI để đánh giá hiệu suất của thành phần của bạn:
from langchain.evaluation import EvaluatorType
from langchain.smith import RunEvalConfig evaluation_config = RunEvalConfig( evaluators=[ EvaluatorType.QA, EvaluatorType.EMBEDDING_DISTANCE, RunEvalConfig.LabeledCriteria("helpfulness"), RunEvalConfig.LabeledScoreString( { "accuracy": """
Score 1: The answer is completely unrelated to the reference.
Score 3: The answer has minor relevance but does not align with the reference.
Score 5: The answer has moderate relevance but contains inaccuracies.
Score 7: The answer aligns with the reference but has minor errors or omissions.
Score 10: The answer is completely accurate and aligns perfectly with the reference.""" }, normalize_by=10, ), ], custom_evaluators=[],
)
- Chạy đại lý và người đánh giá:
Sử dụng hàm run_on_dataset (hoặc arun_on_dataset không đồng bộ) để đánh giá mô hình của bạn. Điều này sẽ:
- Tìm nạp các hàng mẫu từ tập dữ liệu đã chỉ định.
- Chạy tác nhân của bạn (hoặc bất kỳ chức năng tùy chỉnh nào) trên mỗi ví dụ.
- Áp dụng bộ đánh giá cho các dấu vết chạy kết quả và các ví dụ tham chiếu tương ứng để tạo phản hồi tự động.
Kết quả sẽ hiển thị trong ứng dụng LangSmith:
chain_results = run_on_dataset( dataset_name=dataset_name, llm_or_chain_factory=functools.partial(agent_factory, prompt=prompt), evaluation=evaluation_config, verbose=True, client=client, project_name=f"runnable-agent-test-5d466cbc-{unique_id}", tags=[ "testing-notebook", "prompt:5d466cbc", ],
)
Bây giờ chúng tôi đã có kết quả chạy thử nghiệm, chúng tôi có thể thực hiện các thay đổi đối với tác nhân của mình và đánh giá chúng. Hãy thử lại lần nữa với một dấu nhắc khác và xem kết quả:
candidate_prompt = hub.pull("wfh/langsmith-agent-prompt:39f3bbd0") chain_results = run_on_dataset( dataset_name=dataset_name, llm_or_chain_factory=functools.partial(agent_factory, prompt=candidate_prompt), evaluation=evaluation_config, verbose=True, client=client, project_name=f"runnable-agent-test-39f3bbd0-{unique_id}", tags=[ "testing-notebook", "prompt:39f3bbd0", ],
)
LangSmith cho phép bạn xuất dữ liệu sang các định dạng phổ biến như CSV hoặc JSONL trực tiếp trong ứng dụng web. Bạn cũng có thể sử dụng ứng dụng khách để tìm nạp các lần chạy nhằm phân tích thêm, lưu trữ trong cơ sở dữ liệu của riêng bạn hoặc để chia sẻ với người khác. Hãy lấy dấu vết chạy từ lần chạy đánh giá:
runs = client.list_runs(project_name=chain_results["project_name"], execution_order=1) # After some time, these will be populated.
client.read_project(project_name=chain_results["project_name"]).feedback_stats
Đây là hướng dẫn nhanh để bắt đầu nhưng có nhiều cách khác để sử dụng LangSmith nhằm tăng tốc quy trình phát triển của bạn và tạo ra kết quả tốt hơn.
Để biết thêm thông tin về cách bạn có thể tận dụng tối đa LangSmith, hãy xem tài liệu của LangSmith.
Tăng cấp với Nanonet
Mặc dù LangChain là một công cụ có giá trị để tích hợp các mô hình ngôn ngữ (LLM) với các ứng dụng của bạn nhưng nó có thể gặp phải những hạn chế khi áp dụng cho các trường hợp sử dụng của doanh nghiệp. Hãy cùng khám phá cách Nanonets vượt xa LangChain để giải quyết những thách thức này:
1. Kết nối dữ liệu toàn diện:
LangChain cung cấp các trình kết nối, nhưng nó có thể không bao gồm tất cả các ứng dụng không gian làm việc và định dạng dữ liệu mà doanh nghiệp dựa vào. Nanonets cung cấp trình kết nối dữ liệu cho hơn 100 ứng dụng không gian làm việc được sử dụng rộng rãi, bao gồm Slack, Notion, Google Suite, Salesforce, Zendesk, v.v. Nó cũng hỗ trợ tất cả các loại dữ liệu phi cấu trúc như PDF, TXT, hình ảnh, tệp âm thanh và tệp video, cũng như các loại dữ liệu có cấu trúc như cơ sở dữ liệu CSV, bảng tính, MongoDB và SQL.
2. Tự động hóa tác vụ cho ứng dụng Workspace:
Mặc dù việc tạo văn bản/phản hồi hoạt động tốt nhưng khả năng của LangChain bị hạn chế khi sử dụng ngôn ngữ tự nhiên để thực hiện các tác vụ trong nhiều ứng dụng khác nhau. Nanonets cung cấp tác nhân kích hoạt/hành động cho các ứng dụng không gian làm việc phổ biến nhất, cho phép bạn thiết lập quy trình công việc theo dõi sự kiện và thực hiện hành động. Ví dụ: bạn có thể tự động hóa phản hồi email, mục nhập CRM, truy vấn SQL, v.v., tất cả đều thông qua các lệnh ngôn ngữ tự nhiên.
3. Đồng bộ hóa dữ liệu theo thời gian thực:
LangChain tìm nạp dữ liệu tĩnh bằng các trình kết nối dữ liệu, có thể không theo kịp các thay đổi dữ liệu trong cơ sở dữ liệu nguồn. Ngược lại, Nanonets đảm bảo đồng bộ hóa thời gian thực với các nguồn dữ liệu, đảm bảo rằng bạn luôn làm việc với thông tin mới nhất.
3. Cấu hình đơn giản:
Việc định cấu hình các thành phần của đường dẫn LangChain, chẳng hạn như bộ truy xuất và bộ tổng hợp, có thể là một quá trình phức tạp và tốn thời gian. Nanonets hợp lý hóa việc này bằng cách cung cấp khả năng nhập và lập chỉ mục dữ liệu được tối ưu hóa cho từng loại dữ liệu, tất cả đều được Trợ lý AI xử lý ở chế độ nền. Điều này làm giảm gánh nặng tinh chỉnh và giúp thiết lập và sử dụng dễ dàng hơn.
4. Giải pháp thống nhất:
Không giống như LangChain, có thể yêu cầu triển khai riêng cho từng tác vụ, Nanonets đóng vai trò là giải pháp toàn diện để kết nối dữ liệu của bạn với LLM. Cho dù bạn cần tạo ứng dụng LLM hay quy trình làm việc AI, Nanonets đều cung cấp nền tảng thống nhất cho các nhu cầu đa dạng của bạn.
Quy trình làm việc AI của Nanonets
Nanonets Workflows là một Trợ lý AI đa năng, an toàn, giúp đơn giản hóa việc tích hợp kiến thức và dữ liệu của bạn với LLM, đồng thời tạo điều kiện tạo ra các ứng dụng và quy trình làm việc không cần mã. Nó cung cấp một giao diện người dùng dễ sử dụng, giúp cả cá nhân và tổ chức có thể truy cập được.
Để bắt đầu, bạn có thể lên lịch cuộc gọi với một trong các chuyên gia AI của chúng tôi, người có thể cung cấp bản demo và bản dùng thử được cá nhân hóa về Quy trình làm việc Nanonets phù hợp với trường hợp sử dụng cụ thể của bạn.
Sau khi thiết lập, bạn có thể sử dụng ngôn ngữ tự nhiên để thiết kế và thực thi các ứng dụng cũng như quy trình làm việc phức tạp do LLM cung cấp, tích hợp liền mạch với ứng dụng và dữ liệu của bạn.
Tăng cường sức mạnh cho nhóm của bạn bằng Nanonets AI để tạo ứng dụng và tích hợp dữ liệu của bạn với các ứng dụng và quy trình làm việc do AI điều khiển, cho phép nhóm của bạn tập trung vào những gì thực sự quan trọng.
Tự động hóa các tác vụ và quy trình làm việc thủ công bằng trình tạo quy trình làm việc dựa trên AI của chúng tôi, được Nanonets thiết kế cho bạn và nhóm của bạn.
- Phân phối nội dung và PR được hỗ trợ bởi SEO. Được khuếch đại ngay hôm nay.
- PlatoData.Network Vertical Generative Ai. Trao quyền cho chính mình. Truy cập Tại đây.
- PlatoAiStream. Thông minh Web3. Kiến thức khuếch đại. Truy cập Tại đây.
- Trung tâmESG. Than đá, công nghệ sạch, Năng lượng, Môi trường Hệ mặt trời, Quản lý chất thải. Truy cập Tại đây.
- PlatoSức khỏe. Tình báo thử nghiệm lâm sàng và công nghệ sinh học. Truy cập Tại đây.
- nguồn: https://nanonets.com/blog/langchain/
- : có
- :là
- :không phải
- :Ở đâu
- $ LÊN
- 1
- 10
- 100
- 114
- 13
- 15%
- 2000
- 2012
- 2023
- 25
- 30
- 32
- 36
- 40
- 400
- 408
- 50
- 500
- 7
- 8
- a
- ABC
- có khả năng
- Có khả năng
- Giới thiệu
- về nó
- ở trên
- Chấp nhận
- Chấp nhận
- truy cập
- có thể truy cập
- truy cập
- hoàn thành
- cho phù hợp
- Tài khoản
- chính xác
- chính xác
- chính xác
- Đạt được
- đạt được
- Đạt được
- ngang qua
- Hành động
- Hoạt động
- hành động
- hoạt động
- thích nghi
- thích nghi
- thêm vào
- thêm
- thêm
- Ngoài ra
- thêm vào
- Ngoài ra
- địa chỉ
- Thêm
- thừa nhận
- tiên tiến
- Phiêu lưu
- Sau
- một lần nữa
- tuổi
- Đại lý
- đại lý
- AI
- Trợ lý AI
- Mô hình AI
- Hỗ trợ
- Định hướng
- thuật toán
- sắp xếp
- Căn chỉnh
- Tất cả
- cho phép
- Cho phép
- cho phép
- cô đơn
- dọc theo
- bên cạnh
- Đã
- Ngoài ra
- Mặc dù
- luôn luôn
- an
- phân tích
- Phân tích
- phân tích
- và
- Angeles
- Thông báo
- hàng năm
- Một
- trả lời
- câu trả lời
- bài quốc ca
- nhân loại
- bất kì
- bất cứ điều gì
- api
- KHÓA API
- API
- ứng dụng
- áp dụng
- Các Ứng Dụng
- Phát triển ứng dụng
- các ứng dụng
- áp dụng
- áp dụng
- phương pháp tiếp cận
- cách tiếp cận
- thích hợp
- thích hợp
- ứng dụng
- kiến trúc
- LÀ
- đối số
- đối số
- Armstrong
- xung quanh
- Mảng
- Nghệ sĩ
- AS
- xin
- khía cạnh
- các khía cạnh
- hỗ trợ
- Trợ lý
- liên kết
- At
- đính kèm
- sự chú ý
- âm thanh
- tăng cường
- Xác thực
- tự động hóa
- Tự động
- tự động hóa
- tự động
- Tự động hóa
- có sẵn
- Trung bình cộng
- chờ đợi
- nhận thức
- AWS
- trở lại
- Xương sống
- Backend
- lý lịch
- tệ
- Cân đối
- thanh
- cơ sở
- dựa
- Baseline
- bash
- cơ bản
- Khái niệm cơ bản
- BCG
- BE
- bờ biển
- Bears
- bởi vì
- được
- trước
- bắt đầu
- hành vi
- sau
- đằng sau hậu trường
- được
- phía dưới
- điểm chuẩn
- mang lại lợi ích
- BEST
- Hơn
- giữa
- Ngoài
- lớn nhất
- Hóa đơn
- Bill Gates
- ràng buộc
- Bing
- Một chút
- Đen
- Black Hole
- Chặn
- ngăn chặn
- Khối
- Blog
- ngũ cốc
- bootstrap
- sinh
- Bot
- cả hai
- đáy
- Chi nhánh
- Nghỉ giải lao
- ruồi trâu
- một thời gian ngắn
- rộng hơn
- nâu
- trình duyệt
- đệm
- xây dựng
- xây dựng
- Xây dựng
- xây dựng
- gánh nặng
- các doanh nghiệp
- nhưng
- by
- tính toán
- tính toán
- tính
- phép tính
- cuộc gọi
- gọi lại
- gọi là
- gọi
- Cuộc gọi
- CAN
- Có thể có được
- Canada
- khả năng
- có khả năng
- Sức chứa
- nắm bắt
- Chụp
- trường hợp
- trường hợp
- CON MÈO
- phục vụ
- phục vụ
- phục vụ
- Mèo
- thận trọng
- dè dặt
- trung tâm
- nhất định
- chuỗi
- chuỗi
- thách thức
- Những thay đổi
- tính cách
- chatbot
- chatbot
- kiểm tra
- Séc
- Chọn
- lựa chọn
- hoàn cảnh
- City
- tốt nghiệp lớp XNUMX
- các lớp học
- khách hàng
- đám mây
- mã
- Lập trình
- Cà Phê
- mạch lạc
- kết dính
- hợp tác
- Sự sụp đổ
- bộ sưu tập
- đầy màu sắc
- Cột
- Cột
- COM
- kết hợp
- kết hợp
- kết hợp
- kết hợp
- Đến
- đến
- thoải mái
- Chung
- Giao tiếp
- công ty
- so sánh
- so sánh
- khả năng tương thích
- tương thích
- hoàn thành
- hoàn toàn
- hoàn thành
- phức tạp
- phức tạp
- thành phần
- các thành phần
- sáng tác
- thành phần
- toàn diện
- bao gồm
- khái niệm
- ngắn gọn
- đồng thời
- điều kiện
- Cấu hình
- hợp lưu
- Kết nối
- Kết nối
- Kết nối
- Nhược điểm
- Hãy xem xét
- nhất quán
- bao gồm
- An ủi
- liên tục
- cấu trúc
- chứa
- chứa
- nội dung
- bối cảnh
- bối cảnh
- theo ngữ cảnh
- tiếp tục
- liên tục
- Ngược lại
- điều khiển
- điều khiển
- Tiện lợi
- Conversation
- đàm thoại
- AI đàm thoại
- cuộc hội thoại
- Chuyển đổi
- chuyển đổi
- chuyển đổi
- Trung tâm
- Corner
- sửa chữa
- Tương ứng
- có thể
- hơn nữa
- đất nước
- Couple
- che
- phủ
- tạo
- tạo ra
- tạo ra
- Tạo
- tạo
- Credentials
- tiêu chuẩn
- Phê bình
- CRM
- quan trọng
- Current
- Hiện nay
- khách hàng
- khách hàng
- tùy biến
- tùy chỉnh
- tùy chỉnh
- tiên tiến
- dữ liệu
- Cấu trúc dữ liệu
- Cơ sở dữ liệu
- cơ sở dữ liệu
- Ngày
- ngày giờ
- nhiều
- xử lý
- Tháng mười hai
- quyết định
- Quyết định
- Ra quyết định
- Giải mã
- dành riêng
- sâu sắc hơn
- Mặc định
- định nghĩa
- xác định
- xác định
- các định nghĩa
- phân phối
- cung cấp
- đào sâu
- bản demo
- chứng minh
- chứng minh
- thể hiện
- phụ thuộc
- Tùy
- phụ thuộc
- triển khai
- triển khai
- triển khai
- triển khai
- triển khai
- mô tả
- Mô tả
- Thiết kế
- được chỉ định
- thiết kế
- mong muốn
- chi tiết
- chi tiết
- chi tiết
- Xác định
- xác định
- phát triển
- Nhà phát triển
- phát triển
- phát triển
- Phát triển
- sơ đồ
- DICT
- ĐÃ LÀM
- khác nhau
- khác nhau
- khác nhau
- khó khăn
- kích thước
- kích thước
- chỉ thị
- trực tiếp
- thảo luận
- thảo luận
- hiển thị
- khác biệt
- bổ nhào
- khác nhau
- DM
- do
- tài liệu
- tài liệu hướng dẫn
- tài liệu
- làm
- doesn
- làm
- don
- thực hiện
- tăng gấp đôi
- xuống
- tải về
- Tải xuống
- dự thảo
- lái xe
- hai
- suốt trong
- năng động
- năng động
- e
- mỗi
- Sớm hơn
- Đầu
- dễ dàng
- dễ sử dụng
- dễ dàng hơn
- dễ dàng
- dễ dàng
- dễ sử dụng
- bỏ lỡ
- hệ sinh thái
- Hiệu quả
- hiệu quả
- hiệu quả
- hiệu quả
- hiệu quả
- dễ dàng
- hay
- thành phần
- các yếu tố
- Elon
- Elon Musk
- khác
- nhúng
- nhúng
- nhúng
- việc làm
- nhân viên
- sử dụng
- trao quyền
- cho phép
- cho phép
- cho phép
- gói lại
- chạm trán
- Cuối cùng đến cuối
- Điểm cuối
- tương tác
- Động cơ
- Động cơ
- Nước Anh
- Tiếng Anh
- Tiếng Anh Premier League
- nâng cao
- nâng cao
- tăng cường
- đảm bảo
- đảm bảo
- đảm bảo
- Doanh nghiệp
- thực thể
- thực thể
- Môi trường
- môi trường
- Tương đương
- Kỷ nguyên
- lôi
- lỗi
- đặc biệt
- thiết yếu
- ghẻ lạnh
- vv
- đánh giá
- đánh giá
- Ngay cả
- sự kiện
- Mỗi
- ví dụ
- ví dụ
- quá
- Trừ
- thi hành
- Thực thi
- Thi công
- thi hành
- thực hiện
- làm gương
- Tập thể dục
- tồn tại
- mong đợi
- mong đợi
- dự kiến
- kỳ vọng
- kinh nghiệm
- thử nghiệm
- các chuyên gia
- Giải thích
- Giải thích
- rõ ràng
- thăm dò
- khám phá
- Khám phá
- xuất khẩu
- biểu hiện
- thêm
- mở rộng
- mở rộng
- ngoài
- thêm
- trích xuất
- khai thác
- Chất chiết xuất
- Đối mặt
- tạo điều kiện
- tạo điều kiện
- nhà máy
- sự kiện
- xa
- NHANH
- Yêu thích
- Đặc tính
- Tính năng
- thông tin phản hồi
- vài
- lĩnh vực
- Lĩnh vực
- con số
- Hình
- Tập tin
- Các tập tin
- điền
- đầy
- đổ đầy
- lọc
- lọc
- cuối cùng
- Cuối cùng
- Tìm kiếm
- tìm kiếm
- Tên
- năm
- Linh hoạt
- linh hoạt
- dòng chảy
- Tập trung
- tập trung
- tập trung
- tập trung
- theo
- tiếp theo
- sau
- thực phẩm
- Trong
- hình thức
- định dạng
- hình thành
- May mắn thay
- tìm thấy
- Khung
- khung
- thường xuyên
- người bạn
- bạn bè
- từ
- Full
- chính thức
- chức năng
- chức năng
- chức năng
- chức năng
- cơ bản
- buồn cười
- xa hơn
- tương lai
- Thu được
- Trò chơi
- Gates
- Tổng Quát
- nói chung
- tạo ra
- tạo ra
- tạo
- tạo ra
- thế hệ
- thể loại
- Nước Đức
- được
- nhận được
- gif
- GitHub
- được
- GMT
- Go
- Đi
- đi
- tốt
- dạng hạt
- đồ thị
- tuyệt vời
- lớn hơn
- hướng dẫn
- hướng dẫn
- hướng dẫn
- hackathon
- xử lý
- Xử lý
- Xử lý
- tiện dụng
- Cứng
- làm hại
- khai thác
- Có
- có
- nặng nề
- Được tổ chức
- giúp đỡ
- hữu ích
- giúp
- cô
- tại đây
- hi
- Cao
- cấp độ cao
- chất lượng cao
- cao nhất
- cao
- lịch sử
- lịch sử
- Lô
- mui xe
- chủ nhà
- Độ đáng tin của
- Hướng dẫn
- Tuy nhiên
- HTML
- http
- HTTPS
- Hub
- Nhân loại
- Hàng trăm
- i
- ID
- ý tưởng
- lý tưởng
- id
- if
- ii
- iii
- minh họa
- minh họa
- hình ảnh
- lập tức
- thực hiện
- thực hiện
- triển khai
- thực hiện
- nhập khẩu
- cải tiến
- cải thiện
- in
- sâu
- bao gồm
- bao gồm
- bao gồm
- Bao gồm
- kết hợp
- kết hợp
- vô cùng
- chỉ số
- chỉ số
- chỉ
- chỉ
- Cá nhân
- các cá nhân
- thông tin
- ban đầu
- bắt đầu
- sáng tạo
- đầu vào
- đầu vào
- những hiểu biết
- cài đặt, dựng lên
- cài đặt
- Cài đặt
- ví dụ
- ngay lập tức
- thay vì
- hướng dẫn
- thiếu
- tích hợp
- tích hợp
- Tích hợp
- Tích hợp
- hội nhập
- tích hợp
- Thông minh
- dự định
- tương tác
- tương tác
- tương tác
- tương tác
- tương tác
- Giao thức
- giao diện
- nội bộ
- Internet
- trong
- giới thiệu
- Giới thiệu
- trực quan
- liên quan đến
- isn
- vấn đề
- các vấn đề
- IT
- mặt hàng
- sự lặp lại
- ITS
- chính nó
- Jackson
- JavaScript
- Việc làm
- Jordan
- cuộc hành trình
- json
- Tháng Bảy
- chỉ
- Tư pháp
- Giữ
- giữ
- Key
- phím
- Loại
- Biết
- kiến thức
- Sơ đồ tri thức
- nổi tiếng
- nhãn
- Nhãn
- Quốc gia
- Ngôn ngữ
- Ngôn ngữ
- lớn
- lớn hơn
- Họ
- Độ trễ
- một lát sau
- mới nhất
- Liên minh
- LEARN
- học tập
- trái
- Legacy
- Chiều dài
- ít
- cho phép
- cho phép
- bức thư
- Cấp
- niveaux
- Tỉ lệ đòn bẩy
- đòn bẩy
- tận dụng
- thư viện
- Thư viện
- Lượt thích
- Có khả năng
- LIMIT
- hạn chế
- Hạn chế
- hạn chế
- giới hạn
- liên kết
- Danh sách
- nghe
- Chức năng
- sống
- ll
- LLM
- tải
- loader
- nằm
- địa điểm thư viện nào
- đăng nhập
- đăng nhập
- khai thác gỗ
- logic
- dài
- còn
- Xem
- tìm kiếm
- NHÌN
- tra cứu
- các
- Los Angeles
- Thấp
- máy
- học máy
- thực hiện
- duy trì
- Có thể bảo trì
- Duy trì
- duy trì
- làm cho
- LÀM CHO
- Làm
- quản lý
- quản lý
- giám đốc
- quản lý
- manchester
- Manchester United
- Thao tác
- cách thức
- nhãn hiệu
- nhà chế tạo
- nhiều
- nhiều người
- bản đồ
- lập bản đồ
- Maps
- Trận đấu
- phù hợp
- toán học
- toán học
- Vấn đề
- tối đa
- Có thể..
- me
- nghĩa là
- có nghĩa là
- có nghĩa
- đo
- Phương tiện truyền thông
- cuộc họp
- Đạt
- Memories
- Bộ nhớ
- đề cập
- đi
- sáp nhập
- tin nhắn
- tin nhắn
- tin nhắn
- Siêu dữ liệu
- phương pháp
- phương pháp
- Metrics
- Might
- hàng triệu
- tối thiểu
- nhỏ
- mất tích
- sai lầm
- Trộn
- MLB
- di động
- kiểu mẫu
- mô hình
- điều độ
- Mô-đun
- Modules
- thời điểm
- MongoDB
- Màn Hình
- giám sát
- mặt trăng
- chi tiết
- hầu hết
- Phổ biến nhất
- di chuyển
- phim
- nhiều
- nhiều
- nhiều chuỗi
- Xạ hương
- phải
- my
- tên
- Được đặt theo tên
- tên
- quốc dân
- Tự nhiên
- Xử lý ngôn ngữ tự nhiên
- Điều hướng
- điều hướng
- Gần
- cần thiết
- Cần
- cần thiết
- nhu cầu
- tiêu cực
- Mới
- Newyork
- Bán Chạy Nhất của Báo New York Times
- tiếp theo
- Không
- Không áp dụng
- không
- Khái niệm
- tại
- con số
- Obama
- vật
- Mục tiêu
- đối tượng
- quan sát
- được
- có được
- OCR
- of
- cung cấp
- cung cấp
- Cung cấp
- thường
- oh
- Được rồi
- olympics
- on
- hàng loạt
- ONE
- có thể
- mã nguồn mở
- OpenAI
- Hoạt động
- nhà điều hành
- tối ưu hóa
- Tối ưu hóa
- Tùy chọn
- or
- gọi món
- hữu cơ
- tổ chức
- nguyên
- OS
- Nền tảng khác
- Khác
- nếu không thì
- vfoXNUMXfipXNUMXhfpiXNUMXufhpiXNUMXuf
- ra
- đầu ra
- kết quả đầu ra
- kết thúc
- ghi đè
- tổng quan
- riêng
- gói
- gói
- trang
- trang
- cặp
- gấu trúc
- Giấy
- Song song
- tham số
- thông số
- Công viên
- một phần
- đặc biệt
- các bộ phận
- vượt qua
- thông qua
- vượt qua
- Đi qua
- qua
- con đường
- đường dẫn
- mô hình
- Lương bổng
- người
- mỗi
- hoàn hảo
- hoàn hảo
- Thực hiện
- hiệu suất
- biểu diễn
- thực hiện
- quyền
- kiên trì
- người
- Cá nhân
- quan điểm
- Vật lý
- mảnh
- đường ống dẫn
- Bánh Pizza
- giữ chỗ
- nền tảng
- plato
- Thông tin dữ liệu Plato
- PlatoDữ liệu
- Play
- sân chơi
- đóng
- xin vui lòng
- thêm
- Điểm
- Chính sách
- điều luật
- chính trị
- hồ bơi
- Phổ biến
- đông dân cư
- tích cực
- có thể
- Bài đăng
- bài viết
- tiềm năng
- quyền lực
- -
- mạnh mẽ
- Thực tế
- thực hành
- thích hơn
- Thủ tướng
- trình bày
- Chủ tịch
- ngăn chặn
- ngăn chặn
- trước
- chủ yếu
- chính
- Thủ tướng Chính phủ
- riêng
- Vấn đề
- vấn đề
- tiến hành
- quá trình
- Xử lý
- Quy trình
- xử lý
- sản xuất
- Sản phẩm
- Sản lượng
- Giáo sư
- Lập trình
- ngôn ngữ lập trình
- dự án
- dự án
- tài sản
- tài sản
- Ưu điểm
- nguyên mẫu
- tạo mẫu
- cho
- cung cấp
- nhà cung cấp dịch vụ
- nhà cung cấp
- cung cấp
- cung cấp
- công khai
- mục đích
- mục đích
- đặt
- Python
- Q & A
- chất lượng
- truy vấn
- câu hỏi
- Câu hỏi
- Nhanh chóng
- Mau
- dấu ngoặc kép
- R
- nâng cao
- phạm vi
- khác nhau,
- hơn
- giá
- Nguyên
- RE
- đạt
- Phản ứng
- Đọc
- Reading
- sẵn sàng
- thực
- thời gian thực
- dữ liệu theo thời gian thực
- vương quốc
- lý do
- lý do
- gần đây
- đề nghị
- ghi lại
- hồ sơ
- Phục hồi
- giảm
- làm giảm
- giảm
- giảm
- tài liệu tham khảo
- tham khảo
- lọc
- tinh luyện
- vùng
- Mối quan hệ
- phát hành
- sự liên quan
- có liên quan
- độ tin cậy
- đáng tin cậy
- dựa
- dựa vào
- vẫn còn
- nhớ
- nhắc nhở
- xa
- sản lượng
- lặp lại
- NHIỀU LẦN
- diễn đạt lại
- thay thế
- báo cáo
- kho
- đại diện
- đại diện
- đại diện cho
- yêu cầu
- yêu cầu
- yêu cầu
- cần phải
- Yêu cầu
- đòi hỏi
- giải cứu
- nghiên cứu
- giải quyết
- tài nguyên
- Trả lời
- đáp ứng
- phản ứng
- phản ứng
- chịu trách nhiệm
- đáp ứng
- REST của
- kết quả
- kết quả
- Kết quả
- giữ lại
- giữ
- trở lại
- trở về
- Trả về
- có thể tái sử dụng
- xem xét
- xoay vòng
- Gạo
- Giàu
- robot
- Vai trò
- vai trò
- nguồn gốc
- định tuyến
- HÀNG
- chạy
- chạy
- chạy
- thời gian chạy
- s
- biện pháp bảo vệ
- bán hàng
- lực lượng bán hàng
- Sam
- tương tự
- Lưu
- nói
- nói
- khả năng mở rộng
- Quy mô
- kịch bản
- kịch bản
- cảnh
- lịch trình
- Điểm số
- xước
- liền mạch
- liền mạch
- Tìm kiếm
- công cụ tìm kiếm
- tìm kiếm
- tìm kiếm
- Phần
- phần
- an toàn
- an ninh
- xem
- chọn
- lựa chọn
- Bán
- gửi
- nhạy cảm
- tình cảm
- cảm xúc
- riêng biệt
- Tháng Chín
- Trình tự
- Loạt Sách
- phục vụ
- máy chủ
- phục vụ
- DỊCH VỤ
- định
- bộ
- thiết lập
- thiết lập
- thiết lập
- XNUMX
- một số
- Chia sẻ
- chia sẻ
- Shell
- tỏa sáng
- vận chuyển
- nên
- hiển thị
- giới thiệu
- thể hiện
- Chương trình
- Sigma
- có ý nghĩa
- tương tự
- Đơn giản
- đơn giản hóa
- đơn giản hóa
- đơn giản hóa
- đơn giản
- kể từ khi
- duy nhất
- Kích thước máy
- lún xuống
- nhỏ
- nhỏ hơn
- thông minh
- đoạn
- So
- cho đến nay
- Bóng đá
- Mạng xã hội
- truyền thông xã hội
- Bài đăng trên mạng xã hội
- chỉ duy nhất
- rắn
- giải pháp
- động SOLVE
- một số
- một cái gì đó
- đôi khi
- tinh vi
- âm thanh
- nguồn
- nguồn
- Không gian
- Tiếng Tây Ban Nha
- chuyên nghành
- riêng
- đặc biệt
- chi tiết cụ thể
- quy định
- tốc độ
- tiêu
- chia
- Tách
- thể thao
- vuông
- đứng
- độc lập
- Tiêu chuẩn
- Bắt đầu
- bắt đầu
- Bắt đầu
- Tiểu bang
- báo cáo
- tĩnh
- Bước
- Các bước
- Vẫn còn
- Dừng
- dừng lại
- Dừng
- là gắn
- hàng
- lưu trữ
- cửa hàng
- lưu trữ
- Câu chuyện
- đơn giản
- dòng
- trực tuyến
- hợp lý hóa
- sắp xếp hợp lý
- thế mạnh
- Đình công
- Chuỗi
- cấu trúc
- cấu trúc
- cấu trúc
- cấu trúc
- phong cách
- Tiêu đề
- tiếp theo
- Thành công
- như vậy
- Bộ đồ
- phù hợp
- bộ
- tóm tắt
- TÓM TẮT
- Hoàng hôn
- hỗ trợ
- Hỗ trợ
- Hỗ trợ
- chắc chắn
- Tính bền vững
- đồng bộ hóa
- tóm tắc
- cú pháp
- hệ thống
- hệ thống
- bàn
- thợ may
- phù hợp
- Hãy
- mất
- mục tiêu
- Nhiệm vụ
- nhiệm vụ
- nhóm
- đội
- nói
- mẫu
- mẫu
- Thiết bị đầu cuối
- thuật ngữ
- về
- thử nghiệm
- Kiểm tra
- văn bản
- hơn
- Cảm ơn
- việc này
- Sản phẩm
- Khái niệm cơ bản
- trung tâm
- thông tin
- The New York Times
- Dự án
- Nguồn
- thế giới
- cung cấp their dịch
- Them
- sau đó
- Đó
- Kia là
- họ
- điều
- điều này
- những
- Tuy nhiên?
- Thông qua
- khắp
- thời gian
- mất thời gian
- thời gian
- Yêu sách
- đến
- bên nhau
- mã thông báo
- Mã thông báo
- Tokens
- quá
- công cụ
- bộ công cụ
- công cụ
- hàng đầu
- chủ đề
- Chủ đề
- Tổng số:
- thị trấn
- Truy tìm
- theo dõi
- truyền thống
- Hội thảo
- Chuyển đổi
- biến đổi
- biến áp
- máy biến áp
- quá trình chuyển đổi
- thử nghiệm
- đúng
- thực sự
- thử
- điều chỉnh
- XOAY
- Quay
- hướng dẫn
- Hai lần
- hai
- kiểu
- loại
- Bản đánh máy
- thường
- ui
- Cuối cùng
- không bị ảnh hưởng
- Dưới
- cơ bản
- hiểu
- sự hiểu biết
- hiểu
- thống nhât
- độc đáo
- Kỳ
- phổ cập
- không giống
- cho đến khi
- Cập nhật
- Cập nhật
- tải lên
- URL
- us
- khả năng sử dụng
- Sử dụng
- sử dụng
- ca sử dụng
- đã sử dụng
- người sử dang
- Giao diện người dùng
- Người sử dụng
- sử dụng
- sử dụng
- tiện ích
- sử dụng
- tận dụng
- sử dụng
- Bằng cách sử dụng
- v1
- xác nhận
- Xác nhận
- Quý báu
- giá trị
- Các giá trị
- biến
- nhiều
- khác nhau
- Ve
- linh hoạt
- phiên bản
- rất
- thông qua
- Video
- Xem
- Vi phạm
- có thể nhìn thấy
- hình dung
- quan trọng
- vs
- đi bộ
- hương
- muốn
- là
- Đồng hồ đeo tay
- Đường..
- cách
- we
- Thời tiết
- web
- trình duyệt web
- các dịch vụ web
- trang web
- TỐT
- nổi tiếng
- là
- Điều gì
- Là gì
- whats
- khi nào
- liệu
- cái nào
- trong khi
- CHÚNG TÔI LÀ
- toàn bộ
- tại sao
- rộng
- rộng rãi
- phụ tùng
- Wikipedia
- sẽ
- cửa sổ
- Thắng
- với
- ở trong
- không có
- Từ
- Công việc
- làm việc
- quy trình làm việc
- Luồng công việc
- đang làm việc
- công trinh
- thế giới
- sẽ
- viết
- viết
- X
- nhưng
- york
- Bạn
- trên màn hình
- mình
- youtube
- Zendesk
- zephyrnet
- Zip