Add pydantic Object for llm response and rework decision making

This commit is contained in:
robinrolle
2025-04-12 21:51:40 +02:00
parent 94ba43183a
commit 22636070d7
2 changed files with 71 additions and 26 deletions

View File

@ -7,6 +7,10 @@ from dto.requests import GameStartRequestDTO, GameDecisionRequestDTO
from services.extractor import extract_profile, extract_passport, extract_description, extract_account from services.extractor import extract_profile, extract_passport, extract_description, extract_account
from services.julius_baer_api_client import JuliusBaerApiClient from services.julius_baer_api_client import JuliusBaerApiClient
from utils.storage.game_files_manager import store_game_round_data from utils.storage.game_files_manager import store_game_round_data
from langchain_google_genai import ChatGoogleGenerativeAI
from validation.llm_validate import AssistantDecision
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -71,31 +75,73 @@ class Player:
time.sleep(1) time.sleep(1)
def make_decision(self, client_data: Dict[str, Any]) -> Literal["Accept", "Reject"]: def make_decision(self, client_data: Dict[str, Any]) -> Literal["Accept", "Reject"]:
# Data extraction # 1. Extraction des données
profile = extract_profile(client_data) profile = extract_profile(client_data)
passport = extract_passport(client_data) passport = extract_passport(client_data)
description = extract_description(client_data) description = extract_description(client_data)
account = extract_account(client_data) account = extract_account(client_data)
prompt_template = ( # 2. Création du parser
"You are a helpful assistant at a private bank.\n" parser = PydanticOutputParser(pydantic_object=AssistantDecision)
"Your task is to accept or reject a new client's application for private banking.\n\n" format_instructions = parser.get_format_instructions()
"Only reject the application if there is an inconsistency in the data provided.\n"
"Inconsistencies include:\n" # 3. Prompt enrichi
"- Incorrect data (e.g., mismatched or invalid information)\n" prompt = ChatPromptTemplate.from_template(
"- Incomplete data (e.g., missing required fields)\n\n" """You are a compliance analyst in a private bank.
"Return only JSON matching this format:\n" You are given structured data extracted from four different documents of a new client application.
"{format_instructions}\n\n"
"Here is the extracted passport text:\n" Your task is to accept or reject the client's application for private banking.
"{processed_text}\n\n"
"Use the extracted profile, description, and account details to check consistency." Only reject the application if there is an inconsistency in the data provided.
Inconsistencies include:
- Incorrect data (e.g., mismatched or invalid information)
- Incomplete data (e.g., missing required fields)
- Implausible or suspicious details
Use the extracted profile, description, and account details to cross-check the information in the passport and other documents.
Be highly critical. Reject if there's any doubt or if anything feels wrong.
Return only JSON matching this format:
{format_instructions}
---
**Document: Passport**
{passport}
---
**Document: Profile**
{profile}
---
**Document: Description**
{description}
---
**Document: Account**
{account}"""
) )
# You'd insert the format instructions and passport text here before calling the LLM # 4. Chaîne LLM
# For example: chain = prompt | ChatGoogleGenerativeAI(model="gemini-pro") | parser
# final_prompt = prompt_template.format(
# format_instructions=your_format_instructions,
# processed_text=passport['text']
# )
return 'Accept' # Replace me!! # 5. Invocation
result: AssistantDecision = chain.invoke({
"passport": passport.json(),
"profile": profile.json(),
"description": description.json(),
"account": account.json(),
"format_instructions": format_instructions,
})
# 6. Logs et retour
if result.decision == "Reject":
log.warning(f"Client rejected. Reason: {result.reason}")
else:
log.info("Client accepted.")
return result.decision

View File

@ -1,7 +1,6 @@
# TODO from pydantic import BaseModel
# account.reference_currency corresponds to passport.country from typing import Literal, Optional
# account.country ~ passport.country class AssistantDecision(BaseModel):
# account.country ~ description.nationality decision: Literal["Accept", "Reject"]
reason: Optional[str] = None
# account.city is in account.country