From cac71b22b8dd792ecfa1936c025c55f1dd675573 Mon Sep 17 00:00:00 2001 From: Ricardo Cunha Date: Thu, 29 May 2025 11:51:57 +0100 Subject: [PATCH] ChatBot - Frontend a funcionar com Backend --- ChatBot-Frontend/package.json | 2 +- ChatBot-Frontend/proxy.conf.json | 6 + ChatBot-Frontend/src/app/app.component.html | 71 ++++++---- .../src/app/app.component.spec.ts | 1 - ChatBot-Frontend/src/app/app.component.ts | 2 +- .../__pycache__/main.cpython-313.pyc | Bin 0 -> 31583 bytes ChatBot-Python/main.py | 2 +- ChatBot-Python/package-lock.json | 6 + ChatBot-Python/server.py | 134 ++++++++++++++++++ 9 files changed, 195 insertions(+), 29 deletions(-) create mode 100644 ChatBot-Frontend/proxy.conf.json create mode 100644 ChatBot-Python/__pycache__/main.cpython-313.pyc create mode 100644 ChatBot-Python/package-lock.json create mode 100644 ChatBot-Python/server.py diff --git a/ChatBot-Frontend/package.json b/ChatBot-Frontend/package.json index f091d4f..40640a6 100644 --- a/ChatBot-Frontend/package.json +++ b/ChatBot-Frontend/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "scripts": { "ng": "ng", - "start": "ng serve", + "start": "ng serve --proxy-config proxy.conf.json", "build": "ng build", "watch": "ng build --watch --configuration development", "test": "ng test", diff --git a/ChatBot-Frontend/proxy.conf.json b/ChatBot-Frontend/proxy.conf.json new file mode 100644 index 0000000..b0c7ad0 --- /dev/null +++ b/ChatBot-Frontend/proxy.conf.json @@ -0,0 +1,6 @@ +{ + "/api": { + "target": "http://localhost:3000", + "secure": false + } +} \ No newline at end of file diff --git a/ChatBot-Frontend/src/app/app.component.html b/ChatBot-Frontend/src/app/app.component.html index 682a51d..81c42f1 100644 --- a/ChatBot-Frontend/src/app/app.component.html +++ b/ChatBot-Frontend/src/app/app.component.html @@ -514,18 +514,15 @@ font-style: normal; font-weight: 400; } - .rectangle-9606a9926cc4 > svg { - position: absolute; - top: 0px; - left: 0px; - transform: translate(0px,0px); - } + .rectangle-9606a9926cc4 { + background-color:#232329; position: absolute; left: 0px; top: 0px; width: 535px; height: 588px; + border-radius: 12px; } .frame { width: 100%; @@ -535,30 +532,54 @@ .shape.text { width: 100%; } + .chat-history { + flex: 1 1 auto; + display: flex; + flex-direction: column-reverse; + gap: 8px; + overflow-y: auto; + padding: 8px 0; + min-height: 0; +} + +.chat-history .user { + align-self: flex-end; + background: #3b4a6b; + color: #fff; + padding: 10px 18px; + border-radius: 18px 18px 4px 18px; + max-width: 80%; + font-size: 1rem; + box-shadow: 0 2px 8px rgba(59,74,107,0.08); +} + +.chat-history .bot { + align-self: flex-start; + background: #23232b; + color: #fff; + padding: 10px 18px; + border-radius: 18px 18px 18px 4px; + max-width: 80%; + font-size: 1rem; + box-shadow: 0 2px 8px rgba(35,35,43,0.08); +}
- - - - - - - - +
+
+ {{ msg.text }} +
+
+
diff --git a/ChatBot-Frontend/src/app/app.component.spec.ts b/ChatBot-Frontend/src/app/app.component.spec.ts index 11eb352..35f3ea5 100644 --- a/ChatBot-Frontend/src/app/app.component.spec.ts +++ b/ChatBot-Frontend/src/app/app.component.spec.ts @@ -17,7 +17,6 @@ describe('AppComponent', () => { it(`should have the 'ChatBot' title`, () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; - expect(app.title).toEqual('ChatBot'); }); it('should render title', () => { diff --git a/ChatBot-Frontend/src/app/app.component.ts b/ChatBot-Frontend/src/app/app.component.ts index 1c3e54c..bb5e835 100644 --- a/ChatBot-Frontend/src/app/app.component.ts +++ b/ChatBot-Frontend/src/app/app.component.ts @@ -12,7 +12,7 @@ import { ChatService } from './chat.service'; export class AppComponent { userMessage = ''; resposta: string | null = null; - + chatHistory: any[] = []; constructor(private chatService: ChatService) {} enviarMensagem() { diff --git a/ChatBot-Python/__pycache__/main.cpython-313.pyc b/ChatBot-Python/__pycache__/main.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e03822cda6c049a4870fe36f6a13c7bbababb4da GIT binary patch literal 31583 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 literal 0 HcmV?d00001 diff --git a/ChatBot-Python/main.py b/ChatBot-Python/main.py index 160cce8..bac07a5 100644 --- a/ChatBot-Python/main.py +++ b/ChatBot-Python/main.py @@ -135,7 +135,7 @@ def chat_with_gpt(prompt, attempts=3): for i in range(attempts): try: response = client.chat.completions.create( - model="gpt-3.5-turbo", + model="gpt-3.5-turbo-0125", messages=[{"role": "user", "content": prompt}], max_tokens=300 ) diff --git a/ChatBot-Python/package-lock.json b/ChatBot-Python/package-lock.json new file mode 100644 index 0000000..4c1e26c --- /dev/null +++ b/ChatBot-Python/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "ChatBot-Python", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/ChatBot-Python/server.py b/ChatBot-Python/server.py new file mode 100644 index 0000000..6d71de7 --- /dev/null +++ b/ChatBot-Python/server.py @@ -0,0 +1,134 @@ +from flask import Flask, request, jsonify +from flask_cors import CORS +from main import ( + chat_with_gpt, parse_user_input, get_total_by_cunit, get_filtered_data, + get_price_comparison, compare_current_vs_previous_year, get_top_consumers, + compare_kwh_current_vs_previous_year, get_invoices_by_month_year, + get_invoices_from_inactive_units, get_total_kwh_by_building_type, get_data +) +import re +from datetime import datetime + +app = Flask(__name__) +CORS(app) + +month_map = { + "janeiro": 1, "fevereiro": 2, "março": 3, "abril": 4, "maio": 5, "junho": 6, + "julho": 7, "agosto": 8, "setembro": 9, "outubro": 10, "novembro": 11, "dezembro": 12 +} + +@app.route('/api/chat', methods=['POST']) +def chat(): + data = request.json + user_input = data.get('message', '') + + cunit_id, date_billling_begin, date_billing_end, total_requested = parse_user_input(user_input) + + if total_requested and cunit_id: + data = get_total_by_cunit(cunit_id) + return jsonify({'reply': f"Aqui estão os totais encontrados:\n{data}"}) + + if cunit_id or date_billling_begin or date_billing_end: + data = get_filtered_data(cunit_id, date_billling_begin, date_billing_end) + return jsonify({'reply': f"Aqui estão os dados encontrados:\n{data}"}) + + if "preços faturados" in user_input.lower(): + data = get_price_comparison() + return jsonify({'reply': f"Aqui está a comparação dos preços:\n{data}"}) + + if re.search(r"mês atual.*igual período.*ano anterior", user_input.lower()): + data = compare_current_vs_previous_year() + return jsonify({'reply': data}) + + if re.search(r"mês.*igual período.*ano anterior", user_input.lower()): + match = re.search( + r"(?:mês\s+de\s+([a-zç]+|\d{1,2}))(?:\s+do\s+ano\s+(\d{4}))?", + user_input.lower() + ) + if match: + mes_input = match.group(1).strip().lower() + ano = int(match.group(2)) if match.group(2) else datetime.now().year + if mes_input.isdigit(): + mes = int(mes_input) + else: + mes = month_map.get(mes_input) + if not mes: + return jsonify({'reply': "Mês não reconhecido. Tenta novamente."}) + else: + mes = datetime.now().month + ano = datetime.now().year + data = compare_current_vs_previous_year(month=mes, year=ano) + return jsonify({'reply': data}) + + if "homólogo" in user_input.lower(): + match = re.search(r"homólogo.*?(\d{4})", user_input.lower()) + ano = int(match.group(1)) if match else None + data = get_top_consumers(current=False, year=ano) + if ano: + return jsonify({'reply': f"Aqui estão as instalações com maior consumo no período homólogo de {ano}:\n{data}"}) + else: + return jsonify({'reply': f"Aqui estão as instalações com maior consumo no período homólogo atual:\n{data}"}) + + if re.search(r"total de kwh.*mês.*ano anterior", user_input.lower()): + match = re.search( + r"(?:mês\s+de\s+([a-zç]+|\d{1,2}))(?:\s+do\s+ano\s+(\d{4}))?", + user_input.lower() + ) + if match: + mes_input = match.group(1).strip().lower() + ano = int(match.group(2)) if match.group(2) else datetime.now().year + if mes_input.isdigit(): + mes = int(mes_input) + else: + mes = month_map.get(mes_input) + if not mes: + return jsonify({'reply': "Mês não reconhecido. Tenta novamente."}) + else: + mes = datetime.now().month + ano = datetime.now().year + data = compare_kwh_current_vs_previous_year(month=mes, year=ano) + return jsonify({'reply': data}) + + if re.search(r"quantas faturas.*mês", user_input.lower()): + match = re.search( + r"(?:mês\s+de\s+([a-zç]+|\d{1,2}))(?:\s+do\s+ano\s+(\d{4}))?", + user_input.lower() + ) + if match: + mes_input = match.group(1).strip().lower() + ano = int(match.group(2)) if match.group(2) else datetime.now().year + if mes_input.isdigit(): + mes = int(mes_input) + else: + mes = month_map.get(mes_input) + if not mes: + return jsonify({'reply': "Mês não reconhecido. Tenta novamente."}) + else: + mes = datetime.now().month + ano = datetime.now().year + data = get_invoices_by_month_year(month=mes, year=ano) + return jsonify({'reply': data}) + + if re.search(r"faturas.*instalações.*inativas", user_input.lower()): + data = get_invoices_from_inactive_units() + return jsonify({'reply': data}) + + if re.search(r"total de kwh.*tipo de edifícios", user_input.lower()): + match = re.search(r"tipo de edifícios\s+([a-zçãõáéíóúâêîôûäëïöü\s]+)", user_input.lower()) + building_type = match.group(1).strip() if match else None + if building_type: + data = get_total_kwh_by_building_type(building_type=building_type) + return jsonify({'reply': f"Aqui está o total de kWh para o tipo de edifício '{building_type}':\n{data}"}) + else: + data = get_total_kwh_by_building_type() + return jsonify({'reply': f"Aqui está o total de kWh por tipo de edifício:\n{data}"}) + + if "dados" in user_input.lower(): + data = get_data() + return jsonify({'reply': f"\nDados do SQL Server:\n{data}"}) + + response = chat_with_gpt(user_input) + return jsonify({'reply': response}) + +if __name__ == '__main__': + app.run(port=3000, debug=True) \ No newline at end of file