mirror of
https://github.com/rjNemo/rentease.git
synced 2026-06-06 02:36:49 +00:00
Refactors main.go to streamline context and logger initialization. Moves signal handling directly into main, sets up a base logger for early errors, and updates error handling to use structured logging. No functional changes to application logic.
123 lines
3.5 KiB
Go
123 lines
3.5 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
|
|
}
|
|
|
|
func NewBookingAgentParser() *BookingAgentParser {
|
|
return &BookingAgentParser{
|
|
llmClient: openai.NewClient(),
|
|
systemPrompt: ` Extract the following fields from the booking content and return a JSON object with this exact structure (all fields required, use null or empty string if not available):
|
|
|
|
{
|
|
"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.
|
|
|
|
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: openai.ChatModelChatgpt4oLatest,
|
|
})
|
|
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
|
|
}
|