update
This commit is contained in:
128
src/interface.jl
128
src/interface.jl
@@ -174,23 +174,59 @@ function decisionMaker(a::T)::Dict{Symbol, Any} where {T<:agent}
|
||||
# {"thought"
|
||||
# """
|
||||
|
||||
# systemmsg =
|
||||
# """
|
||||
# You are a helpful sommelier working for a wine store.
|
||||
# Your task is to help the user choose the best wine that match the user preferences from your inventory.
|
||||
# You are also eager to improve your helpfulness.
|
||||
|
||||
# You must follow the following guidelines:
|
||||
# - Get to know how much the user willing to spend
|
||||
# - Get to know type of wine the user is looking for e.g. red, white, sparkling, rose, dessert, fortified
|
||||
# - Get to know what occasion the user is buying wine for
|
||||
# - Get to know what characteristics of wine the user is looking for e.g. tannin, sweetness, intensity, acidity
|
||||
# - Get to know what food the user will have with wine
|
||||
|
||||
# At each round of conversation, the user will give you the current situation:
|
||||
# Context: ...
|
||||
# Your earlier conversation with the user: ...
|
||||
|
||||
# You should then respond to the user with interleaving Thought, Plan, Action and Observation:
|
||||
# - thought:
|
||||
# 1) State your reasoning about the current situation.
|
||||
# - plan: Based on the current situation, what would you do to complete the task? Be specific.
|
||||
# - action (Must be aligned with your plan): Can be one of the following functions:
|
||||
# 1) CHATBOX[text], which you can use to talk with the user. "text" is in verbal English.
|
||||
# 2) WINESTOCK[query], which you can use to find info about wine in your inventory. "query" is a search term in verbal English.
|
||||
# - observation: result of the action.
|
||||
|
||||
# You should only respond in format as described below:
|
||||
# thought: ...
|
||||
# plan: ...
|
||||
# action_name: ...
|
||||
# action_input: ...
|
||||
# observation: ...
|
||||
|
||||
# Let's begin!
|
||||
# """
|
||||
|
||||
systemmsg =
|
||||
"""
|
||||
You are a helpful sommelier working for a wine store.
|
||||
Your task is to help the user choose the best wine that match the user preferences from your inventory.
|
||||
You are also eager to improve your helpfulness.
|
||||
|
||||
You must follow the following guidelines:
|
||||
|
||||
At each round of conversation, the user will give you the current situation:
|
||||
Context: ...
|
||||
Your earlier conversation with the user: ...
|
||||
|
||||
You should follow the following guidelines:
|
||||
- Get to know how much the user willing to spend
|
||||
- Get to know type of wine the user is looking for e.g. red, white, sparkling, rose, dessert, fortified
|
||||
- Get to know what occasion the user is buying wine for
|
||||
- Get to know what characteristics of wine the user is looking for e.g. tannin, sweetness, intensity, acidity
|
||||
- Get to know what food the user will have with wine
|
||||
|
||||
At each round of conversation, the user will give you the current situation:
|
||||
Context: ...
|
||||
Your earlier conversation with the user: ...
|
||||
|
||||
You should then respond to the user with interleaving Thought, Plan, Action and Observation:
|
||||
- thought:
|
||||
1) State your reasoning about the current situation.
|
||||
@@ -213,7 +249,7 @@ function decisionMaker(a::T)::Dict{Symbol, Any} where {T<:agent}
|
||||
usermsg =
|
||||
"""
|
||||
Context: None
|
||||
Your earlier conversation with the user: $(chatHistoryToString(a))
|
||||
Your earlier conversation with the user: $(vectorOfDictToText(a.chathistory))
|
||||
"""
|
||||
|
||||
_prompt =
|
||||
@@ -902,10 +938,11 @@ function conversation(a::T, userinput::Dict) where {T<:agent}
|
||||
# add usermsg to a.chathistory
|
||||
addNewMessage(a, "user", userinput[:text])
|
||||
|
||||
thought = think(a)
|
||||
think(a)
|
||||
|
||||
# thought will be added to chat model via context
|
||||
chatresponse = generatechat(a, thought)
|
||||
chatresponse = generatechat(a)
|
||||
addNewMessage(a, "assistant", chatresponse)
|
||||
|
||||
return chatresponse
|
||||
end
|
||||
@@ -1024,8 +1061,12 @@ function think(a::T) where {T<:agent}
|
||||
isterminal::Bool = haskey(response, :isterminal) ? response[:isterminal] : false
|
||||
errormsg::Union{AbstractString, Nothing} = haskey(response, :errormsg) ? response[:errormsg] : nothing
|
||||
success::Bool = haskey(response, :success) ? response[:success] : false
|
||||
a.shortmem
|
||||
return result
|
||||
|
||||
if actionname == "CHATBOX"
|
||||
a.memory[:chatbox] = result
|
||||
else
|
||||
push!(a.memory[:shortmem], Dict(Symbol(actionname)=> result))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1049,27 +1090,22 @@ julia>
|
||||
|
||||
# Signature
|
||||
"""
|
||||
function generatechat(a::T1, input::T2) where {T1<:agent, T2<:AbstractString}
|
||||
function generatechat(a::T) where {T<:agent}
|
||||
systemmsg =
|
||||
"""
|
||||
You are a helpful sommelier working for a wine store.
|
||||
Your task is to help the user choose the best wine that match the user preferences from your inventory.
|
||||
You are also eager to improve your helpfulness.
|
||||
|
||||
You must follow the following guidelines:
|
||||
- Get to know how much the user willing to spend
|
||||
- Get to know type of wine the user is looking for e.g. red, white, sparkling, rose, dessert, fortified
|
||||
- Get to know what occasion the user is buying wine for
|
||||
- Get to know what characteristics of wine the user is looking for e.g. tannin, sweetness, intensity, acidity
|
||||
- Get to know what food the user will have with wine
|
||||
|
||||
At each round of conversation, the user will give you:
|
||||
At each round of conversation, the user will give you the current situation:
|
||||
Context: ...
|
||||
Your thoughts: Your current thinking in your mind
|
||||
Your earlier conversation with the user: ...
|
||||
|
||||
You must follow the following guidelines (if the user interrupts, prioritize the user):
|
||||
- Do not recommend specific wine before you checked your inventory.
|
||||
|
||||
You should then respond to the user with:
|
||||
- chat: what do you want to say to the user
|
||||
- chat: what do you want to say to the user based on the current situation
|
||||
|
||||
You should only respond in format as described below:
|
||||
chat: ...
|
||||
@@ -1077,11 +1113,13 @@ function generatechat(a::T1, input::T2) where {T1<:agent, T2<:AbstractString}
|
||||
Let's begin!
|
||||
"""
|
||||
|
||||
context = length(a.memory[:shortmem]) > 0 ? vectorOfDictToText(a.memory[:shortmem], withkey=false) : "None"
|
||||
|
||||
usermsg =
|
||||
"""
|
||||
Context: None
|
||||
Your thoughts: $input
|
||||
Your earlier conversation with the user: $(chatHistoryToString(a))
|
||||
Context: $context
|
||||
Your earlier conversation with the user: $(vectorOfDictToText(a.chathistory))
|
||||
Your thoughts: $(a.memory[:chatbox])
|
||||
"""
|
||||
|
||||
_prompt =
|
||||
@@ -1099,31 +1137,31 @@ function generatechat(a::T1, input::T2) where {T1<:agent, T2<:AbstractString}
|
||||
|
||||
for attempt in 1:5
|
||||
try
|
||||
response = text2textInstructLLM(prompt)
|
||||
response = a.text2textInstructLLM(prompt)
|
||||
responsedict = GeneralUtils.textToDict(response,
|
||||
["chat"],
|
||||
rightmarker=":", symbolkey=true)
|
||||
|
||||
# check if dict has all required value
|
||||
evaluationtext::AbstractString = responsedict[:evaluation]
|
||||
responsedict[:score] = parse(Int, responsedict[:score]) # convert string "5" into integer 5
|
||||
score::Integer = responsedict[:score]
|
||||
accepted_as_answer::AbstractString = responsedict[:accepted_as_answer]
|
||||
suggestion::AbstractString = responsedict[:suggestion]
|
||||
|
||||
# add to state here instead to in transition() because the latter causes julia extension crash (a bug in julia extension)
|
||||
state[:evaluation] = responsedict[:evaluation]
|
||||
state[:evaluationscore] = responsedict[:score]
|
||||
state[:accepted_as_answer] = responsedict[:accepted_as_answer]
|
||||
state[:suggestion] = responsedict[:suggestion]
|
||||
|
||||
# mark as terminal state when the answer is achieved
|
||||
if accepted_as_answer == "Yes"
|
||||
state[:isterminal] = true
|
||||
state[:reward] = 1
|
||||
for i ∈ [:chat]
|
||||
if length(JSON3.write(responsedict[i])) == 0
|
||||
error("$i is empty ", @__LINE__)
|
||||
end
|
||||
end
|
||||
|
||||
return responsedict[:score]
|
||||
# check if there are more than 1 key per categories
|
||||
for i ∈ [:chat]
|
||||
matchkeys = GeneralUtils.findMatchingDictKey(responsedict, i)
|
||||
if length(matchkeys) > 1
|
||||
error("generatechat has more than one key per categories")
|
||||
end
|
||||
end
|
||||
|
||||
result = responsedict[:chat]
|
||||
|
||||
#[WORKING] delete chat
|
||||
a.memory[:chatbox] = ""
|
||||
|
||||
return result
|
||||
catch e
|
||||
io = IOBuffer()
|
||||
showerror(io, e)
|
||||
@@ -1134,7 +1172,7 @@ function generatechat(a::T1, input::T2) where {T1<:agent, T2<:AbstractString}
|
||||
println("")
|
||||
end
|
||||
end
|
||||
error("evaluator failed to generate an evaluation")
|
||||
error("generatechat failed to generate an evaluation")
|
||||
|
||||
|
||||
|
||||
|
||||
11
src/type.jl
11
src/type.jl
@@ -93,7 +93,7 @@ mutable struct sommelier <: agent
|
||||
|
||||
"""
|
||||
chathistory::Vector{Dict{Symbol, Any}}
|
||||
shortmem::Dict{Symbol, Any}
|
||||
memory::Dict{Symbol, Any}
|
||||
|
||||
# communication function
|
||||
text2textInstructLLM::Function
|
||||
@@ -105,7 +105,7 @@ function sommelier(
|
||||
name::String= "Assistant",
|
||||
id::String= string(uuid4()),
|
||||
maxHistoryMsg::Integer= 20,
|
||||
chathistory::Vector{Dict{Symbol, Any}} = Vector{Dict{Symbol, Any}}(),
|
||||
chathistory::Vector{Dict{Symbol, String}} = Vector{Dict{Symbol, String}}(),
|
||||
)
|
||||
|
||||
tools = Dict( # update input format
|
||||
@@ -127,13 +127,18 @@ function sommelier(
|
||||
# ),
|
||||
)
|
||||
|
||||
memory = Dict{Symbol, Any}(
|
||||
:chatbox=> "",
|
||||
:shortmem=> Vector{Dict{Symbol, String}}()
|
||||
)
|
||||
|
||||
newAgent = sommelier(
|
||||
name,
|
||||
id,
|
||||
tools,
|
||||
maxHistoryMsg,
|
||||
chathistory,
|
||||
Dict{Symbol, Any}(),
|
||||
memory,
|
||||
text2textInstructLLM,
|
||||
)
|
||||
|
||||
|
||||
47
src/util.jl
47
src/util.jl
@@ -1,6 +1,6 @@
|
||||
module util
|
||||
|
||||
export clearhistory, addNewMessage, chatHistoryToString
|
||||
export clearhistory, addNewMessage, vectorOfDictToText
|
||||
|
||||
using UUIDs, Dates, DataStructures, HTTP, MQTTClient, JSON3
|
||||
using GeneralUtils
|
||||
@@ -113,15 +113,43 @@ function addNewMessage(a::T1, name::String, text::T2;
|
||||
end
|
||||
|
||||
|
||||
function chatHistoryToString(a)
|
||||
chatHistoryStr = ""
|
||||
for i in a.chathistory
|
||||
name = i[:name]
|
||||
text = i[:text]
|
||||
chatHistoryStr *= "$name> $text"
|
||||
"""
|
||||
|
||||
# Arguments
|
||||
- `v::Integer`
|
||||
dummy variable
|
||||
|
||||
# Return
|
||||
|
||||
# Example
|
||||
```jldoctest
|
||||
julia>
|
||||
```
|
||||
|
||||
# TODO
|
||||
- [] update docstring
|
||||
- [x] implement the function
|
||||
|
||||
# Signature
|
||||
"""
|
||||
function vectorOfDictToText(vecd::Vector; withkey=true)
|
||||
text = ""
|
||||
|
||||
if withkey
|
||||
for d in vecd
|
||||
name = d[:name]
|
||||
_text = d[:text]
|
||||
text *= "$name> $_text \n"
|
||||
end
|
||||
else
|
||||
for d in vecd
|
||||
for (k, v) in d
|
||||
text *= "$v \n"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return chatHistoryStr
|
||||
return text
|
||||
end
|
||||
|
||||
|
||||
@@ -131,9 +159,6 @@ end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# """ Convert a single chat dictionary into LLM model instruct format.
|
||||
|
||||
# # Llama 3 instruct format example
|
||||
|
||||
@@ -67,11 +67,11 @@ end
|
||||
response = YiemAgent.conversation(a, Dict(:text=> "Hello, I would like a get a bottle of wine."))
|
||||
println("---> YiemAgent: ", response)
|
||||
|
||||
response = YiemAgent.conversation(a, Dict(:text=> "I'm having a graduation party this evening. I'll pay at most 30 bucks.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
) )
|
||||
response = YiemAgent.conversation(a, Dict(:text=> "I'm having a graduation party this evening. I'll pay at most 30 bucks."))
|
||||
response = YiemAgent.conversation(a, Dict(:text=> "What type of wine do you recommend for a celebration?"))
|
||||
|
||||
|
||||
|
||||
println("---> YiemAgent: ", response)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user