feat(contacts): events can now have organizers

This commit is contained in:
2025-03-31 18:40:36 +00:00
parent bb5f2bc2fe
commit c5278554cc
11 changed files with 284 additions and 70 deletions

View File

@@ -13,25 +13,27 @@ import (
"github.com/google/uuid"
)
// This prompt is probably shit.
const eventLocationPrompt = `
You are an agent that extracts events and locations from an image.
Your job is to check if an image has an event or a location and use the correct tools to extract this information.
You are an agent that extracts events, locations, and organizers from an image. Your primary tasks are to identify and create locations and organizers before creating events. Follow these steps:
If you find an event, you should look for a location for this event on the image, it is possible an event doesn't have a location.
Only create an event if you see an event on the image, not all locations have an associated event.
Identify and Create Locations:
It is possible that there is no location or event on an image.
Check if the image contains a location.
If a location is found, check if it exists in the listLocations.
If the location does not exist, create it first.
Always reuse existing locations from listLocations to avoid duplicates.
You should ask for a list of locations, as the user is likely to have this location saved. Reuse existing locations where possible.
Identify and Create Events:
Always reuse existing locations from listLocations. Do not create duplicates.
Check if the image contains an event. An event should have a name and a date.
If an event is found, ensure you have a location (from step 1) and an organizer (from step 2) before creating the event.
Events must have an associated location and organizer. Do not create an event without these.
If possible, return a start time and an end time as ISO datetime strings.
Handling Images Without Events or Locations:
Do not create an event if you don't see any dates, or a name indicating an event.
Events can have an associated location, if you think there is a location, then you must either use a location from listLocations or you must create it first.
Wherever possible, find the location in the image.
When possible return a start time as a ISO datetime string, as well as an end date time.
It is possible that the image does not contain an event or a location. In such cases, do not create an event.
Always prioritize the creation of locations and organizers before events. Ensure that all events have an associated location and organizer.
`
// TODO: this should be read directly from a file on load.
@@ -80,18 +82,22 @@ const TOOLS = `
},
"startDateTime": {
"type": "string",
"description": "The start time as an ISO string"
"description": "The start time as an ISO string"
},
"endDateTime": {
"type": "string",
"description": "The end time as an ISO string"
"description": "The end time as an ISO string"
},
"locationId": {
"type": "string",
"description": "The ID of the location, available by listLocations"
},
"organizerName": {
"type": "string",
"description": "The name of the organizer"
}
},
"required": ["name", "startDateTime", "endDateTime"]
"required": ["name"]
}
}
},
@@ -114,11 +120,13 @@ type EventLocationAgent struct {
eventModel models.EventModel
locationModel models.LocationModel
contactModel models.ContactModel
toolHandler ToolsHandlers
}
type ListLocationArguments struct{}
type ListOrganizerArguments struct{}
type CreateLocationArguments struct {
Name string `json:"name"`
@@ -126,6 +134,12 @@ type CreateLocationArguments struct {
Coordinates *string `json:"coordinates,omitempty"`
}
type CreateOrganizerArguments struct {
Name string `json:"name"`
PhoneNumber *string `json:"phoneNumber,omitempty"`
Email *string `json:"email,omitempty"`
}
type AttachImageLocationArguments struct {
LocationId string `json:"locationId"`
}
@@ -135,6 +149,7 @@ type CreateEventArguments struct {
StartDateTime string `json:"startDateTime"`
EndDateTime string `json:"endDateTime"`
LocationId string `json:"locationId"`
OrganizerName string `json:"organizerName"`
}
func (agent EventLocationAgent) GetLocations(userId uuid.UUID, imageId uuid.UUID, imageName string, imageData []byte) error {
@@ -251,7 +266,7 @@ func (handler ToolsHandlers) Handle(info ToolHandlerInfo, request *AgentRequestB
return string(stringResponse), nil
}
func NewLocationEventAgent(locationModel models.LocationModel, eventModel models.EventModel) (EventLocationAgent, error) {
func NewLocationEventAgent(locationModel models.LocationModel, eventModel models.EventModel, contactModel models.ContactModel) (EventLocationAgent, error) {
client, err := CreateAgentClient(eventLocationPrompt)
if err != nil {
return EventLocationAgent{}, err
@@ -261,6 +276,7 @@ func NewLocationEventAgent(locationModel models.LocationModel, eventModel models
client: client,
locationModel: locationModel,
eventModel: eventModel,
contactModel: contactModel,
}
toolHandler := ToolsHandlers{
@@ -317,7 +333,7 @@ func NewLocationEventAgent(locationModel models.LocationModel, eventModel models
Fn: func(info ToolHandlerInfo, args CreateEventArguments, call ToolCall) (model.Events, error) {
ctx := context.Background()
layout := "2006-01-02T15:04:05"
layout := "2006-01-02T15:04:05Z"
startTime, err := time.Parse(layout, args.StartDateTime)
if err != nil {
@@ -339,6 +355,14 @@ func NewLocationEventAgent(locationModel models.LocationModel, eventModel models
return event, err
}
organizer, err := agent.contactModel.Save(ctx, info.userId, model.Contacts{
Name: args.Name,
})
if err != nil {
return event, err
}
_, err = agent.eventModel.SaveToImage(ctx, info.imageId, event.ID)
if err != nil {
return event, err
@@ -349,7 +373,12 @@ func NewLocationEventAgent(locationModel models.LocationModel, eventModel models
return event, err
}
return agent.eventModel.UpdateLocation(ctx, event.ID, locationId)
event, err = agent.eventModel.UpdateLocation(ctx, event.ID, locationId)
if err != nil {
return event, err
}
return agent.eventModel.UpdateOrganizer(ctx, event.ID, organizer.ID)
},
}