2
respostas

[Dúvida] Primeiro projeto: Agente de Futebol com IA gratuita

Boa tarde!
Com ajuda de IA consegui implementar no colab o primeiro projeto do Agente de Futebol utilizando IA gratuita, porém a resposta não é nada humanizada, ou seja, não cumpre com a proposta do RAG.

Caso alguém tenha alguma melhoria para que o código funcione de forma que a resposta seja coerente, por favor, compartilhe?

Exemplo de saída:
Pergunta: O que caracteriza a posição de impedimento no futebol?

Resposta do Agente:
Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer.

Após isto é exibido os trechos, que suprimi, para responder a pergunta.

segue código:

!pip install -U \
  langchain==0.1.20 \
  langchain-community==0.0.38 \
  chromadb \
  sentence-transformers \
  pypdf
# Importações básicas

# loader de documentos PDF
from langchain_community.document_loaders import PyPDFLoader

# Divisão de texto em blocos
from langchain_text_splitters import RecursiveCharacterTextSplitter

# Embeddings
from langchain_community.embeddings import HuggingFaceEmbeddings

# Banco vetorial
from langchain_community.vectorstores import Chroma

# Cadeia RAG
from langchain.chains import RetrievalQA

from langchain_community.llms import HuggingFacePipeline

from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, pipeline
# Caminho do PDF
CAMINHO_PDF = "regras_futebol.pdf"

# carrega o PDF
loader = PyPDFLoader(CAMINHO_PDF)
documents = loader.load()

# quantidade de páginas carregadas
len(documents)
from google.colab import drive
drive.mount('/content/drive')

Preparação dos Documentos
Os documentos precisam ser divididos em pequenos blocos para facilitar a recuperação de contexto

# Divide os documentos em chuncks menores
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=100
)

chunks = text_splitter.split_documents(documents)

len(chunks)
# Inicializa embeddings
embeddings = HuggingFaceEmbeddings(
    model_name="sentence-transformers/all-MiniLM-L6-v2"
)

# Cria o banco vetorial
vectorstore = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./chroma_regras_futebol"
)

vectorstore.persist()

Recuperação de Contexto (Retriever)
O retriever busca os trechos mais relevantes para cada pergunta do usuário.

# cria o retriever
retriever = vectorstore.as_retriever(
    search_type="similarity",
    search_kwargs={"k": 3}
)

Integração com o LLM (RAG)
O contexto recuperado será injetado no prompt enviado ao modelo de linguagem

# Inicializa o modelo de linguagem
# Carrega o tokenizer e o modelo explicitamente para garantir o tipo correto (Seq2Seq)
tokenizer = AutoTokenizer.from_pretrained("google/flan-t5-base")
model = AutoModelForSeq2SeqLM.from_pretrained("google/flan-t5-base")

# Cria o pipeline da transformers com o modelo e tokenizer corretos
llm_pipeline  = pipeline(
    task="text-generation",
    model=model,
    tokenizer=tokenizer,
    max_new_tokens=256,
    do_sample=False
)

# Passa o pipeline diretamente para o HuggingFacePipeline do LangChain
llm = HuggingFacePipeline(pipeline=llm_pipeline )

from langchain.chains import RetrievalQA

# Cria a cadeia RAG
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=retriever,
    return_source_documents=True
)

Testes e Validação
Agora podemos testar perguntas reais e validar se as respostas estão baseadas nos documentos.

# Pergunta de teste
pergunta = "O que caracteriza a posição de impedimento no futebol?"

# Executa a pergunta no agente RAG
resposta = qa_chain(pergunta)

print("Pergunta:")
print(pergunta)

print("\nResposta do Agente:")
print(resposta["result"])

print("\nTrechos utilizados como contexto:\n")
for i, doc in enumerate(resposta["source_documents"], start=1):
    print(f"--- Trecho {i} ---")
    print(f"Fonte: {doc.metadata.get('source', 'Documento desconhecido')}")
    print(f"Página: {doc.metadata.get('page', 'N/A')}\n")
    print("Conteúdo:")
    print(doc.page_content)
    print("\n")
2 respostas

Segue a resposta completa da execução da pergunta:

Both max_new_tokens (=256) and max_length(=20) seem to have been set. max_new_tokens will take precedence. Please refer to the documentation for more information. (https://huggingface.co/docs/transformers/main/en/main_classes/text_generation)
Pergunta:
O que caracteriza a posição de impedimento no futebol?

Resposta do Agente:
Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer.

Para todas as categorias do futebol:
• 
o número de substituições que cada equipe está autorizada a fazer, até o máximo
de cinco*, exceto no futebol juvenil, em que o máximo será determinado pela
federação nacional, a confederação ou a FIFA.

  • Consulte também a Regra 3 para conhecer as condições que se aplicam aos jogos
    que vão para a prorrogação e os detalhes sobre as restrições aplicáveis às
    oportunidades de substituição.
    Modificações gerais

20
A universalidade das Regras do Jogo significa que o futebol é essencialmente o
mesmo em todas as partes do mundo e em todas as categorias. Além de criarem
um ambiente justo e seguro para sua disputa, as Regras devem fomentar a
participação e o divertimento.
Historicamente, a IFAB vem concedendo às federações nacionais de futebol certa
flexibilidade para modificar as Regras organizacionais em determinadas
categorias. No entanto, a IFAB acredita firmemente que as federações nacionais

pode compartilhar com outras federações para auxiliá-las no desenvolvimento do
futebol.
A IFAB também tem muito interesse em conhecer outras possíveis modificações
nas Regras do Jogo que aumentem a participação no futebol, o tornem mais
atrativo e fomentem seu desenvolvimento em todo o mundo.
Regras do Jogo 2023/24 | Notas e modificações

Question: O que caracteriza a posição de impedimento no futebol?
Helpful Answer:

Trechos utilizados como contexto:

--- Trecho 1 ---
Fonte: regras_futebol.pdf
Página: 19

Conteúdo:
Para todas as categorias do futebol:
• 
o número de substituições que cada equipe está autorizada a fazer, até o máximo
de cinco*, exceto no futebol juvenil, em que o máximo será determinado pela
federação nacional, a confederação ou a FIFA.

  • Consulte também a Regra 3 para conhecer as condições que se aplicam aos jogos
    que vão para a prorrogação e os detalhes sobre as restrições aplicáveis às
    oportunidades de substituição.
    Modificações gerais

Olá Rafael!

Muito bem, ta muito bom seu trabalho!

Pelo que você mostrou, o comportamento estranho da resposta está mais ligado à configuração do modelo do que ao RAG em si.

No seu código, você está usando o flan-t5-base, que é um modelo do tipo encoder-decoder. Ele normalmente funciona melhor com a task text2text-generation, mas no pipeline você definiu text-generation. Isso pode fazer o modelo “devolver” parte do próprio prompt em vez de gerar só a resposta.

Outro ponto é o modelo de embeddings all-MiniLM-L6-v2, que é mais voltado para inglês. Como seu PDF está em português, a busca semântica pode não recuperar os trechos mais corretos. Testar um modelo multilíngue pode ajudar a melhorar a qualidade do contexto retornado.

Também vale observar que o prompt padrão do RetrievalQA vem em inglês. Como sua pergunta e seus dados estão em português, criar um prompt simples em português pode deixar a resposta mais natural.

Resumindo, você pode testar três ajustes simples: usar text2text-generation no pipeline do T5, experimentar embeddings multilíngues e definir um prompt em português. Isso já tende a deixar as respostas mais coerentes, embora o resultado possa variar um pouco dependendo do modelo e do ambiente.

Você já está no caminho certo montando tudo no Colab e validando os trechos retornados. Agora é mais um ajuste fino de configuração do que de arquitetura.

Bons estudos!

Sucesso

Imagem da comunidade