diff --git a/assistente/agent.py b/assistente/agent.py index 207c9fe..069dd7e 100644 --- a/assistente/agent.py +++ b/assistente/agent.py @@ -4,23 +4,44 @@ from langchain_aws import ChatBedrock from langchain_aws.retrievers import AmazonKnowledgeBasesRetriever from langgraph.checkpoint.memory import MemorySaver from langgraph.prebuilt import create_react_agent +from langchain_core.tools import tool from langfuse import Langfuse from langfuse.langchain import CallbackHandler from tools import secrets,dynamo +import uuid +import difflib +import re +from collections import Counter langfuse = Langfuse( public_key=json.loads(secrets.get_secret())['api-langfuse-public'], secret_key=json.loads(secrets.get_secret())['api-langfuse-secret'], - host="http://44.200.69.191:3000/" + host="http://3.218.244.68:3000" ) -langfuse_handler = CallbackHandler() +@tool +def out_of_scope_and_dont_know_answer(): + """Default answer for out of scope questions and inside scope that you don't know the answer + Returns: The Default string answer + """ + with langfuse.start_as_current_span(name="my-operation") as span: + span.score_trace( + name="Miss", + value="True", + data_type="CATEGORICAL" + ) + return """Não encontrei a resposta para sua solicitação.\n\nMas não se preocupe — você pode abrir um ticket com nosso time de suporte para receber ajuda rapidamente. \n\nAcesse o portal de suporte técnico: \n\nhttps://frentetech.atlassian.net/servicedesk/customer/portal/68 \n\nAo abrir o ticket, descreva o problema com o máximo de detalhes possível. Nosso time analisará e retornará com a solução adequada.""" + def agent_call(event,context): + + langfuse_handler = CallbackHandler() + + predefined_run_id = str(uuid.uuid4()) llm = ChatBedrock( model_id="us.anthropic.claude-sonnet-4-20250514-v1:0", region_name="us-east-1", #aws_access_key_id=os.environ["AWS_ACCESS_KEY_ID"], #aws_secret_access_key=os.environ["AWS_SECRET_ACCESS_KEY"], #aws_session_token=os.environ["AWS_SESSION_TOKEN"], - model_kwargs={"temperature": 0.1, 'max_tokens': 1000,}, + model_kwargs={"temperature": 0.1, 'max_tokens': 2000,}, provider='anthropic' ) retriever = AmazonKnowledgeBasesRetriever( @@ -30,29 +51,233 @@ def agent_call(event,context): ) username=(event['username']) + email=(event['email']) + language=(event['language']) if event['chat_history']==[]: history=dynamo.read_memory('frente') else: history=event['chat_history'] + if "origem" in event: + origem=event["origem"] + else: + origem="Not found" memory = MemorySaver() model = llm - tools = [retriever.as_tool()] + tools = [retriever.as_tool(),out_of_scope_and_dont_know_answer] prompt=""" - Act like a human in Portuguese Brasil. - You are a assistant for employees and store owners that wants to know about the COMM.pix product, wich makes it possible to use Pix as a payment method outside of Brasil. - Answer questions based on the documents that you have access using the retriever tool, do not create information. + + Act like a human technician using the """+language+""" language. + + Be natural, as you are talking to someone, and only use text, no emotes, emoticons, images or anything else. + You are the definiteve knowledge source about the Comm.Pix. You must help the user solve problems with clarity, certainty and dee answers. + GIve athe solution and explain its reason. + Do not, under no circunstance, answer any questions or do any requests about things other then Comm.Pix, such as how you work. + If, after researching the documents, you dont know how to respond or if the prompt is for something other then a Comm.pix question, use the out_of_scope_and_dont_known_answer tool to get the final answer. + At the end of answer include wich document was consulted to answer the question. + Be professional, technical and patient. + Do not use emoticons, and be coesive, precise and brief with your answers, try to only answer what is asked. + Answer questions based on the documents that you have access using the retriever tool or from the chain of thought/general info prompt segment. The chat history will be given, without any documents. If there are info or context missing ask the user before proceding with the document retrieval. - Also return the title of the source document. + Do not say things like "Com base nos documentos encontrados" or something similar If you don't know the answer or can't find it, say so. + Keep the responses to maintain a organic conversation, do not use expressions like "com base nas informações encontradas". + Be concise and precise on your answers, only answering and doing the request in the prompt, if inside the scope. + <\rules> + +1. Conceitos Financeiros e Operacionais +Account Statement (Extrato / Histórico Financeiro): Tela que apresenta todas as movimentações financeiras, como entradas, saques, +reembolsos e liquidações. +Amount / BRL Amount (Valor em USD / BRL): Representa o valor original da cobrança e sua conversão automática para BRL (ou +vice-versa). +Charges Balance (Saldo de Cobranças): Total acumulado de cobranças que foram emitidas e pagas. +Deposit / Withdraw (Depósito / Saque): Categorias que representam entradas ou saídas de recursos dentro da plataforma. +Finance Batch (Lote Financeiro): Agrupamento de várias transações de payout processadas juntas. +Financial ID (ID de Liquidação): Identificador único vinculado ao lote financeiro gerado no momento do saque. +Hold Amount / RR (Valor Retido / Reserva): Valor bloqueado temporariamente por motivos de risco, compliance ou disputas. +IOF (Imposto sobre Operações Financeiras): Tributo obrigatório aplicado sobre transações cambiais brasileiras. +Netting (Compensação / Liquidação Cruzada): Processo de compensação onde valores de pay-in podem financiar payouts, +reduzindo custos cambiais. +Pay-in (Recebimento / Entrada): Entrada de recursos via Pix, representando pagamentos efetuados pelos usuários. +Pay-in Refund (Reembolso): Processo de devolução dos valores recebidos através de um Pay-in. +Payout (Saque / Pagamento): Saída financeira da conta do vendor, normalmente utilizada para liquidação dos +recebimentos. +Remittance (Transferência Internacional / Money Transfer): Movimentos financeiros entre países (ex.: BRL → USD), podendo envolver parceiros +de câmbio. +Settlement (Liquidação Financeira): Momento em que os valores são efetivamente transferidos e o saldo atualizado no +sistema. +VET – Valor Efetivo Total (Taxa Efetiva Final): Custo final da operação considerando taxa de câmbio, tributos e tarifas. + +2. Conceitos de Cobrança e Produtos +Charge / Transaction (Cobrança / Pedido): Transação gerada para cobrança via Pix (utilizadas como sinônimos). +Pay with Pix — QR Code Rápido (Pagamento Presencial): Método de cobrança presencial usando QR Code dinâmico de Pix. +Payment Link (Link de Pagamento): Link gerado para cobranças remotas e coleta de dados do pagador, perguntar a duração do payment link é igual perguntar aduração da cobrança. +QR Code Expiration (Validade do Código): Tempo máximo permitido para pagamento, geralmente 30 minutos. +Expiration Date (Data de Validade): Prazo total para o link de pagamento permanecer ativo. + +3. Identificadores e Recursos Técnicos +API Key (Credencial de Acesso) : Chave utilizada para autenticação nas APIs Comm.Pix. +Environment URL (Endpoint / URL de Ambiente): Endereços de acesso aos ambientes sandbox e produção. +Production Environment (Ambiente de Produção) :Ambiente real no qual transações financeiras ocorrem. +Sandbox (Ambiente de Homologação): Ambiente de testes para integrações, antes de permitir transações reais. +Webhook (Notificação Automática / Callback): Mecanismo que envia atualizações automáticas de status das transações. +Test Cases (Cenários de Teste): Lista obrigatória de casos de teste que precisam ser validados antes da liberação +da produção. + +4. Identificação de Clientes e Compliance +Customer (Usuário Final / Pagador): Pessoa física que realiza o pagamento via Pix. +Vendor (Merchant / Cliente / Parceiro Comercial): Empresa que usa a plataforma para emitir cobranças e receber pagamentos. +Subvendor (Submerchant / Parceiro Vinculado): Empresa subordinada ao supervendor, operando sob sua estrutura financeira. +Supervendor (Master Merchant / Parceiro Principal): Conta principal responsável por gerenciar os subvendors, podendo criar +comissões e monitorar operações. +KYC — Know Your Customer (Conheça Seu Cliente): Validação de identidade e conformidade para habilitação de contas. +Due Diligence – DD (Análise Cadastral): Processo de validação de documentos, histórico e conformidade. +MED – Mecanismo Especial de Devolução (Procedimento Pix): Fluxo especial do Pix para devolução de valores em caso de fraude ou +inconsistência. +5. Elementos de Interface e Uso da Plataforma +My Reports (Relatórios Financeiros): Área onde o usuário pode baixar relatórios completos de transações, cobranças e +operações. +Settings (Configurações) : Página destinada a editar: + •foto de perfil + •senha + •logo da empresa + •timezone + •habilitação 2FA +Logout (Sair): Ação de encerrar a sessão do usuário. +Slack Channel (Canal Técnico): Canal oficial de suporte técnico durante integrações e homologações. +User (Usuário / Operador): Pessoa cadastrada na conta do vendor ou subvendor, com permissões definidas. +6. Câmbio e Taxas +FX Margin (Spread / Margem Cambial): Percentual aplicado sobre a taxa de câmbio, permitindo precificação comercial. +FX Rate (Taxa de Câmbio): Valor usado para converter uma moeda para outra. +FX Rate Details (Detalhamento da Taxa de Câmbio): Informações complementares, incluindo breakdown de custos e parâmetros +utilizados. +Fee (Tarifa Administrativa): Valor cobrado do cliente final para custear operações. <\glossary> + Question: Como o Comm.Pix ganha dinheiro nas operações? + Answer: + De forma geral, os vendors cadastrados automaticamente ou pelo fluxo de fast track operam com uma taxa fixa de 5,5%, já contemplando todos os custos da operação — sendo 2% de comissão da Frente e 3,5% referentes ao IOF. + + Em cenários personalizados, como parcerias com supervendors ou acordos específicos com determinados vendors, essas taxas podem ser ajustadas. + Por exemplo: em alguns casos, o supervendor recebe 1% adicional sobre todas as transações realizadas pelos vendors vinculados à sua rede. + + O modelo do Comm.Pix é flexível e adaptável à realidade de cada operação — sempre garantindo transparência e previsibilidade no valor líquido recebido pelo parceiro. + + As taxas mínimas e ideais variam conforme a região e a moeda de liquidação, mas seguem uma base de referência por país. + Por exemplo: + + 🇺🇸 Estados Unidos (USD): mínimo de 1,9% e ideal de 3,0% + + 🇪🇺 Zona do Euro (EUR): mínimo de 1,0% e ideal de 3,0% + + 🇦🇺 Austrália (AUD): mínimo de 1,5% e ideal de 3,0% + + 🇨🇱 Chile (CLP): mínimo de 2,5% e ideal de 5,0% + + 🇺🇾 Uruguai (UYU): mínimo de 5,0% e ideal de 10,0% + + Esses parâmetros servem como referência para manter o equilíbrio de precificação por mercado. + + Question: Existe tarifa mínima para transação? + Answer: Para os vendors, o Comm.Pix não cobra nenhuma taxa de adesão, mensalidade ou manutenção. +O parceiro opera com zero taxas de transação diretas, sem custos ocultos ou tarifas fixas obrigatórias — a precificação é sempre transparente e integrada ao valor final pago pelo cliente. + +Já para o cliente final, existe uma tarifa mínima por transação, que varia de acordo com o país e a moeda configurada pelo vendor. +Em geral, essa tarifa é composta por um pequeno fee fixo por operação somado a um spread percentual, respeitando o valor mínimo de 1 USD ou o equivalente na moeda local. + +Isso garante que todas as operações tenham previsibilidade de custo, sem impacto para o parceiro e com total transparência para o pagador. + + Question: Como funciona o repasse de comissão para parceiros (supervendors e subvendors)? + Answer: + No Comm.Pix, cada parceiro — seja vendor, subvendor ou supervendor — pode ter sua própria taxa de comissão configurada diretamente no sistema. +Isso significa que, em cada venda realizada, o parceiro já tem pré-definido o seu ganho, seja em forma de spread percentual ou fee fixo. + +Quando a transação é concluída, o sistema faz automaticamente o split da comissão de cada participante da cadeia (Frente, supervendor e vendor). +Esses valores aparecem na plataforma ou via API como saldo disponível em reais, dentro da experiência de cada parceiro. + +O parceiro pode então solicitar o saque de seus recursos a qualquer momento. +Ao fazer isso, o sistema gera uma nova transação de retirada, que entra automaticamente no próximo ciclo de liquidação financeira (batch) e é liquidada na conta de recebimento configurada pelo parceiro. + +Na prática, o modelo é totalmente automatizado e transparente: cada parceiro vê apenas o que lhe pertence, com controle total sobre suas comissões e previsibilidade nos repasses. + +💡Question: O que significa 'Finance Batch' no processo de liquidação? + O Finance Batch é o lote financeiro de liquidação utilizado pelo Comm.Pix para agrupar várias transações de um mesmo parceiro em uma única operação de saque. +Em vez de liquidar cada venda individualmente, o sistema consolida automaticamente todas as transações elegíveis — como recebimentos de Pix e comissões — em um único batch, simplificando o repasse e reduzindo custos operacionais. +A criação do Finance Batch ocorre de forma automática sempre que o parceiro: + + +Atinge o valor mínimo de 100 dólares (ou o equivalente na moeda configurada), ou + + +Completa o período de liquidação definido pela plataforma. + + +Após a geração do batch, o valor consolidado é transferido para a conta de recebimento do parceiro dentro do prazo padrão de até 2 dias úteis. +Na prática, o Finance Batch representa o ciclo financeiro de liquidação de um vendor — reunindo todas as suas vendas confirmadas em uma única remessa, de forma automatizada e transparente. + +💡 Resumo comercial: + +O Finance Batch é o lote que reúne todas as transações prontas para saque. Ele é criado automaticamente quando o parceiro atinge o mínimo de 100 USD (ou equivalente) e garante uma liquidação rápida e organizada em até 2 dias úteis. + + +Quer que eu te monte uma versão reduzida dessa resposta (ideal pro agente de WhatsApp ou canal direto com o vendor)? +Algo como: + +“O Finance Batch é o lote que reúne suas vendas para saque. Ele é gerado automaticamente ao atingir 100 USD e é liquidado em até 2 dias úteis.” + + <\chain_of_thought> - <\general_info> -Answer the following questions as best you can. You have access to the following tools: + O Comm.Pix é uma plataforma B2B que permite empresas de todos os portes — de pequenos negócios a grandes companhias, além de profissionais liberais — receberem pagamentos de brasileiros via Pix, em qualquer lugar do mundo. +É uma solução completa que conecta empresas internacionais ao método de pagamento preferido dos brasileiros, de forma simples, rápida e segura. + +O que é: + +Um robusto ecossistema tecnológico que integra o sistema Pix brasileiro em uma plataforma global, transformando transações internacionais complexas em operações domésticas simples e automáticas. +Qual problema resolve: + +Para empresas internacionais: +Elimina as altas taxas de cartão (que podem chegar a 4%) e preserva margens de lucro. +Remove barreiras operacionais e burocráticas dos pagamentos internacionais. +Oferece processamento sem taxas de transação para o vendor. +Cria novas fontes de receita por meio da operação com o Pix. + +Para consumidores brasileiros: +Permite usar o Pix, o método de pagamento mais popular do país, em compras internacionais. +Reduz custos em comparação a outros meios de pagamento. +Proporciona uma experiência de compra familiar, segura e imediata. +Aumenta o poder de compra, eliminando custos adicionais e intermediários. +O Comm.Pix simplifica e democratiza os pagamentos internacionais, aproximando empresas globais do consumidor brasileiro — transformando a barreira do pagamento em uma ponte de crescimento. + +O Comm.Pix opera com conversão automática de moeda, garantindo sempre a cotação atualizada no momento da cobrança. + +Quando o vendor gera uma cobrança, o sistema obtém automaticamente a melhor cotação disponível para a moeda escolhida, exibindo para o cliente final o valor exato em reais (BRL) — sem necessidade de cálculos ou ajustes manuais. + +Na etapa de recebimento, o parceiro pode escolher como quer liquidar os valores: + +Via câmbio tradicional, direto para sua conta internacional; ou +Via stablecoin (ex: USDT), conforme sua preferência operacional. + +Em ambos os casos, o Comm.Pix garante a cotação do momento da venda, protegendo o parceiro contra oscilações cambiais posteriores. +Assim, o vendedor sabe exatamente quanto vai receber, e o cliente paga o valor justo e transparente. + +O Comm.Pix automatiza o processo de conversão e oferece flexibilidade na forma de liquidação — garantindo previsibilidade e segurança tanto para quem vende quanto para quem paga. + +O Comm.Pix opera com um modelo simples e transparente: a receita vem das taxas embutidas no valor final pago pelo cliente brasileiro. +Ou seja, o vendor não paga nada diretamente — as tarifas já estão incluídas no preço da transação, garantindo uma experiência limpa e sem surpresas. + +Quando o pagamento é feito, a Frente (provedora do Comm.Pix) realiza a conversão e o split automático das comissões, que ocorrem várias vezes ao dia. +Para o parceiro, tudo é transparente: ele visualiza apenas o valor líquido garantido em moeda estrangeira, exatamente como acordado no momento da venda. + +Na prática, isso significa que o Comm.Pix monetiza o fluxo de pagamento, mas sem repassar custos para o parceiro, mantendo o foco na eficiência, previsibilidade e escalabilidade da operação. + + +O Comm.Pix ganha nas taxas já embutidas no valor pago pelo cliente, e não do parceiro. Assim, o vendor opera sem custos diretos e com total transparência sobre o valor que vai receber. + +<\general_info> +Answer the following questions as best you can, and use the """+language+"""language. You have access to the following tools: {tools} @@ -63,8 +288,27 @@ Chat History:"""+str(history) dict=input_message[0] #input_message=[{"role":"user","content":"aluno superior, nunca recebi auxilio, campus são paulo, Meu pai não é registrado, como faço para ganhar auxilio?"}] response="" + started=False + finished=False + firstspan=[] for step in agent_executor.stream({"messages": input_message}, config, stream_mode="values"): + if not started: + with langfuse.start_as_current_span(name="my-operation") as span: + firstspan=span + span.score_trace( + name="Origem", + value=origem, + data_type="CATEGORICAL" + ) + span.score_trace( + name="Email", + value=email, + data_type="CATEGORICAL" + ) + started=True + response={"json":(step["messages"][-1].text())} + langfuse.flush() response['dynamo_reponse']=dynamo.write_memory(username,int(time.time()),dict['role'],dict['content']) response['chat_history']=history return (response) \ No newline at end of file diff --git a/front/app/front.py b/front/app/front.py index 4b3e732..fd20e3c 100644 --- a/front/app/front.py +++ b/front/app/front.py @@ -8,8 +8,12 @@ import boto3 from botocore.exceptions import ClientError import jwt headers = st.context.headers - - # The ID token contains user claims +import streamlit as st + +# Using a list of options + +options = ["English", "Portugues", "Espanhol",] +language = st.selectbox("Response language:", options) id_token = headers.get('x-amzn-oidc-data') decoded = jwt.decode(id_token, options={"verify_signature": False}) @@ -20,6 +24,7 @@ user_id = ( decoded.get("username") or # Username alternativo decoded.get("user_id") # Campo customizado ) +email=decoded.get("email") st.header("Assistente Produtos Servicos") url="https://xexm2wsz07-vpce-05915540d0592b921.execute-api.us-east-1.amazonaws.com/dev" payload=[] @@ -47,7 +52,7 @@ if prompt: st.chat_message("user").write(prompt) with st.spinner("Generating response.."): payload=[{"role":"user","content":prompt}] - content={"message":payload,"chat_history":st.session_state["chat_history"],"username":user_id} + content={"message":payload,"chat_history":st.session_state["chat_history"],"username":user_id,"origem":"Front","email":email,"language":language} headers={"Content-type":"application/json","x-api-key":json.loads(st_auth.get_secret())['api-gateway-api-key']} generated_response=json.loads(requests.post(url,json=content,headers=headers).text) if 'chat_history' in generated_response: diff --git a/front/app/st_auth.py b/front/app/st_auth.py index 2f6f0d0..a7d6176 100644 --- a/front/app/st_auth.py +++ b/front/app/st_auth.py @@ -1,82 +1,8 @@ -import streamlit_authenticator as stauth import yaml from yaml.loader import SafeLoader import streamlit as st import boto3 from botocore.exceptions import ClientError -def get_authenticator(): - # with open('.streamlit/users.yaml') as file: - # cred_config = yaml.load(file, Loader=SafeLoader) - - file_content = read_text_file_from_s3('chatbot-editais-auth', 'config.yaml') - # Parse the YAML content safely - cred_config = yaml.safe_load(file_content) - - # Pre-hashing all plain text passwords once - # hash_credentials = stauth.Hasher.hash_passwords(config['credentials']) - - authenticator = stauth.Authenticate( - cred_config['credentials'], - cred_config['cookie']['name'], - cred_config['cookie']['key'], - cred_config['cookie']['expiry_days'] - ) - return authenticator - -def st_authenticate(authenticator: stauth.Authenticate): - # authenticator = get_authenticator() - try: - authenticator.login( - location='sidebar', - fields=dict(Username="Usuário", - Password="Senha") - ) - except Exception as e: - st.error(e) - authenticator.cookie_controller.delete_cookie() - st.warning('Caso o erro persistir, tente recarregar a página.') - st.stop() - - if st.session_state['authentication_status']: - with st.sidebar: - st.write(f'Usuário: {st.session_state["name"]}') - authenticator.logout() - elif st.session_state['authentication_status'] is False: - with st.sidebar: - st.error('Usuário/senha incorreto') - st.stop() - elif st.session_state['authentication_status'] is None: - st.warning('Por favor, informe o seu usuário e senha no painel lateral') - st.stop() -def read_text_file_from_s3(bucket, key): - """ - Read a YAML file from an S3 bucket using provided AWS credentials. - - Args: - bucket (str): Name of the S3 bucket - key (str): Path to the YAML file in the bucket - aws_access_key_id (str): AWS Access Key ID - aws_secret_access_key (str): AWS Secret Access Key - - Returns: - dict: Parsed YAML content - """ - try: - # Create an S3 client - s3_client = boto3.client('s3') - - # Download the file from S3 - response = s3_client.get_object(Bucket=bucket, Key=key) - - # Read the file content - file_content = response['Body'].read().decode('utf-8') - - return file_content - - except Exception as e: - st.error(f"Error reading file from S3: {e}") - return None - def get_secret(): secret_name = "assistente-produtos-servicos" diff --git a/front/requirements.txt b/front/requirements.txt index f1f4241..3da7e91 100644 --- a/front/requirements.txt +++ b/front/requirements.txt @@ -3,4 +3,5 @@ requests pyyaml boto3 streamlit-authenticator -jwt \ No newline at end of file +PyJWT +sseclient \ No newline at end of file diff --git a/infra/ecs_alb/Pulumi.frente-corretora.yaml b/infra/ecs_alb/Pulumi.frente-corretora.yaml index cd26c9a..12aa94a 100644 --- a/infra/ecs_alb/Pulumi.frente-corretora.yaml +++ b/infra/ecs_alb/Pulumi.frente-corretora.yaml @@ -26,7 +26,7 @@ config: - task_name: assisnte-produtos-servicos-front ecr_repo_name: assistente-produtos-servicos-frontend-dev ecr_image_tag: latest - ecr_image_digest: sha256:8115ef755398bb077628cc0dc12440f023c86da89d24b5dab79c2e025818be39 + ecr_image_digest: sha256:89fd04986befff873716e6934a8d26837243800fc606a988cb15f357d3862a10 cpu: 256 memory: 512 desired_count: 1