MariTalk
简介
MariTalk 是由巴西公司 Maritaca AI 开发的助手。 MariTalk 基于特别训练以很好地理解葡萄牙语的语言模型。
这个笔记本通过两个例子展示了如何使用MariTalk与LangChain结合。
- 使用 MariTalk 执行任务的简单示例。
- LLM + RAG: 第二个示例展示了如何回答一个答案来源于一份超出了MariTalk的令牌限制的长文档中的问题。为此,我们将使用一个简单的搜索器(BM25)首先在文档中查找最相关的部分,然后将这些部分提供给MariTalk来作答。
安装
首先,使用以下命令安装LangChain库及其所有依赖项:
!pip install langchain langchain-core langchain-community httpx
API 密钥
您将需要一个API密钥,可以在chat.maritaca.ai(“Chaves da API”部分)获得。
Example 1 - 宠物名称建议
让我们定义我们的语言模型,ChatMaritalk,并配置您的API密钥。
from langchain_community.chat_models import ChatMaritalk
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts.chat import ChatPromptTemplate
llm = ChatMaritalk(
model="sabia-2-medium", # Available models: sabia-2-small and sabia-2-medium
api_key="", # Insert your API key here
temperature=0.7,
max_tokens=100,
)
output_parser = StrOutputParser()
chat_prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"You are an assistant specialized in suggesting pet names. Given the animal, you must suggest 4 names.",
),
("human", "I have a {animal}"),
]
)
chain = chat_prompt | llm | output_parser
response = chain.invoke({"animal": "dog"})
print(response) # should answer something like "1. Max\n2. Bella\n3. Charlie\n4. Rocky"
流生成
对于生成长文本的任务,例如撰写一篇长篇文章或翻译一份大型文档,分阶段接收生成的文本会更有优势,而无需等待整个文本生成完毕。这使得应用程序更加响应和高效,特别是在生成的文本较长时尤为明显。我们提供两种满足这一需求的方法:一种是同步方法,另一种是异步方法。
异步:
from langchain_core.messages import HumanMessage
messages = [HumanMessage(content="Suggest 3 names for my dog")]
for chunk in llm.stream(messages):
print(chunk.content, end="", flush=True)
API 参考:人类消息
异步:
from langchain_core.messages import HumanMessage
async def async_invoke_chain(animal: str):
messages = [HumanMessage(content=f"Suggest 3 names for my {animal}")]
async for chunk in llm._astream(messages):
print(chunk.message.content, end="", flush=True)
await async_invoke_chain("dog")
API 参考:人类消息
Example 2 - RAG + LLM: UNICAMP 2024 入学考试问答系统
对于这个例子,我们需要安装一些额外的库:
!pip install unstructured rank_bm25 pdf2image pdfminer-six pikepdf pypdf unstructured_inference fastapi kaleido uvicorn "pillow<10.1.0" pillow_heif -q
加载数据库
第一步是创建一个数据库,包含通知中的信息。为此,我们将从COMVEST网站下载该通知,并将提取的文本分割成500字符的窗口。
from langchain_community.document_loaders import OnlinePDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
# Loading the COMVEST 2024 notice
loader = OnlinePDFLoader(
"https://www.comvest.unicamp.br/wp-content/uploads/2023/10/31-2023-Dispoe-sobre-o-Vestibular-Unicamp-2024_com-retificacao.pdf"
)
data = loader.load()
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, chunk_overlap=100, separators=["\n", " ", ""]
)
texts = text_splitter.split_documents(data)
API 参考:OnlinePDFLoader |递归字符文本分割器
创建一个搜索器
现在我们有了数据库,接下来需要一个搜索器。对于这个示例,我们将使用简单的BM25作为搜索引擎,但这可以被其他任何搜索器(如基于嵌入的搜索)所替代。
from langchain_community.retrievers import BM25Retriever
retriever = BM25Retriever.from_documents(texts)
API 参考:BM25Retriever
结合搜索系统 + 语言模型LLM
现在我们已经有了搜索器,我们只需要实现一个提示来指定任务并调用链。
from langchain.chains.question_answering import load_qa_chain
prompt = """Baseado nos seguintes documentos, responda a pergunta abaixo.
{context}
Pergunta: {query}
"""
qa_prompt = ChatPromptTemplate.from_messages([("human", prompt)])
chain = load_qa_chain(llm, chain_type="stuff", verbose=True, prompt=qa_prompt)
query = "Qual o tempo máximo para realização da prova?"
docs = retriever.invoke(query)
chain.invoke(
{"input_documents": docs, "query": query}
) # Should output something like: "O tempo máximo para realização da prova é de 5 horas."
API 参考:load_qa_chain