Feat: Final changes to prompt
This commit is contained in:
@@ -7,7 +7,7 @@ COPY requirements.txt ${LAMBDA_TASK_ROOT}
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
# Copy function code
|
||||
COPY agent.py ${LAMBDA_TASK_ROOT}
|
||||
COPY ./ ${LAMBDA_TASK_ROOT}
|
||||
|
||||
# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
|
||||
CMD ["agent.hello" ]
|
||||
CMD ["agent.agent_call"]
|
||||
@@ -1,37 +1,22 @@
|
||||
import json
|
||||
from langchain_core.tools import tool
|
||||
from langchain.agents.output_parsers import ReActJsonSingleInputOutputParser
|
||||
from langchain_core.prompts import ChatPromptTemplate,MessagesPlaceholder, PromptTemplate
|
||||
from langchain_core.messages import HumanMessage,AIMessage
|
||||
from langchain_core.tools import render_text_description
|
||||
from langchain.chains import create_history_aware_retriever
|
||||
from langchain.chains.combine_documents import create_stuff_documents_chain
|
||||
import langchain.chains
|
||||
from langchain.chains import create_history_aware_retriever
|
||||
from langchain.chains.combine_documents import create_stuff_documents_chain
|
||||
from langchain.agents.format_scratchpad import format_log_to_str
|
||||
from langchain.chains import create_retrieval_chain
|
||||
from langchain_aws import ChatBedrock
|
||||
from langchain_aws.retrievers import AmazonKnowledgeBasesRetriever
|
||||
from langchain.chains import ConversationalRetrievalChain
|
||||
from typing import Union
|
||||
from langchain_core.agents import AgentAction, AgentFinish
|
||||
from langchain.agents.output_parsers import ReActSingleInputOutputParser
|
||||
from langchain.tools import Tool
|
||||
from langgraph.checkpoint.memory import MemorySaver
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
import os
|
||||
|
||||
def find_tool_by_name(tools: list[Tool],tool_name:str):
|
||||
for tool in tools:
|
||||
if tool.name==tool_name:
|
||||
print(tool.name)
|
||||
print("\n\n")
|
||||
return tool
|
||||
raise ValueError(f"Tool with name {tool_name} not found")
|
||||
def hello(event,context):
|
||||
from langfuse import Langfuse
|
||||
from langfuse.langchain import CallbackHandler
|
||||
from tools import secrets,dynamo
|
||||
import time
|
||||
langfuse = Langfuse(
|
||||
public_key=json.loads(secrets.get_secret())['api-langfuse-public'],
|
||||
secret_key=json.loads(secrets.get_secret())['api-langfuse-secret'],
|
||||
host="http://107.20.48.139:3000"
|
||||
)
|
||||
langfuse_handler = CallbackHandler()
|
||||
def agent_call(event,context):
|
||||
llm = ChatBedrock(
|
||||
model_id="arn:aws:bedrock:us-east-1:654654422992:application-inference-profile/glvyppv11ds5",
|
||||
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"],
|
||||
@@ -45,6 +30,10 @@ def hello(event,context):
|
||||
retrieval_config={"vectorSearchConfiguration": {"numberOfResults": 4}},
|
||||
|
||||
)
|
||||
if event['chat_history']==[]:
|
||||
history=dynamo.read_memory(event['username'])
|
||||
else:
|
||||
history=event['chat_history']
|
||||
memory = MemorySaver()
|
||||
model = llm
|
||||
tools = [retriever.as_tool()]
|
||||
@@ -53,18 +42,47 @@ def hello(event,context):
|
||||
Act like a human in Portuguese Brasil.
|
||||
You are a assistant for students from diferent school campuses of the Instituto Federal de São Paulo.
|
||||
Your objective is to answer diferent questions about editais de bolsas, which can be acessed by the AmazonKnowledgeBaseRetriever tool.
|
||||
The editais change based on the student's campus, if he is a superior or médio student, and if he is already receiving any bolsa or not. Get these informations from the user, only prompting one per message to the user, before ansewering any questions.
|
||||
The editais change based on the student's campus, if he is a superior or médio student, and if he is already receiving any type of "Bolsa PAP", not including "Iniciação Cientifica" or "bolsa de extensão" . Get these informations from the user, only prompting one per message to the user, before ansewering any questions.
|
||||
The criteria for every type of "bolsa" is different, look at the editals to check. Been a student, who doesnt have a bolsa for any campi is not enough for any bolsa, so check for the extra conditions.
|
||||
Retrieve the answer from the most recent edital that contemplates this type of student.
|
||||
The chat history will be given, without the previous retrieved editais info.
|
||||
If there are info or context missing ask the user before proceding with the document retrie
|
||||
Also return the title of the source document, with edital number and year, not the file name.val.
|
||||
Document with MTO are from "Campus Matão" and SPO from "Campus São Paulo".
|
||||
Document with MTO are from "Campus Matão", SPO from "Campus São Paulo" and CBT from "Campus Cubatão".
|
||||
If you are prompted after a campus that is not Matão, São Paulo or Cubatão, answer that you can only work with one of these.
|
||||
Don't get information from diferent campus under no circunstance.
|
||||
You cant evaluate if someone can receive a bolsa, only get the info from docs and send them to the procedure in the document.
|
||||
If the prompt is too generic like or too short, like "sim" or "quero bolsa", ask for more context before retrieving from the documents.
|
||||
If the user prompt you about wanting to get or to know more about a bolsa pap, ask wich of them (saúde,moradia,transporte,creche didático-pedagócio) they want to know more.
|
||||
<\rules>
|
||||
<glossary>
|
||||
"não registrado" means trabalhador informal.
|
||||
"banco inter" means "banco intermedium", if a user asks about inter, include in the answer this info.
|
||||
<\glossary>
|
||||
<chain_of_thought>
|
||||
Use these questions as examples:
|
||||
Quando a minha bolsa vai cair?
|
||||
Resposta: Devido a complexidade da estrtura em volta do pagamento das bolsas, não existe um dia fixo, ele tende a variar dependendo do mês.
|
||||
|
||||
Não tenho conta bancária em meu nome, pode ser no nome do meu responsável?
|
||||
Resposta: Não! A conta deve ser aberta no nome do estudante e pode ser em bancos digitais sem que seja necessário sair de casa, fazendo tudo pela internet!
|
||||
|
||||
Posso enviar a Documentação solicitada no Edital por e-mail?
|
||||
Resposta: Não! Documentos enviados por e-mail não serão considerados para análise.
|
||||
|
||||
A comprovação de renda deve ser referente ao qual mês?
|
||||
Resposta: agosto que é o mês mais recente em relação a inscrição.
|
||||
|
||||
Não tenho a Carteira de Trabalho impressa. Serve a digital?
|
||||
Resposta: Sim!
|
||||
|
||||
Na carteira de trabalho consta o salário. Ela substitui o contracheque?
|
||||
Resposta: Não, pois somente no contracheque encontramos o valor da renda BRUTA.
|
||||
|
||||
Trabalhador informal e trabalhador autônomo são sinônimos?
|
||||
Resposta: Não! Trabalhadores informais são os que trabalham por conta própria, NÃO tem CNPJ e geralmente não pagam o carnê do INSS, não tendo nenhum direito trabalhista. Diferente deste, o profissional autônomo geralmente é especializado em algum segmento do mercado e atua por conta própria, geralmente sendo MEI – Micro Empreendedores Individuais e tendo CNPJ.
|
||||
|
||||
<\chain_of_thought>
|
||||
<general_info>
|
||||
Tipos de bolsa:
|
||||
Auxílio Alimentação: É um auxílio financeiro que tem por objetivo garantir e disponibilizar condições de que o estudante usufrua de ao menos uma refeição por dia. É pago mensalmente, e caso o aluno não frequente as aulas todos os dias ele poderá ser oferecido de forma parcial, calculado pela quantidade de dias que o aluno frequenta a aula.
|
||||
@@ -99,13 +117,16 @@ Answer the following questions as best you can. You have access to the following
|
||||
|
||||
{tools}
|
||||
|
||||
Chat History:"""+str(event["chat_history"])
|
||||
Chat History:"""+str(history)
|
||||
|
||||
agent_executor = create_react_agent(model, tools, checkpointer=memory, prompt=prompt)
|
||||
config = {"configurable": {"thread_id": "abc123"}}
|
||||
config = {"configurable": {"thread_id": "abc123"},"callbacks": [langfuse_handler]}
|
||||
input_message = event["message"]
|
||||
#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?"}]
|
||||
dict=input_message[0]
|
||||
response=""
|
||||
for step in agent_executor.stream({"messages": input_message}, config, stream_mode="values"):
|
||||
response={"json":(step["messages"][-1].text())}
|
||||
response['dynamo_reponse']=dynamo.write_memory(event['username'],int(time.time()),dict['role'],dict['content'])
|
||||
#response['chat_history']=history
|
||||
response['chat_history']=[]
|
||||
return (response)
|
||||
@@ -1,74 +0,0 @@
|
||||
import boto3
|
||||
from langchain_core.prompts import ChatPromptTemplate,MessagesPlaceholder
|
||||
from langchain_core.messages import HumanMessage,AIMessage
|
||||
from langchain.chains import create_history_aware_retriever
|
||||
from langchain.chains.combine_documents import create_stuff_documents_chain
|
||||
import langchain.chains
|
||||
from langchain.chains import create_retrieval_chain
|
||||
from langchain_aws import ChatBedrock
|
||||
from langchain_aws.retrievers import AmazonKnowledgeBasesRetriever
|
||||
from langchain.chains import ConversationalRetrievalChain
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
import os
|
||||
llm = ChatBedrock(
|
||||
model_id="arn:aws:bedrock:us-east-1:654654422992:application-inference-profile/d9blf0g3fzqz",
|
||||
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.2, 'max_tokens': 1000,},
|
||||
provider='anthropic'
|
||||
)
|
||||
# Cria o prompt de busca
|
||||
prompt_search_query = ChatPromptTemplate.from_messages([
|
||||
MessagesPlaceholder(variable_name="chat_history"),
|
||||
("user", "{input}"),
|
||||
("assistant", "-"),
|
||||
("user", "Given the above conversation, generate a search query to look up to get information relevant to the conversation")
|
||||
])
|
||||
|
||||
# Cria o prompt de resposta
|
||||
prompt_get_answer = ChatPromptTemplate.from_messages([
|
||||
("system", "Answer the user's questions based on the below context:\n\n{context}"),
|
||||
MessagesPlaceholder(variable_name="chat_history"),
|
||||
("user", "{input}")
|
||||
])
|
||||
|
||||
# Conecta ao Qdrant
|
||||
retriever = AmazonKnowledgeBasesRetriever(
|
||||
knowledge_base_id="RBD9TI5HYU",
|
||||
region_name="us-east-1",
|
||||
retrieval_config={"vectorSearchConfiguration": {"numberOfResults": 4}},
|
||||
|
||||
)
|
||||
# Cria o retriever com histórico
|
||||
retriever_chain = create_history_aware_retriever(llm, retriever, prompt_search_query)
|
||||
|
||||
# Cria o documento chain
|
||||
document_chain = create_stuff_documents_chain(llm, prompt_get_answer)
|
||||
|
||||
# Cria o retrieval chain
|
||||
retrieval_chain= create_retrieval_chain(
|
||||
retriever_chain,document_chain
|
||||
)
|
||||
|
||||
def chat_with_bot(user_input, chat_history):
|
||||
"""
|
||||
Função para interagir com o chatbot.
|
||||
|
||||
Args:
|
||||
user_input (str): A entrada do usuário.
|
||||
chat_history (list): O histórico da conversa, incluindo mensagens do usuário e do assistente.
|
||||
|
||||
Returns:
|
||||
str: A resposta do chatbot.
|
||||
"""
|
||||
# Chama o chain de recuperação com o histórico e a entrada do usuário
|
||||
response = retrieval_chain.invoke({
|
||||
"chat_history": chat_history,
|
||||
"input": user_input,
|
||||
})
|
||||
# Retorna a resposta do assistente
|
||||
return response['answer']
|
||||
print(chat_with_bot("Quanto é o auxilio?",chat_history=[{"role":"user","content":"Hello"}]))
|
||||
1470
agent/poetry.lock
generated
1470
agent/poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,20 +0,0 @@
|
||||
[tool.poetry]
|
||||
name = "agent"
|
||||
version = "0.1.0"
|
||||
description = "Agente edital IFSP"
|
||||
authors = ["Lucas DNX"]
|
||||
readme = "README.md"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.12"
|
||||
langchain-core = "^0.3.75"
|
||||
langchain = "^0.3.27"
|
||||
boto3 = "^1.40.19"
|
||||
langchain-aws = "^0.2.31"
|
||||
dotenv = "^0.9.9"
|
||||
langgraph = "^0.6.7"
|
||||
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
@@ -2,4 +2,5 @@ langchain_core
|
||||
langchain
|
||||
langchain_aws
|
||||
langgraph
|
||||
|
||||
langfuse
|
||||
boto3
|
||||
41
agent/tools/dynamo.py
Normal file
41
agent/tools/dynamo.py
Normal file
@@ -0,0 +1,41 @@
|
||||
import boto3
|
||||
def write_memory(user,timestamp,role,content):
|
||||
dynamodb = boto3.resource('dynamodb')
|
||||
|
||||
table = dynamodb.Table('br-edu-ifsp-ifsp-ret-memoria-tabela-chatbot-editais-dev') # Replace 'YourTableName' with your actual table name
|
||||
|
||||
item_data = {
|
||||
'UserId': user, # Replace with your partition key attribute and value
|
||||
'Timestamp': timestamp, # Replace with your sort key attribute and value (if applicable)
|
||||
'role': role,
|
||||
'content': content
|
||||
}
|
||||
|
||||
try:
|
||||
response = table.put_item(Item=item_data)
|
||||
return response
|
||||
except Exception as e:
|
||||
return "Error adding item:"+str(e)
|
||||
def read_memory(userid):
|
||||
dynamodb = boto3.resource('dynamodb')
|
||||
table = dynamodb.Table('br-edu-ifsp-ifsp-ret-memoria-tabela-chatbot-editais-dev')
|
||||
|
||||
# Query parameters
|
||||
|
||||
try:
|
||||
response = table.query(
|
||||
KeyConditionExpression=boto3.dynamodb.conditions.Key('UserId').eq(userid),
|
||||
ScanIndexForward=False, # Descending order
|
||||
Limit=30 # Get only the latest item
|
||||
)
|
||||
|
||||
items = response.get('Items', [])
|
||||
if items:
|
||||
latest_items = items
|
||||
return latest_items
|
||||
else:
|
||||
return []
|
||||
|
||||
except Exception as e:
|
||||
print("Error querying DynamoDB:", str(e))
|
||||
|
||||
25
agent/tools/secrets.py
Normal file
25
agent/tools/secrets.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import boto3
|
||||
from botocore.exceptions import ClientError
|
||||
def get_secret():
|
||||
|
||||
secret_name = "dev/chatboteditais/apigateway/apikey"
|
||||
region_name = "us-east-1"
|
||||
|
||||
# Create a Secrets Manager client
|
||||
session = boto3.session.Session()
|
||||
client = session.client(
|
||||
service_name='secretsmanager',
|
||||
region_name=region_name
|
||||
)
|
||||
|
||||
try:
|
||||
get_secret_value_response = client.get_secret_value(
|
||||
SecretId=secret_name
|
||||
)
|
||||
except ClientError as e:
|
||||
# For a list of exceptions thrown, see
|
||||
# https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
|
||||
raise e
|
||||
|
||||
secret = get_secret_value_response['SecretString']
|
||||
return secret
|
||||
Reference in New Issue
Block a user