diff --git a/src/utils.jl b/src/utils.jl index 0612a78..a958535 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -74,36 +74,39 @@ end """ - prepareContext(state::agentState) -> Vector{agentMessage} + prepareContext(state::agentState) -> agentContext -Returns a deep copy of the messages from the given `agentState`, ready -to be sent to the LLM. Override this function to inject additional -context — such as retrieved documents, current time, user preferences, -or any other relevant information — into the message list before -formatting and calling the LLM. +Prepares an `agentContext` from the given `agentState` for sending to +the LLM. By default, it deep copies the system prompt, messages, and +tools from `state` into a new `agentContext`. -By default, returns an exact copy of `state.messages` without -modification. +Override this function to customize the context — such as filtering +tools based on the user's intent, modifying the system prompt, injecting +additional context (retrieved documents, current time, user preferences), +or pruning and reordering messages before formatting and calling the LLM. # Arguments -- `state::agentState`: The current agent state containing conversation history +- `state::agentState`: The current agent state containing conversation history, + system prompt, tools, and other configuration # Returns -- `Vector{agentMessage}`: A deep copy of the messages to be sent to the LLM +- `agentContext`: An `agentContext` containing the prepared system prompt, + messages, and tools to be sent to the LLM # Examples ```julia -# Default: returns a deep copy of messages -prepareContext(state) == deepcopy(state.messages) +# Default: returns an agentContext with deep copies of system prompt, messages, and tools +prepareContext(state).messages == deepcopy(state.messages) -# Override to inject system context: -# function Base.prepareContext(state::agentState) +# Override to filter tools and inject system context: +# function prepareContext(state::agentState) # msgs = deepcopy(state.messages) -# pushfirst!(msgs, textMessage("system", "You are a helpful assistant.")) -# return msgs +# sysPrompt = state.systemPrompt * "\\nCurrent time: $(now())" +# tools = filter(t -> contains(t.description, "wine"), state.tools) +# return agentContext(sysPrompt, msgs, tools) # end ``` -""" #WORKING +""" function prepareContext(state::agentState)::agentContext #TODO filter tools from state.tools based on user intend in user message and tool description @@ -121,9 +124,38 @@ function prepareContext(state::agentState)::agentContext end -""" convert preparedcontext into openai message format ready to be used by LLM """ -function formatMsgForLLM(preparedContext::Vector{agentMessage})::Dict{String, Any} + formatMsgForLLM(ctx::agentContext) -> Dict{String, Any} + +Converts an `agentContext` into OpenAI-compatible message format +ready to be sent to the LLM. The system prompt is converted into +a system role message, followed by user, assistant, and tool result +messages. + +This function can be overridden in `yiemAgent` to produce custom +LLM message formats for different APIs/providers. + +# Arguments +- `ctx::agentContext`: The prepared context containing system prompt, + messages, and tools + +# Returns +- `Dict{String, Any}`: A dictionary with `"messages"` key containing + an array of OpenAI-format message dicts + +# Examples +```julia +# Default output: +formatMsgForLLm(ctx) == Dict("messages" => [ + Dict("role" => "system", "content" => [...]), + Dict("role" => "user", "content" => [...]), + Dict("role" => "assistant", "content" => [...]), + Dict("role" => "tool", "tool_call_id" => "...", "content" => [...]), +]) +``` +""" +function formatMsgForLLM(ctx::agentContext)::Dict{String, Any} + """ openai message format example msg = Dict( "model" => "gemma-4-E4B-it-UD-Q4_K_XL", @@ -140,7 +172,7 @@ function formatMsgForLLM(preparedContext::Vector{agentMessage})::Dict{String, An Dict("type" => "text", "text" => "Do you have something similar to the one in the image?"), Dict( "type" => "image_url", - "image_url" => Dict("url" => data1_uri) + "image_url" => Dict("url" => data_uri) ) ] ), @@ -161,9 +193,18 @@ function formatMsgForLLM(preparedContext::Vector{agentMessage})::Dict{String, An ) """ - messages = Dict{String, Any}[] + messages = Vector{Dict{String, Any}}() - for msg in preparedContext + # System prompt as system message + if !isempty(ctx.systemPrompt) + push!(messages, Dict( + "role" => "system", + "content" => [Dict("type" => "text", "text" => ctx.systemPrompt)] + )) + end + + # Conversation messages + for msg in ctx.messages if msg isa userMessage push!(messages, _userMessageToOpenAI(msg)) elseif msg isa assistantMessage