mirror of
https://github.com/rjNemo/rentease.git
synced 2026-06-10 12:46:53 +00:00
Some checks failed
CI / checks (push) Has been cancelled
Add a sample booking input and expected JSON output to guide extraction. Clarify missing value handling, ISO dates, and decimal conversion.
151 lines
4.6 KiB
Go
151 lines
4.6 KiB
Go
package parser
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"github.com/openai/openai-go"
|
|
"github.com/openai/openai-go/responses"
|
|
|
|
"github.com/rjNemo/rentease/internal/service/booking"
|
|
)
|
|
|
|
type BookingAgentParser struct {
|
|
systemPrompt string
|
|
llmClient openai.Client
|
|
model string
|
|
}
|
|
|
|
func NewBookingAgentParser(model string) *BookingAgentParser {
|
|
return &BookingAgentParser{
|
|
llmClient: openai.NewClient(),
|
|
model: model,
|
|
systemPrompt: ` Extract booking reservation fields from the booking content and return a JSON object with this exact structure.
|
|
All fields are required. Use an empty string for missing string values, 0 for missing integer values, and "0" for missing number strings.
|
|
Use ISO dates in YYYY-MM-DD format. Convert comma decimals to dot decimals.
|
|
|
|
{
|
|
"data": {
|
|
"arrival_date": "YYYY-MM-DD",
|
|
"booking_fees": "number as string",
|
|
"booking_id": "string",
|
|
"departure_date": "YYYY-MM-DD",
|
|
"stay_length": int,
|
|
"guest_email": "string",
|
|
"guest_name": "string",
|
|
"guest_number": int,
|
|
"guest_phone": "string",
|
|
"room_booked": "string",
|
|
"standard_rate": "number as string",
|
|
"special_requests": "string"
|
|
}
|
|
}
|
|
|
|
Respond ONLY with the JSON object above, wrapped in a top-level "data" field as shown, no code fences.
|
|
|
|
Example input:
|
|
Date d'arrivee jeu. 3 avr. 2025 Date de depart dim. 6 avr. 2025 Duree de sejour : 3 nuits Nombre de personnes : 2
|
|
Montant total EUR 186 Nom du client : Olga Korovina okorov.905387@guest.booking.com
|
|
Numero de reservation : 4453602306 Montant soumis a commission : EUR 177 Commission : EUR 31,86
|
|
Maison 1 Chambre T2 - VillaFleurie au bourg du Gosier EUR 186 Standard Rate EUR 59 Sous-total EUR 177 Conversation avec le client Aucun message
|
|
|
|
Example output:
|
|
{
|
|
"data": {
|
|
"arrival_date": "2025-04-03",
|
|
"booking_fees": "31.86",
|
|
"booking_id": "4453602306",
|
|
"departure_date": "2025-04-06",
|
|
"stay_length": 3,
|
|
"guest_email": "okorov.905387@guest.booking.com",
|
|
"guest_name": "Olga Korovina",
|
|
"guest_number": 2,
|
|
"guest_phone": "",
|
|
"room_booked": "Maison 1 Chambre T2 - VillaFleurie au bourg du Gosier",
|
|
"standard_rate": "59",
|
|
"special_requests": ""
|
|
}
|
|
}
|
|
|
|
Booking content:`,
|
|
}
|
|
}
|
|
|
|
// ResponseData is the expected structure returned by the LLM parser.
|
|
type ResponseData struct {
|
|
ArrivalDate string `json:"arrival_date"`
|
|
BookingFees json.Number `json:"booking_fees"`
|
|
BookingID string `json:"booking_id"`
|
|
DepartureDate string `json:"departure_date"`
|
|
StayLength int `json:"stay_length"`
|
|
GuestEmail string `json:"guest_email"`
|
|
GuestName string `json:"guest_name"`
|
|
GuestNumber int `json:"guest_number"`
|
|
GuestPhone string `json:"guest_phone"`
|
|
RoomBooked string `json:"room_booked"`
|
|
StandardRate json.Number `json:"standard_rate"`
|
|
SpecialRequests string `json:"special_requests"`
|
|
}
|
|
|
|
func (p *BookingAgentParser) Parse(rawContent string) (*booking.Booking, error) {
|
|
log.Println("sending request to OpenAI LLM parser")
|
|
|
|
ctx := context.Background()
|
|
|
|
prompt := p.systemPrompt + "\n" + rawContent
|
|
|
|
resp, err := p.llmClient.Responses.New(ctx, responses.ResponseNewParams{
|
|
Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(prompt)},
|
|
Model: p.model,
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error sending request to OpenAI: %w", err)
|
|
}
|
|
|
|
var r struct {
|
|
Data ResponseData `json:"data"`
|
|
}
|
|
|
|
// The LLM is instructed to return the JSON for ResponseData directly, so parse it
|
|
err = json.Unmarshal([]byte(resp.OutputText()), &r)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error decoding response from OpenAI: %w", err)
|
|
}
|
|
|
|
var b booking.Booking
|
|
b.From, err = time.Parse("2006-01-02", r.Data.ArrivalDate)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error parsing arrival_date: %w", err)
|
|
}
|
|
b.To, err = time.Parse("2006-01-02", r.Data.DepartureDate)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error parsing departure_date: %w", err)
|
|
}
|
|
b.Name = r.Data.GuestName
|
|
b.PhoneNumber = r.Data.GuestPhone
|
|
b.Email = r.Data.GuestEmail
|
|
b.CustomerNumber = r.Data.GuestNumber
|
|
bookingFees, err := r.Data.BookingFees.Float64()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error parsing booking fees: %w", err)
|
|
}
|
|
b.Platform = "Booking"
|
|
b.PlatformFees = bookingFees
|
|
b.ExternalID = &r.Data.BookingID
|
|
|
|
price, err := r.Data.StandardRate.Float64()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error parsing standard rate: %w", err)
|
|
}
|
|
b.Items = append(b.Items, booking.Item{
|
|
Item: r.Data.RoomBooked,
|
|
Quantity: r.Data.StayLength,
|
|
Price: price,
|
|
PaymentMethod: "Card",
|
|
})
|
|
|
|
return &b, nil
|
|
}
|