Spaces:
Build error
Build error
Commit
·
3b4b1fb
1
Parent(s):
38451c9
feat: Adicionando funcionalidade de IA para chatbot, incluindo template de mensagem e comportamento de regra.
Browse files- .gitignore +2 -2
- README.md +1 -1
- app.py +44 -26
- data/data.json +30 -0
- prompt_bot.py +34 -0
- requirements.txt +82 -1
- server.py +30 -0
- util/access_token.py +15 -0
- util/extract_data.py +49 -0
- util/import_dataset.py +12 -0
.gitignore
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
venv
|
| 2 |
-
Medflow-Bot
|
| 3 |
.env
|
| 4 |
-
.python-version
|
|
|
|
|
|
| 1 |
venv
|
|
|
|
| 2 |
.env
|
| 3 |
+
.python-version
|
| 4 |
+
__pycache__
|
README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
emoji: 💬
|
| 4 |
colorFrom: yellow
|
| 5 |
colorTo: purple
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Commit-IA
|
| 3 |
emoji: 💬
|
| 4 |
colorFrom: yellow
|
| 5 |
colorTo: purple
|
app.py
CHANGED
|
@@ -1,31 +1,51 @@
|
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
|
|
|
| 2 |
from huggingface_hub import InferenceClient
|
| 3 |
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
|
| 10 |
def respond(
|
| 11 |
-
message,
|
| 12 |
-
history:
|
| 13 |
-
system_message,
|
| 14 |
-
max_tokens,
|
| 15 |
-
temperature,
|
| 16 |
-
top_p,
|
| 17 |
-
):
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
| 19 |
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
|
|
|
| 25 |
|
| 26 |
-
|
| 27 |
|
| 28 |
-
|
|
|
|
| 29 |
|
| 30 |
for message in client.chat_completion(
|
| 31 |
messages,
|
|
@@ -34,19 +54,15 @@ def respond(
|
|
| 34 |
temperature=temperature,
|
| 35 |
top_p=top_p,
|
| 36 |
):
|
| 37 |
-
token = message.choices[0].delta.content
|
| 38 |
-
|
| 39 |
response += token
|
| 40 |
yield response
|
| 41 |
|
| 42 |
|
| 43 |
-
|
| 44 |
-
For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
|
| 45 |
-
"""
|
| 46 |
-
demo = gr.ChatInterface(
|
| 47 |
respond,
|
| 48 |
additional_inputs=[
|
| 49 |
-
gr.Textbox(value="
|
| 50 |
gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
|
| 51 |
gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
|
| 52 |
gr.Slider(
|
|
@@ -57,6 +73,8 @@ demo = gr.ChatInterface(
|
|
| 57 |
label="Top-p (nucleus sampling)",
|
| 58 |
),
|
| 59 |
],
|
|
|
|
|
|
|
| 60 |
)
|
| 61 |
|
| 62 |
|
|
|
|
| 1 |
+
from typing import List, Optional
|
| 2 |
+
|
| 3 |
import gradio as gr
|
| 4 |
+
from datasets import load_dataset
|
| 5 |
from huggingface_hub import InferenceClient
|
| 6 |
|
| 7 |
+
from prompt_bot import prompt_for_template, template_bot
|
| 8 |
+
from util.extract_data import extrair_dados_template
|
| 9 |
+
from util.import_dataset import get_response_from_huggingface_dataset
|
| 10 |
+
|
| 11 |
+
descricao, regras, comportamento = extrair_dados_template()
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
MODEL: str = "meta-llama/Llama-3.2-3B-Instruct"
|
| 15 |
+
|
| 16 |
+
TEMPLATE_BOT = template_bot()
|
| 17 |
+
prompt_template = prompt_for_template(TEMPLATE_BOT)
|
| 18 |
+
|
| 19 |
+
# modify future
|
| 20 |
+
DATASET = load_dataset("wendellast/GUI-Ban")
|
| 21 |
+
|
| 22 |
+
client: InferenceClient = InferenceClient(model=MODEL)
|
| 23 |
|
| 24 |
|
| 25 |
def respond(
|
| 26 |
+
message: str,
|
| 27 |
+
history: List[dict],
|
| 28 |
+
system_message: str,
|
| 29 |
+
max_tokens: int,
|
| 30 |
+
temperature: float,
|
| 31 |
+
top_p: float,
|
| 32 |
+
) -> any:
|
| 33 |
+
response: Optional[str] = get_response_from_huggingface_dataset(message, DATASET)
|
| 34 |
+
if response:
|
| 35 |
+
yield response
|
| 36 |
+
return
|
| 37 |
|
| 38 |
+
prompt: str = prompt_template.format(
|
| 39 |
+
description=descricao,
|
| 40 |
+
regras=regras,
|
| 41 |
+
comportamento=comportamento,
|
| 42 |
+
mensagem=message,
|
| 43 |
+
)
|
| 44 |
|
| 45 |
+
print(prompt)
|
| 46 |
|
| 47 |
+
messages: List[dict] = [{"role": "system", "content": prompt}]
|
| 48 |
+
response: str = ""
|
| 49 |
|
| 50 |
for message in client.chat_completion(
|
| 51 |
messages,
|
|
|
|
| 54 |
temperature=temperature,
|
| 55 |
top_p=top_p,
|
| 56 |
):
|
| 57 |
+
token: str = message.choices[0].delta.content
|
|
|
|
| 58 |
response += token
|
| 59 |
yield response
|
| 60 |
|
| 61 |
|
| 62 |
+
demo: gr.ChatInterface = gr.ChatInterface(
|
|
|
|
|
|
|
|
|
|
| 63 |
respond,
|
| 64 |
additional_inputs=[
|
| 65 |
+
gr.Textbox(value="", label="System message"),
|
| 66 |
gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
|
| 67 |
gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
|
| 68 |
gr.Slider(
|
|
|
|
| 73 |
label="Top-p (nucleus sampling)",
|
| 74 |
),
|
| 75 |
],
|
| 76 |
+
title="Medflow-BOT",
|
| 77 |
+
type="messages",
|
| 78 |
)
|
| 79 |
|
| 80 |
|
data/data.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"template": {
|
| 3 |
+
"description": "Você é uma assistente especializada em escrever mensagens de commit curtas, diretas e bem estruturadas. Suas mensagens seguem boas práticas, são semanticamente claras e comunicam de forma objetiva as alterações realizadas no código.",
|
| 4 |
+
"rules": [
|
| 5 |
+
"A mensagem deve ser baseada no que foi alterado no git diff e descrever as ações feitas.",
|
| 6 |
+
"Use frases curtas e diretas, separando as ações realizadas no commit por vírgulas.",
|
| 7 |
+
"**Fale das alterações do commit, separando com vírgulas e de forma simples e curta.**",
|
| 8 |
+
"Não fale o caminho dos arquivos alterados ou criados.",
|
| 9 |
+
"Não invente mensagens ou coisas que não têm no commit.",
|
| 10 |
+
"**Não use caracteres especiais como crase ou aspas.**",
|
| 11 |
+
"A primeira linha deve começar com o prefixo correto (feat, fix, chore).",
|
| 12 |
+
"Não inclua caminhos completos dos arquivos, apenas nomes principais se necessário.",
|
| 13 |
+
"Utilize obrigatoriamente o idioma **%s** na resposta.",
|
| 14 |
+
"Escreva a mensagem como se fosse em primeira pessoa.",
|
| 15 |
+
"A mensagem tem que ser com palavras curtas, diretas ao ponto, e mencionar todas as alterações feitas.",
|
| 16 |
+
"A saída deve ser **apenas a mensagem de commit final**, sem comentários ou explicações adicionais."
|
| 17 |
+
],
|
| 18 |
+
"behavior": {
|
| 19 |
+
"tone": "Formal, amigável e acessível.",
|
| 20 |
+
"response_style": "Clara e objetiva, com mensagens de commit curtas, diretas e separadas por ação usando vírgulas. Explicações detalhadas apenas quando necessário.",
|
| 21 |
+
"examples": [
|
| 22 |
+
"feat: Adicionando funcionalidade de cadastro de usuários, criando validação de senha, ajustando layout do formulário.",
|
| 23 |
+
"fix: Corrigindo bug na autenticação, ajustando lógica de verificação de tokens.",
|
| 24 |
+
"chore: Renomeando variáveis para maior clareza, removendo comentários desnecessários.",
|
| 25 |
+
"refactor: Melhorando estrutura do código na função de busca, otimizando loops, ajustando nomenclatura.",
|
| 26 |
+
"docs: Atualizando README com instruções de instalação, adicionando seção de contribuições."
|
| 27 |
+
]
|
| 28 |
+
}
|
| 29 |
+
}
|
| 30 |
+
}
|
prompt_bot.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain.prompts import PromptTemplate
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def template_bot() -> str:
|
| 5 |
+
template: str = """
|
| 6 |
+
Descrição:
|
| 7 |
+
- Você é {description}
|
| 8 |
+
- Aqui estão algumas regras que você deve seguir:
|
| 9 |
+
|
| 10 |
+
Regras:
|
| 11 |
+
{regras}
|
| 12 |
+
|
| 13 |
+
se comporte assim:
|
| 14 |
+
{comportamento}
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
Usuário: {mensagem}
|
| 18 |
+
IA-BOT:
|
| 19 |
+
"""
|
| 20 |
+
return template
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def prompt_for_template(template_bot: str) -> str:
|
| 24 |
+
prompt_template: PromptTemplate = PromptTemplate(
|
| 25 |
+
input_variables=[
|
| 26 |
+
"description",
|
| 27 |
+
"regras",
|
| 28 |
+
"comportamento",
|
| 29 |
+
"mensagem",
|
| 30 |
+
],
|
| 31 |
+
template=template_bot,
|
| 32 |
+
)
|
| 33 |
+
|
| 34 |
+
return prompt_template
|
requirements.txt
CHANGED
|
@@ -1 +1,82 @@
|
|
| 1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
aiofiles==23.2.1
|
| 2 |
+
aiohappyeyeballs==2.4.4
|
| 3 |
+
aiohttp==3.11.11
|
| 4 |
+
aiosignal==1.3.2
|
| 5 |
+
annotated-types==0.7.0
|
| 6 |
+
anyio==4.8.0
|
| 7 |
+
async-timeout==4.0.3
|
| 8 |
+
attrs==24.3.0
|
| 9 |
+
blinker==1.9.0
|
| 10 |
+
certifi==2024.12.14
|
| 11 |
+
charset-normalizer==3.4.1
|
| 12 |
+
click==8.1.8
|
| 13 |
+
datasets==3.2.0
|
| 14 |
+
dill==0.3.8
|
| 15 |
+
exceptiongroup==1.2.2
|
| 16 |
+
fastapi==0.115.6
|
| 17 |
+
ffmpy==0.5.0
|
| 18 |
+
filelock==3.16.1
|
| 19 |
+
Flask==3.1.0
|
| 20 |
+
Flask-Cors==5.0.0
|
| 21 |
+
frozenlist==1.5.0
|
| 22 |
+
fsspec==2024.9.0
|
| 23 |
+
gradio==5.12.0
|
| 24 |
+
gradio_client==1.5.4
|
| 25 |
+
greenlet==3.1.1
|
| 26 |
+
h11==0.14.0
|
| 27 |
+
httpcore==1.0.7
|
| 28 |
+
httpx==0.28.1
|
| 29 |
+
huggingface-hub==0.25.2
|
| 30 |
+
idna==3.10
|
| 31 |
+
itsdangerous==2.2.0
|
| 32 |
+
Jinja2==3.1.5
|
| 33 |
+
jsonpatch==1.33
|
| 34 |
+
jsonpointer==3.0.0
|
| 35 |
+
langchain==0.3.14
|
| 36 |
+
langchain-core==0.3.30
|
| 37 |
+
langchain-text-splitters==0.3.5
|
| 38 |
+
langsmith==0.2.11
|
| 39 |
+
markdown-it-py==3.0.0
|
| 40 |
+
MarkupSafe==2.1.5
|
| 41 |
+
mdurl==0.1.2
|
| 42 |
+
multidict==6.1.0
|
| 43 |
+
multiprocess==0.70.16
|
| 44 |
+
numpy==1.26.4
|
| 45 |
+
orjson==3.10.14
|
| 46 |
+
packaging==24.2
|
| 47 |
+
pandas==2.2.3
|
| 48 |
+
pillow==11.1.0
|
| 49 |
+
propcache==0.2.1
|
| 50 |
+
pyarrow==19.0.0
|
| 51 |
+
pydantic==2.10.5
|
| 52 |
+
pydantic_core==2.27.2
|
| 53 |
+
pydub==0.25.1
|
| 54 |
+
Pygments==2.19.1
|
| 55 |
+
python-dateutil==2.9.0.post0
|
| 56 |
+
python-dotenv==1.0.1
|
| 57 |
+
python-multipart==0.0.20
|
| 58 |
+
pytz==2024.2
|
| 59 |
+
PyYAML==6.0.2
|
| 60 |
+
requests==2.32.3
|
| 61 |
+
requests-toolbelt==1.0.0
|
| 62 |
+
rich==13.9.4
|
| 63 |
+
ruff==0.9.2
|
| 64 |
+
safehttpx==0.1.6
|
| 65 |
+
semantic-version==2.10.0
|
| 66 |
+
shellingham==1.5.4
|
| 67 |
+
six==1.17.0
|
| 68 |
+
sniffio==1.3.1
|
| 69 |
+
SQLAlchemy==2.0.37
|
| 70 |
+
starlette==0.41.3
|
| 71 |
+
tenacity==9.0.0
|
| 72 |
+
tomlkit==0.13.2
|
| 73 |
+
tqdm==4.67.1
|
| 74 |
+
typer==0.15.1
|
| 75 |
+
typing_extensions==4.12.2
|
| 76 |
+
tzdata==2024.2
|
| 77 |
+
urllib3==2.3.0
|
| 78 |
+
uvicorn==0.34.0
|
| 79 |
+
websockets==14.1
|
| 80 |
+
Werkzeug==3.1.3
|
| 81 |
+
xxhash==3.5.0
|
| 82 |
+
yarl==1.18.3
|
server.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dotenv import load_dotenv
|
| 2 |
+
from flask import Flask, jsonify, request
|
| 3 |
+
from flask_cors import CORS
|
| 4 |
+
from gradio_client import Client
|
| 5 |
+
|
| 6 |
+
load_dotenv()
|
| 7 |
+
|
| 8 |
+
port = 5003
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
app = Flask(__name__)
|
| 12 |
+
|
| 13 |
+
CORS(app)
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
@app.route("/bot", methods=["POST"])
|
| 17 |
+
def send_message():
|
| 18 |
+
data = request.get_json()
|
| 19 |
+
message = data.get("message")
|
| 20 |
+
|
| 21 |
+
client = Client("wendellast/test")
|
| 22 |
+
result = client.predict(
|
| 23 |
+
message=message, max_tokens=512, temperature=0.7, top_p=0.95, api_name="/chat"
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
return jsonify({"response": result})
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
if __name__ == "__main__":
|
| 30 |
+
app.run(host="0.0.0.0", port=port)
|
util/access_token.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
|
| 3 |
+
from dotenv import load_dotenv
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def load_token(token_env):
|
| 7 |
+
|
| 8 |
+
load_dotenv()
|
| 9 |
+
|
| 10 |
+
token = os.getenv(token_env)
|
| 11 |
+
|
| 12 |
+
if token is None:
|
| 13 |
+
raise ValueError("Token não encontrado no arquivo .env")
|
| 14 |
+
|
| 15 |
+
return str(token)
|
util/extract_data.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
|
| 3 |
+
try:
|
| 4 |
+
with open("data/data.json", "r", encoding="UTF-8") as file:
|
| 5 |
+
data: dict = json.load(file)
|
| 6 |
+
except:
|
| 7 |
+
raise "Error ao carregar config.json"
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def extrair_dados_template(template: dict = data):
|
| 11 |
+
try:
|
| 12 |
+
if "template" not in template:
|
| 13 |
+
raise KeyError("'template' não encontrado no dicionário.")
|
| 14 |
+
|
| 15 |
+
template_data = template["template"]
|
| 16 |
+
|
| 17 |
+
descricao: str = template_data.get("description", "Descrição não disponível.")
|
| 18 |
+
|
| 19 |
+
if "rules" not in template_data:
|
| 20 |
+
raise KeyError("'rules' não encontrado em 'template'.")
|
| 21 |
+
|
| 22 |
+
regras: str = "\n".join([f"- {rule}" for rule in template_data["rules"]])
|
| 23 |
+
|
| 24 |
+
if "behavior" not in template_data:
|
| 25 |
+
raise KeyError("'behavior' não encontrado em 'template'.")
|
| 26 |
+
|
| 27 |
+
comportamento = []
|
| 28 |
+
for key, value in template_data["behavior"].items():
|
| 29 |
+
if key == "examples" and isinstance(value, list):
|
| 30 |
+
exemplos = "\n".join([f" * {ex}" for ex in value])
|
| 31 |
+
comportamento.append(f"- {key.capitalize()}:\n{exemplos}")
|
| 32 |
+
else:
|
| 33 |
+
comportamento.append(f"- {key.capitalize()}: {value}")
|
| 34 |
+
|
| 35 |
+
comportamento_str = "\n".join(comportamento)
|
| 36 |
+
|
| 37 |
+
return descricao, regras, comportamento_str
|
| 38 |
+
|
| 39 |
+
except KeyError as e:
|
| 40 |
+
print(f"Erro ao acessar a chave: {e}")
|
| 41 |
+
return None
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
"""
|
| 45 |
+
descricao, regra, compoa = extrair_dados_template()
|
| 46 |
+
print(descricao)
|
| 47 |
+
print(regra)
|
| 48 |
+
print(compoa)
|
| 49 |
+
"""
|
util/import_dataset.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Optional
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def get_response_from_huggingface_dataset(message: str, DATASET) -> Optional[str]:
|
| 5 |
+
for data in DATASET["train"]:
|
| 6 |
+
if "dialog" in data and len(data["dialog"]) > 1:
|
| 7 |
+
input_text: str = data["dialog"][0].lower()
|
| 8 |
+
response_text: str = data["dialog"][1]
|
| 9 |
+
|
| 10 |
+
if input_text == message.lower():
|
| 11 |
+
return response_text
|
| 12 |
+
return None
|