Desplegar backend com LLM no HuggingFace

Desplegar backend com LLM no HuggingFace Desplegar backend com LLM no HuggingFace

Deployar backend no HuggingFacelink image 96

Aviso: Este post foi traduzido para o português usando um modelo de tradução automática. Por favor, me avise se encontrar algum erro.

Neste post, vamos ver como deployar um backend no HuggingFace. Vamos ver como fazer isso de duas maneiras, através da forma comum, criando uma aplicação com Gradio, e através de uma opção diferente usando FastAPI, Langchain e Docker.

Para ambos casos será necessário ter uma conta no HuggingFace, já que vamos implantar o backend em um espaço do HuggingFace.

Desplegar backend com Gradiolink image 97

Criar espaçolink image 98

Primeiro de tudo, criamos um novo espaço na Hugging Face.

  • Colocamos um nome, uma descrição e escolhemos a licença.* Escolhemos o Gradio como o tipo de SDK. Ao escolher o Gradio, serão exibidas algumas templates, então escolhemos a template do chatbot.* Selecionamos o HW no qual vamos a desdobrar o backend, eu vou escolher a CPU gratuita, mas você escolha o que melhor considerar.* E por último, temos que escolher se queremos criar o espaço público ou privado.

backend gradio - criar espaço

Códigolink image 99

Ao criar o space, podemos cloná-lo ou podemos ver os arquivos na própria página do HuggingFace. Podemos ver que foram criados 3 arquivos, app.py, requirements.txt e README.md. Então, vamos ver o que colocar em cada um.

app.pylink image 100

Aqui está o código do aplicativo. Como escolhemos o template de chatbot, já temos muito feito, mas vamos ter que mudar 2 coisas: primeiro, o modelo de linguagem e o system prompt.

Como modelo de linguagem, vejo HuggingFaceH4/zephyr-7b-beta, mas vamos utilizar Qwen/Qwen2.5-72B-Instruct, que é um modelo muito capaz. Então, procure pelo texto client = InferenceClient("HuggingFaceH4/zephyr-7b-beta") e substitua-o por client = InferenceClient("Qwen/Qwen2.5-72B-Instruct"), ou espere que colocarei todo o código mais tarde.

Também vamos alterar o system prompt, que por padrão é You are a friendly Chatbot., mas como o modelo foi treinado principalmente em inglês, é provável que se você falar com ele em outro idioma, ele responda em inglês. Então, vamos mudá-lo para You are a friendly Chatbot. Always reply in the language in which the user is writing to you.. Então, procure pelo texto gr.Textbox(value="You are a friendly Chatbot.", label="System message"), e substitua-o por gr.Textbox(value="You are a friendly Chatbot. Always reply in the language in which the user is writing to you.", label="System message"),, ou espere até eu colocar todo o código agora.

import gradio as grdo huggingface_hub import InferenceClient
      """"""Para mais informações sobre o suporte da API de Inferência do `huggingface_hub`, consulte a documentação: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference""""""client = InferenceClient("Qwen/Qwen2.5-72B-Instruct")
      
      def responder(mensagem,história: list[tuple[str, str]],Mensagem do sistema,max_tokens,temperatura,top_p,):mensagens = [{"papel": "sistema", "conteúdo": system_message}]
      for val in history:if val[0]:messages.append({"role": "user", "content": val[0]})if val[1]:messages.append({"role": "assistant", "content": val[1]})
      messages.append({"role": "user", "content": message})
      response = ""
      para mensagem em client.chat_completion(mensagens,max_tokens=max_tokens,stream=True,temperature=temperature,top_p=top_p,):token = message.choices[0].delta.content
      response += tokenyield response
      
      """"""Para informações sobre como personalizar a ChatInterface, consulte a documentação do gradio: https://www.gradio.app/docs/chatinterface""""""demo = gr.ChatInterface(responda,```markdown
      additional_inputs=[
      ```gr.Textbox(value="Você é um chatbot amigável. Sempre responda na língua em que o usuário está escrevendo para você.", label="Mensagem do sistema"),gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Máximo de novos tokens"),gr.Slider(mínimo=0,1, máximo=4,0, valor=0,7, passo=0,1, rótulo="Temperatura"),gr.Slider(mínimo=0.1,máximo=1.0,value=0.95,passo=0.05,label="Top-p (amostragem do núcleo)"),],)
      
      if __name__ == "__main__":demo.launch()```
      

requirements.txtlink image 101

Este é o arquivo onde serão escritas as dependências, mas para este caso vai ser muito simples:

txt
      huggingface_hub==0.25.2```

LEIA-ME.mdlink image 102

Este é o arquivo no qual vamos colocar as informações do espaço. Nos spaces da HuggingFace, no início dos readmes, coloca-se um código para que a HuggingFace saiba como exibir a miniatura do espaço, qual arquivo deve ser usado para executar o código, versão do sdk, etc.

---título: SmolLM2emoji: 💬colorFrom: amarelocolorTo: roxosdk: gradiosdk_version: 5.0.1app_file: app.pypinned: falselicença: apache-2.0short_description: Bate-papo com o Gradio SmolLM2---
      Um exemplo de chatbot usando [Gradio](https://gradio.app), [`huggingface_hub`](https://huggingface.co/docs/huggingface_hub/v0.22.2/en/index) e a [Hugging Face Inference API](https://huggingface.co/docs/api-inference/index).```
      

Implantaçãolink image 103

Se nós clonamos o espaço, temos que fazer um commit e um push. Se modificamos os arquivos no HuggingFace, basta salvá-los. Então, quando as alterações estiverem no HuggingFace, teremos que esperar alguns segundos para que o espaço seja construído e possamos usá-lo. backend gradio - chatbot

Backendlink image 104

Muito bem, fizemos um chatbot, mas não era essa a intenção, aqui tínhamos vindo fazer um backend! Pára, pára, olha o que diz abaixo do chatbot backend gradio - Use via API

Podemos ver um texto Use via API, onde se clicarmos, se abrirá um menu com uma API para poder usar o chatbot. backend gradio - API

Vemos que nos dá uma documentação de como usar a API, tanto com Python, com JavaScript, quanto com bash.

Teste da APIlink image 105

Usamos o código de exemplo de Python.

	
from gradio_client import Client
client = Client("Maximofn/SmolLM2")
result = client.predict(
message="Hola, ¿cómo estás? Me llamo Máximo",
system_message="You are a friendly Chatbot. Always reply in the language in which the user is writing to you.",
max_tokens=512,
temperature=0.7,
top_p=0.95,
api_name="/chat"
)
print(result)
Copy
	
Loaded as API: https://maximofn-smollm2.hf.space ✔
¡Hola Máximo! Mucho gusto, estoy bien, gracias por preguntar. ¿Cómo estás tú? ¿En qué puedo ayudarte hoy?

Estamos fazendo chamadas à API do InferenceClient da HuggingFace, então poderíamos pensar, Para que fizemos um backend, se podemos chamar diretamente a API da HuggingFace? Bem, você vai ver isso abaixo.

	
result = client.predict(
message="¿Cómo me llamo?",
system_message="You are a friendly Chatbot. Always reply in the language in which the user is writing to you.",
max_tokens=512,
temperature=0.7,
top_p=0.95,
api_name="/chat"
)
print(result)
Copy
	
Tu nombre es Máximo. ¿Es correcto?

O modelo de bate-papo do Gradio gerencia o histórico para nós, de forma que cada vez que criamos um novo cliente, uma nova thread de conversa é criada.

Vamos a tentar criar um novo cliente e ver se uma nova thread de conversa é criada.

	
from gradio_client import Client
new_client = Client("Maximofn/SmolLM2")
result = new_client.predict(
message="Hola, ¿cómo estás? Me llamo Luis",
system_message="You are a friendly Chatbot. Always reply in the language in which the user is writing to you.",
max_tokens=512,
temperature=0.7,
top_p=0.95,
api_name="/chat"
)
print(result)
Copy
	
Loaded as API: https://maximofn-smollm2.hf.space ✔
Hola Luis, estoy muy bien, gracias por preguntar. ¿Cómo estás tú? Es un gusto conocerte. ¿En qué puedo ayudarte hoy?

Agora vamos perguntar novamente como me chamo

	
result = new_client.predict(
message="¿Cómo me llamo?",
system_message="You are a friendly Chatbot. Always reply in the language in which the user is writing to you.",
max_tokens=512,
temperature=0.7,
top_p=0.95,
api_name="/chat"
)
print(result)
Copy
	
Te llamas Luis. ¿Hay algo más en lo que pueda ayudarte?

Como podemos ver, temos dois clientes, cada um com seu próprio fio de conversa.

Deploy do backend com FastAPI, Langchain e Dockerlink image 106

Agora vamos a fazer o mesmo, criar um backend de um chatbot, com o mesmo modelo, mas nesse caso usando FastAPI, Langchain e Docker.

Criar espaçolink image 107

Temos que criar um novo espaço, mas nesse caso faremos de outra maneira

  • Colocamos um nome, uma descrição e escolhemos a licença.* Escolhemos Docker como o tipo de SDK. Ao escolher Docker, aparecerão modelos, então escolhemos um modelo em branco.* Selecionamos o HW no qual vamos a desdobrar o backend, eu vou escolher a CPU gratuita, mas você escolha o que melhor considerar.* E por fim, é preciso escolher se queremos criar o espaço público ou privado.

backend docker - criar espaço

Códigolink image 108

Agora, ao criar o space, vemos que temos apenas um arquivo, o README.md. Então vamos ter que criar todo o código nós mesmos.

app.pylink image 109

Vamos a criar o código do aplicativo

Começamos com as bibliotecas necessárias

from fastapi import FastAPI, HTTPExceptionfrom pydantic import BaseModeldo huggingface_hub import InferenceClient
      ```markdown
      from langchain_core.messages import HumanMessage, AIMessage
      ```from langgraph.checkpoint.memory import MemorySaverfrom langgraph.graph import START, MessagesState, StateGraph
      import osfrom dotenv import load_dotenvload_dotenv()```
      
      Carregamos `fastapi` para poder criar as rotas da API, `pydantic` para criar o template das queries, `huggingface_hub` para poder criar um modelo de linguagem, `langchain` para indicar ao modelo se as mensagens são do chatbot ou do usuário e `langgraph` para criar o chatbot.
      Além disso, carregamos `os` e `dotenv` para poder carregar as variáveis de ambiente.
      

Carregamos o token do HuggingFace

# Token da HuggingFaceHUGGINGFACE_TOKEN = os.environ.get("HUGGINGFACE_TOKEN", os.getenv("HUGGINGFACE_TOKEN"))```
      

Criamos o modelo de linguagem

# Inicializar o modelo da HuggingFacemodel = InferenceClient(model="Qwen/Qwen2.5-72B-Instruct",api_key=os.getenv("HUGGINGFACE_TOKEN"))```
      

Criamos agora uma função para chamar o modelo

# Defina a função que chama o modelodef chamar_modelo(estado: MessagesState):""""""Chame o modelo com as mensagens fornecidas
      Argumentos:estado: EstadoMensagens
      Retorna:um dicionário contendo o texto gerado e o ID do thread""""""# Converter mensagens do LangChain para o formato do HuggingFacehf_messages = []for msg in state["messages"]:Se `isinstance(msg, HumanMessage)`:hf_messages.append({"role": "user", "content": msg.content})elif isinstance(msg, AIMessage):hf_messages.append({"role": "assistant", "content": msg.content})    
      # Chamar a APIresposta = modelo.completar_chat(mensagens=hf_mensagens,temperature=0.5,max_tokens=64,top_p=0,7)    
      # Converter a resposta para o formato LangChain```python
      ai_message = AIMessage(content=response.choices[0].message.content)
      ```return {"messages": state["messages"] + [ai_message]}```
      
      Convertemos as mensagens do formato LangChain para o formato HuggingFace, assim podemos usar o modelo de linguagem.
      

Definimos uma template para as queries

class QueryRequest(BaseModel):query: strthread_id: str = "padrão"```
      
      As consultas terão um `query`, a mensagem do usuário, e um `thread_id`, que é o identificador do fio da conversação e mais adiante explicaremos para que o utilizamos.
      

Criamos um grafo de LangGraph

# Definir o gráficoworkflow = StateGraph(state_schema=MessagesState)
      # Defina o nódo na gráficoworkflow.add_edge(START, "model")workflow.add_node("modelo", call_model)
      # Adicionar memóriamemory = MemorySaver()graph_app = workflow.compile(checkpointer=memory)```
      
      Com isso, criamos um grafo de LangGraph, que é uma estrutura de dados que nos permite criar um chatbot e gerenciar o estado do chatbot para nós, ou seja, entre outras coisas, o histórico de mensagens. Dessa forma, não precisamos fazer isso nós mesmos.
      

Criamos a aplicação de FastAPI

app = FastAPI(title="LangChain FastAPI", description="API para gerar texto usando LangChain e LangGraph")```
      

Criamos os endpoints da API

# Ponto de entrada Bem-vindo@app.get("/")async def api_home():"""Ponto de entrada Welcome"""return {"detail": "Bem-vindo ao tutorial de FastAPI, Langchain, Docker"}
      # Gerar ponto final@app.post("/generate")async def gerar(request: QueryRequest):""""""Ponto final para gerar texto usando o modelo de linguagem    
      Argumentos:solicitação: QueryRequestquery: strthread_id: str = "padrão"
      Retorna:um dicionário contendo o texto gerado e o ID do thread""""""tente:# Configurar o ID da threadconfig = {"configurable": {"thread_id": request.thread_id}}        
      # Crie a mensagem de entradainput_messages = [HumanMessage(content=request.query)]        
      # Invocar o gráficooutput = graph_app.invoke({"messages": input_messages}, config)        
      # Obter a resposta do modeloresposta = output["messages"][-1].conteúdo        
      return {"generated_text": resposta,"thread_id": request.thread_id}except Exception as e:raise HTTPException(status_code=500, detail=f"Erro ao gerar texto: {str(e)}")```
      
      Criamos o endpoint `/` que nos retornará um texto quando acessarmos a API, e o endpoint `/generate` que é o que usaremos para gerar o texto.
      Se nós olharmos para a função `generate`, temos a variável `config`, que é um dicionário que contém o `thread_id`. Este `thread_id` é o que nos permite ter um histórico de mensagens de cada usuário, desta forma, diferentes usuários podem usar o mesmo endpoint e ter seu próprio histórico de mensagens.
      

Por último, temos o código para que se possa executar a aplicação

if __name__ == "__main__":import uvicornuvicorn.run(app, host="0.0.0.0", port=7860)```
      

Vamos escrever todo o código juntos

from fastapi import FastAPI, HTTPExceptionfrom pydantic import BaseModeldo huggingface_hub import InferenceClient
      ```markdown
      from langchain_core.messages import HumanMessage, AIMessage
      ```from langgraph.checkpoint.memory import MemorySaverfrom langgraph.graph import START, MessagesState, StateGraph
      import osfrom dotenv import load_dotenvload_dotenv()
      # Token da HuggingFaceHUGGINGFACE_TOKEN = os.environ.get("HUGGINGFACE_TOKEN", os.getenv("HUGGINGFACE_TOKEN"))
      # Inicialize o modelo do HuggingFacemodel = InferenceClient(model="Qwen/Qwen2.5-72B-Instruct",api_key=os.getenv("HUGGINGFACE_TOKEN"))
      # Defina a função que chama o modelodef chamar_modelo(estado: EstadoMensagens):""""""Chame o modelo com as mensagens fornecidas
      Argumentos:estado: MensagensState
      Retorna:um dicionário contendo o texto gerado e o ID do thread""""""# Converter mensagens do LangChain para o formato do HuggingFacehf_messages = []for msg in state["messages"]:if isinstance(msg, HumanMessage):hf_messages.append({"role": "user", "content": msg.content})elif isinstance(msg, AIMessage):hf_messages.append({"role": "assistant", "content": msg.content})    
      # Chame a APIresposta = modelo.completar_chat(mensagens=hf_mensagens,temperature=0.5,max_tokens=64,top_p=0,7)    
      # Converter a resposta para o formato LangChain```markdown
      ai_message = AIMessage(content=response.choices[0].message.content)
      ```return {"messages": state["messages"] + [ai_message]}
      # Definir o gráficoworkflow = StateGraph(state_schema=MessagesState)
      # Defina o nó no grafoworkflow.add_edge(START, "model")workflow.add_node("modelo", call_model)
      # Adicionar memóriamemory = MemorySaver()graph_app = workflow.compile(checkpointer=memory)
      # Defina o modelo de dados para o pedidoclass QueryRequest(BaseModel):query: strthread_id: str = "padrão"
      # Criar a aplicação FastAPIapp = FastAPI(title="LangChain FastAPI", description="API para gerar texto usando LangChain e LangGraph")
      # Ponto de entrada Bem-vindo@app.get("/")async def api_home():"""Ponto de entrada Welcome"""return {"detalhe": "Bem-vindo ao tutorial de FastAPI, Langchain, Docker"}
      # Gerar ponto final@app.post("/gerar")async def generate(request: QueryRequest):"""Ponto final para gerar texto usando o modelo de linguagem    
      Argumentos:solicitação: QueryRequestquery: strthread_id: str = "padrão"
      Retorna:um dicionário contendo o texto gerado e o ID do fio"""tente:# Configurar o ID da threadconfig = {"configurable": {"thread_id": request.thread_id}}        
      # Criar a mensagem de entradainput_messages = [HumanMessage(content=request.query)]        
      # Invocar o gráficooutput = graph_app.invoke({"messages": input_messages}, config)        
      # Obter a resposta do modeloresposta = output["messages"][-1].conteúdo        
      return {"generated_text": resposta,"thread_id": request.thread_id}except Exception as e:raise HTTPException(status_code=500, detail=f"Erro ao gerar texto: {str(e)}")
      if __name__ == "__main__":import uvicornuvicorn.run(app, host="0.0.0.0", port=7860)```
      

Dockerfilelink image 110

Agora vemos como criar o Dockerfile

Primeiro indicamos a partir de qual imagem vamos começar

FROM python:3.13-slim```
      

Agora criamos o diretório de trabalho

RUN useradd -m -u 1000 userWORKDIR /app```
      

Copiamos o arquivo com as dependências e instalamos

COPY --chown=user ./requirements.txt requirements.txtRUN pip install --no-cache-dir --upgrade -r requirements.txt```
      

Copiamos o resto do código

COPY --chown=user . /app```
      

Exponhamos o porto 7860

EXPOSE 7860```
      

Criamos as variáveis de ambiente

RUN --mount=type=secret,id=HUGGINGFACE_TOKEN,mode=0444,required=true \test -f /run/secrets/HUGGINGFACE_TOKEN && echo "Segredo existe!"```
      

Por último, indicamos o comando para executar a aplicação

CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]```
      

Agora colocamos tudo junto

FROM python:3.13-slim
      RUN useradd -m -u 1000 userWORKDIR /app
      COPY --chown=user ./requirements.txt requirements.txtRUN pip install --no-cache-dir --upgrade -r requirements.txt
      COPY --chown=user . /app
      EXPOSE 7860
      RUN --mount=type=secret,id=HUGGINGFACE_TOKEN,mode=0444,required=true \test -f /run/secrets/HUGGINGFACE_TOKEN && echo "Segredo existe!"
      CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]```
      

requirements.txtlink image 111

Criamos o arquivo com as dependências

txt
      fastapiuvicornpedidospydantic>=2.0.0langchainlangchain-huggingfacelangchain-corelanggraph > 0.2.27python-dotenv.2.11```

README.mdlink image 112

Por fim, criamos o arquivo README.md com informações sobre o espaço e as instruções para o HuggingFace.

---título: Backend do SmolLM2emoji: 📊colorFrom: amarelocolorTo: vermelhosdk: dockerpinned: falselicença: apache-2.0short_description: Backend do chat SmolLM2app_port: 7860---
      # Backend do SmolLM2
      Este projeto implementa uma API FastAPI que usa LangChain e LangGraph para gerar texto com o modelo Qwen2.5-72B-Instruct do HuggingFace.
      ## Configuração
      ### No HuggingFace Spaces
      Este projeto está projetado para ser executado em HuggingFace Spaces. Para configurá-lo:
      1. Crie um novo Espaço no HuggingFace com o SDK Docker2. Configure a variável de ambiente `HUGGINGFACE_TOKEN` ou `HF_TOKEN` na configuração do Space:- Vá para a aba "Configurações" do seu Espaço- Role para a seção "Secrets do repositório"- Adicione uma nova variável com o nome `HUGGINGFACE_TOKEN` e seu token como valor- Salve as alterações
      ### Desenvolvimento local
      Para o desenvolvimento local:
      1. Clone este repositório2. Crie um arquivo `.env` na raiz do projeto com seu token do HuggingFace:```
      ```HUGGINGFACE_TOKEN=seu_token_aqui```
      ```3. Instale as dependências:```
      ```pip install -r requirements.txt```
      Por favor, forneça o texto em Markdown que você gostaria de traduzir para o português.
      

Execução locallink image 113

``bashuvicorn app:app --reload``` Por favor, forneça o texto em Markdown que você gostaria de traduzir para o português.

A API estará disponível em `http://localhost:8000`.
      ## Endpoints
      ### GET `/`
      Ponto final de boas-vindas que retorna uma mensagem de saudação.
      ### POST `/gerar`
      Ponto final para gerar texto usando o modelo de linguagem.
      **Parâmetros da solicitação:**``json{"query": "Sua pergunta aqui","thread_id": "identificador_de_thread_opcional"}```
      Por favor, forneça o texto em markdown que você gostaria de traduzir para o português.

Resposta:``json{"Texto gerado pelo modelo""thread_id": "identificador do thread"} Por favor, forneça o texto em Markdown que deseja traduzir para o português.

## Docker
      Para executar a aplicação em um contêiner Docker:
      ``bash# Construa a imagemdocker build -t smollm2-backend .
      # Executar o contêinerdocker run -p 8000:8000 --env-file .env smollm2-backend```

Documentação da APIlink image 114

A documentação interativa da API está disponível em:- Swagger UI: http://localhost:8000/docs- ReDoc: `http://localhost:8000/redoc%60%60%60%60

Token do HuggingFacelink image 115

Se você notou no código e no Dockerfile, usamos um token do HuggingFace, então vamos ter que criar um. Em nossa conta do HuggingFace, criamos um novo token, damos um nome a ele e concedemos as seguintes permissões:

  • Acesso de leitura aos conteúdos de todos os repositórios sob o seu namespace pessoal* Acesso de leitura aos conteúdos de todos os repositórios sob seu namespace pessoal* Fazer chamadas para provedores de inferência* Fazer chamadas para Pontos de Extremidade de Inferência

backend docker - token

Adicionar o token aos secrets do espaçolink image 116

Agora que já temos o token, precisamos adicioná-lo ao espaço. Na parte superior do aplicativo, poderemos ver um botão chamado Settings, clicamos nele e poderemos ver a seção de configuração do espaço. Se formos para baixo, poderemos ver uma seção onde podemos adicionar Variables e Secrets. Neste caso, como estamos adicionando um token, vamos adicioná-lo aos Secrets. Damos o nome HUGGINGFACE_TOKEN e o valor do token.

Implantaçãolink image 117

Se nós clonamos o espaço, temos que fazer um commit e um push. Se modificamos os arquivos no HuggingFace, basta salvá-los. Então, quando as alterações estiverem no HuggingFace, teremos que esperar alguns segundos para que o espaço seja construído e possamos usá-lo. Neste caso, construímos apenas um backend, portanto o que vamos ver ao entrar no espaço é o que definimos no endpoint / backend docker - espaço

URL do backendlink image 118

Precisamos saber a URL do backend para poder fazer chamadas à API. Para isso, temos que clicar nos três pontos no canto superior direito para ver as opções. backend docker - opções

No menu suspenso, clicamos em Embed this Spade. Será aberta uma janela indicando como incorporar o espaço com um iframe e também fornecerá a URL do espaço. backend docker - embed

Se agora formos para essa URL, veremos o mesmo que no espaço.

Documentaçãolink image 119

FastAPI, além de ser uma API extremamente rápida, tem outra grande vantagem: gera documentação automaticamente.

Se adicionarmos /docs à URL que vimos anteriormente, poderemos visualizar a documentação da API com o Swagger UI. backend docker - swagger doc

Também podemos adicionar /redoc à URL para ver a documentação com ReDoc. backend docker - redoc doc

Teste da APIlink image 120

O bom da documentação Swagger UI é que nos permite testar a API diretamente do navegador.

Adicionamos /docs à URL que obtivemos, abrimos o menu suspenso do endpoint /generate e clicamos em Try it out, modificamos o valor da query e do thread_id e clicamos em Execute. No primeiro caso vou colocar

  • query: Olá, como você está? Sou Máximo* thread_id: user1

backend docker - test API

Recebemos a seguinte resposta Olá Máximo! Estou muito bem, obrigado por perguntar. Como você está? Em que posso ajudar hoje? backend docker -response 1 - user1

Vamos testar agora a mesma pergunta, mas com um thread_id diferente, neste caso user2. backend docker - query 1 - user2

E nos responde isso Olá Luis! Estou muito bem, obrigado por perguntar. Como você está? No que posso ajudar hoje? backend docker - response 1 - user2

Agora pedimos nosso nome com os dois usuários e obtemos isso

  • Para o usuário user1: Você se chama Máximo. Há algo mais em que eu possa ajudar você?* Para o usuário user2: Você se chama Luis. Há mais alguma coisa em que eu possa ajudá-lo hoje, Luis?

backend docker - response 2 - user1 backend docker - response 2 - user2

Deploy do backend com Gradio e modelo rodando no servidorlink image 121

Os dois backends que criamos na verdade não estão executando um modelo, mas sim fazendo chamadas para Inference Endpoints da HuggingFace. Mas pode ser que queiramos que tudo rode no servidor, inclusive o modelo. Pode ser que você tenha feito um fine-tuning de um LLM para seu caso de uso, por isso já não pode fazer chamadas para Inference Endpoints. Então vamos ver como modificar o código dos dois backends para executar um modelo no servidor e não fazer chamadas para Inference Endpoints.

Criar Espaçolink image 122

Na hora de criar o space no HuggingFace fazemos o mesmo que antes, criamos um novo space, colocamos um nome e uma descrição, selecionamos Gradio como SDK, selecionamos o HW em que vamos deployar, no meu caso selecionei o HW mais básico e gratuito, e selecionamos se o faremos privado ou público.

Códigolink image 123

Temos que fazer alterações em app.py e em requirements.txt para que, em vez de fazer chamadas a Inference Endpoints, o modelo seja executado localmente.

app.pylink image 124

As mudanças que temos que fazer são

Importar AutoModelForCausalLM e AutoTokenizer da biblioteca transformers e importar torch

from transformers import AutoModelForCausalLM, AutoTokenizerimport torch```
      

Em vez de criar um modelo com InferenceClient, criamos com AutoModelForCausalLM e AutoTokenizer.

# Carregar o modelo e o tokenizermodel_name = "HuggingFaceTB/SmolLM2-1.7B-Instruct"tokenizer = AutoTokenizer.from_pretrained(model_name)model = AutoModelForCausalLM.from_pretrained(nome_do_modelo,torch_dtype=torch.float16,device_map="auto")```
      
      Utilizo `HuggingFaceTB/SmolLM2-1.7B-Instruct` porque é um modelo bastante capaz com apenas 1.7B de parâmetros. Como escolhi o hardware mais básico, não posso usar modelos muito grandes. Você, se quiser usar um modelo maior, tem duas opções: usar o hardware gratuito e aceitar que a inferência será mais lenta, ou usar um hardware mais potente, mas pago.
      

Modificar a função respond para que construa o prompt com a estrutura necessária pela biblioteca transformers, tokenizar o prompt, fazer a inferência e destokenizar a resposta.

def responder(mensagem,histórico: list[tuple[str, str]],Mensagem do sistema,max_tokens,temperatura,top_p,):# Construir o prompt com o formato corretoprompt = f"<|system|>\n{system_message}</s>\n"    
      for val in history:if val[0]:prompt += f"<|user|>\n{val[0]}</s>\n"if val[1]:prompt += f"<|assistant|>\n{val[1]}</s>\n"    
      prompt += f"<|user|>\n{message}</s>\n<|assistant|>\n"    
      # Tokenizar o promptinputs = tokenizer(prompt, return_tensors="pt").to(model.device)    
      # Gerar a respostaoutputs = model.generate(**entradas,**max_new_tokens=max_tokens,temperature=temperature,top_p=top_p,do_sample=True,pad_token_id=tokenizer.eos_token_id)    
      # Decodificar a respostaresponse = tokenizer.decode(outputs[0], skip_special_tokens=True)    
      # Extrair apenas a parte da resposta do assistenteresponse = response.split("<|assistant|>\n")[-1].strip()    
      yield response```
      

A seguir deixo todo o código

import gradio as grfrom transformers import AutoModelForCausalLM, AutoTokenizerimport torch
      """"""Para mais informações sobre o suporte à API de Inferência do `huggingface_hub`, consulte a documentação: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference""""""
      # Carregar o modelo e o tokenizermodel_name = "HuggingFaceTB/SmolLM2-1.7B-Instruct"tokenizer = AutoTokenizer.from_pretrained(model_name)model = AutoModelForCausalLM.from_pretrained(nome_do_modelo,torch_dtype=torch.float16,device_map="auto")
      def responder(mensagem,história: list[tuple[str, str]],Mensagem do sistema,max_tokens,temperatura,top_p,):# Construir o prompt com o formato corretoprompt = f"<|system|>\n{system_message}</s>\n"    
      for val in history:if val[0]:prompt += f"<|user|>\n{val[0]}</s>\n"if val[1]:prompt += f"<|assistant|>\n{val[1]}</s>\n"    
      prompt += f"<|user|>\n{message}</s>\n<|assistant|>\n"    
      # Tokenizar o promptinputs = tokenizer(prompt, return_tensors="pt").to(model.device)    
      # Gerar a respostasaídas = modelo.gerar(**entradas,**max_new_tokens=max_tokens,temperature=temperature,top_p=top_p,do_sample=True,pad_token_id=tokenizer.eos_token_id)    
      # Decodificar a respostaresponse = tokenizer.decode(outputs[0], skip_special_tokens=True)    
      # Extrair apenas a parte da resposta do assistenteresponse = response.split("<|assistant|>\n")[-1].strip()    
      yield response
      
      """"""Para informações sobre como personalizar o ChatInterface, consulte a documentação do Gradio: https://www.gradio.app/docs/chatinterface""""""demo = gr.ChatInterface(responda,```markdown
      additional_inputs=[
      ```gr.Textbox(value="Você é um Chatbot amigável. Sempre responda na língua em que o usuário está escrevendo para você."rótulo="Mensagem do sistema"),gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Máximo de novos tokens"),gr.Slider(mínimo=0,1, máximo=4,0, valor=0,7, passo=0,1, rótulo="Temperatura"),gr.Slider()mínimo=0.1,máximo=1.0,value=0.95,passo=0.05,label="Top-p (amostragem do núcleo)"),],)
      
      if __name__ == "__main__":demo.launch()```
      

requirements.txtlink image 125

Neste arquivo, devemos adicionar as novas bibliotecas que vamos utilizar, neste caso transformers, accelerate e torch. O arquivo completo ficaria:

txt
      huggingface_hub==0.25.2gradio>=4.0.0transformers>=4.36.0torch>=2.0.0accelerate>=0.25.0```

Teste da APIlink image 126

Desplegamos o space e testamos diretamente a API.

	
from gradio_client import Client
client = Client("Maximofn/SmolLM2_localModel")
result = client.predict(
message="Hola, ¿cómo estás? Me llamo Máximo",
system_message="You are a friendly Chatbot. Always reply in the language in which the user is writing to you.",
max_tokens=512,
temperature=0.7,
top_p=0.95,
api_name="/chat"
)
print(result)
Copy
	
Loaded as API: https://maximofn-smollm2-localmodel.hf.space ✔
Hola Máximo, soy su Chatbot amable y estoy funcionando bien. Gracias por tu mensaje, me complace ayudarte hoy en día. ¿Cómo puedo servirte?

Surpreende-me o quão rápido o modelo responde, mesmo estando em um servidor sem GPU.

Deploy de backend com FastAPI, Langchain e Docker e modelo rodando no servidorlink image 127

Agora fazemos o mesmo que antes, mas com FastAPI, LangChain e Docker.

Criar Espaçolink image 128

Ao criar o space no HuggingFace, fazemos o mesmo que antes: criamos um novo espaço, colocamos um nome e uma descrição, selecionamos Docker como SDK, escolhemos o HW em que vamos implantá-lo, no meu caso, escolho o HW mais básico e gratuito, e decidimos se o faremos privado ou público.

Códigolink image 129

app.pylink image 130

Já não importamos InferenceClient e agora importamos AutoModelForCausalLM e AutoTokenizer da biblioteca transformers e importamos torch.

from transformers import AutoModelForCausalLM, AutoTokenizerimport torch```
      

Instanciamos o modelo e o tokenizer com AutoModelForCausalLM e AutoTokenizer.

# Inicialize o modelo e o tokenizadorprint("Carregando modelo e tokenizer...")dispositivo = "cuda" if torch.cuda.is_available() else "cpu"model_name = "HuggingFaceTB/SmolLM2-1.7B-Instruct"
      tente:# Carregar o modelo no formato BF16 para melhor desempenho e menor uso de memóriatokenizer = AutoTokenizer.from_pretrained(model_name)    
      if device == "cuda":print("Usando GPU para o modelo...")model = AutoModelForCausalLM.from_pretrained(nome_do_modelo,torch_dtype=torch.bfloat16,device_map="auto",low_cpu_mem_usage=True)else:print("Usando CPU para o modelo...")model = AutoModelForCausalLM.from_pretrained(nome_do_modelo,device_map={"": device},torch_dtype=torch.float32)
      print(f"Modelo carregado com sucesso em: {device}")except Exception as e:print(f"Erro ao carregar o modelo: {str(e)}")aumentar```
      

Re definimos a função call_model para que faça a inferência com o modelo local.

# Defina a função que chama o modelodef chamar_modelo(estado: EstadoMensagens):"""Chame o modelo com as mensagens fornecidas
      Argumentos:estado: EstadoMensagens
      Retorna:dicionário: Um dicionário contendo o texto gerado e o ID do thread""""""# Converter mensagens LangChain para formato de bate-papomensagens = []for msg in state["messages"]:if isinstance(msg, HumanMessage):messages.append({"role": "user", "content": msg.content})elif isinstance(msg, AIMessage):messages.append({"role": "assistant", "content": msg.content})    
      # Prepare o input usando o modelo de bate-papoinput_text = tokenizer.apply_chat_template(messages, tokenize=False)inputs = tokenizer.encode(input_text, return_tensors="pt").to(device)    
      # Gerar respostasaídas = modelo.gerar(entradas,max_new_tokens=512,  # Aumente o número de tokens para respostas mais longastemperature=0.7,top_p=0,9,do_sample=True,pad_token_id=tokenizer.eos_token_id)    
      # Decodificar e limpar a respostaresponse = tokenizer.decode(outputs[0], skip_special_tokens=True)# Extrair apenas a resposta do assistente (após a última mensagem do usuário)response = response.split("Assistant:")[-1].strip()    
      # Converter a resposta para o formato LangChain```markdown
      ai_message = AIMessage(content=response)
      ```return {"messages": state["messages"] + [ai_message]}```
      

requirements.txtlink image 131

Temos que remover langchain-huggingface e adicionar transformers, accelerate e torch no arquivo requirements.txt. O arquivo ficaria:

txt
      fastapiuvicornsolicitaçõespydantic>=2.0.0langchain>=0.1.0langchain-core>=0.1.10langgraph>=0.2.27python-dotenv>=1.0.0transformers>=4.36.0torch>=2.0.0accelerate>=0.26.0```

Dockerfilelink image 132

Já não precisamos ter RUN --mount=type=secret,id=HUGGINGFACE_TOKEN,mode=0444,required=true porque como o modelo vai estar no servidor e não vamos fazer chamadas para Inference Endpoints, não precisamos do token. O arquivo ficaria:

FROM python:3.13-slim
      RUN useradd -m -u 1000 userWORKDIR /app
      COPY --chown=user ./requirements.txt requirements.txtRUN pip install --no-cache-dir --upgrade -r requirements.txt
      COPY --chown=user . /app
      EXPOSE 7860
      CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]```
      

Teste da APIlink image 133

Deployamos o space e testamos a API. Neste caso, vou testar diretamente do Python.

	
import requests
url = "https://maximofn-smollm2-backend-localmodel.hf.space/generate"
data = {
"query": "Hola, ¿cómo estás?",
"thread_id": "user1"
}
response = requests.post(url, json=data)
if response.status_code == 200:
result = response.json()
print("Respuesta:", result["generated_text"])
print("Thread ID:", result["thread_id"])
else:
print("Error:", response.status_code, response.text)
Copy
	
Respuesta: system
You are a friendly Chatbot. Always reply in the language in which the user is writing to you.
user
Hola, ¿cómo estás?
assistant
Estoy bien, gracias por preguntar. Estoy muy emocionado de la semana que viene.
Thread ID: user1

Este demora um pouco mais que o anterior. Na verdade, demora o normal para um modelo sendo executado em um servidor sem GPU. O estranho é quando o deployamos no Gradio. Não sei o que a HuggingFace faz por trás, ou talvez tenha sido coincidência.

Conclusõeslink image 134

Vimos como criar um backend com um LLM, tanto fazendo chamadas ao Inference Endpoint da HuggingFace, quanto fazendo chamadas a um modelo rodando localmente. Vimos como fazer isso com Gradio ou com FastAPI, Langchain e Docker.

A partir daqui você tem o conhecimento para poder implantar seus próprios modelos, mesmo que não sejam LLMs, podem ser modelos multimodais. A partir daqui você pode fazer o que quiser.

-->

Continuar lendo

Últimos posts -->

Você viu esses projetos?

Subtify

Subtify Subtify

Gerador de legendas para vídeos no idioma que você desejar. Além disso, coloca uma legenda de cor diferente para cada pessoa

Ver todos os projetos -->

Quer aplicar IA no seu projeto? Entre em contato!

Quer melhorar com essas dicas?

Últimos tips -->

Use isso localmente

Os espaços do Hugging Face nos permitem executar modelos com demos muito simples, mas e se a demo quebrar? Ou se o usuário a deletar? Por isso, criei contêineres docker com alguns espaços interessantes, para poder usá-los localmente, aconteça o que acontecer. Na verdade, se você clicar em qualquer botão de visualização de projeto, ele pode levá-lo a um espaço que não funciona.

Flow edit

Flow edit Flow edit

Edite imagens com este modelo de Flow. Baseado em SD3 ou FLUX, você pode editar qualquer imagem e gerar novas

FLUX.1-RealismLora

FLUX.1-RealismLora FLUX.1-RealismLora
Ver todos os contêineres -->

Quer aplicar IA no seu projeto? Entre em contato!

Você quer treinar seu modelo com esses datasets?

short-jokes-dataset

Dataset com piadas em inglês

opus100

Dataset com traduções de inglês para espanhol

netflix_titles

Dataset com filmes e séries da Netflix

Ver mais datasets -->