update
This commit is contained in:
126
src/interface.jl
126
src/interface.jl
@@ -174,23 +174,59 @@ function decisionMaker(a::T)::Dict{Symbol, Any} where {T<:agent}
|
|||||||
# {"thought"
|
# {"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 =
|
systemmsg =
|
||||||
"""
|
"""
|
||||||
You are a helpful sommelier working for a wine store.
|
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.
|
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 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 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 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 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 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
|
- 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:
|
You should then respond to the user with interleaving Thought, Plan, Action and Observation:
|
||||||
- thought:
|
- thought:
|
||||||
1) State your reasoning about the current situation.
|
1) State your reasoning about the current situation.
|
||||||
@@ -213,7 +249,7 @@ function decisionMaker(a::T)::Dict{Symbol, Any} where {T<:agent}
|
|||||||
usermsg =
|
usermsg =
|
||||||
"""
|
"""
|
||||||
Context: None
|
Context: None
|
||||||
Your earlier conversation with the user: $(chatHistoryToString(a))
|
Your earlier conversation with the user: $(vectorOfDictToText(a.chathistory))
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_prompt =
|
_prompt =
|
||||||
@@ -902,10 +938,11 @@ function conversation(a::T, userinput::Dict) where {T<:agent}
|
|||||||
# add usermsg to a.chathistory
|
# add usermsg to a.chathistory
|
||||||
addNewMessage(a, "user", userinput[:text])
|
addNewMessage(a, "user", userinput[:text])
|
||||||
|
|
||||||
thought = think(a)
|
think(a)
|
||||||
|
|
||||||
# thought will be added to chat model via context
|
# thought will be added to chat model via context
|
||||||
chatresponse = generatechat(a, thought)
|
chatresponse = generatechat(a)
|
||||||
|
addNewMessage(a, "assistant", chatresponse)
|
||||||
|
|
||||||
return chatresponse
|
return chatresponse
|
||||||
end
|
end
|
||||||
@@ -1024,8 +1061,12 @@ function think(a::T) where {T<:agent}
|
|||||||
isterminal::Bool = haskey(response, :isterminal) ? response[:isterminal] : false
|
isterminal::Bool = haskey(response, :isterminal) ? response[:isterminal] : false
|
||||||
errormsg::Union{AbstractString, Nothing} = haskey(response, :errormsg) ? response[:errormsg] : nothing
|
errormsg::Union{AbstractString, Nothing} = haskey(response, :errormsg) ? response[:errormsg] : nothing
|
||||||
success::Bool = haskey(response, :success) ? response[:success] : false
|
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
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -1049,27 +1090,22 @@ julia>
|
|||||||
|
|
||||||
# Signature
|
# Signature
|
||||||
"""
|
"""
|
||||||
function generatechat(a::T1, input::T2) where {T1<:agent, T2<:AbstractString}
|
function generatechat(a::T) where {T<:agent}
|
||||||
systemmsg =
|
systemmsg =
|
||||||
"""
|
"""
|
||||||
You are a helpful sommelier working for a wine store.
|
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.
|
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:
|
||||||
- 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:
|
|
||||||
Context: ...
|
Context: ...
|
||||||
Your thoughts: Your current thinking in your mind
|
Your thoughts: Your current thinking in your mind
|
||||||
Your earlier conversation with the user: ...
|
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:
|
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:
|
You should only respond in format as described below:
|
||||||
chat: ...
|
chat: ...
|
||||||
@@ -1077,11 +1113,13 @@ function generatechat(a::T1, input::T2) where {T1<:agent, T2<:AbstractString}
|
|||||||
Let's begin!
|
Let's begin!
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
context = length(a.memory[:shortmem]) > 0 ? vectorOfDictToText(a.memory[:shortmem], withkey=false) : "None"
|
||||||
|
|
||||||
usermsg =
|
usermsg =
|
||||||
"""
|
"""
|
||||||
Context: None
|
Context: $context
|
||||||
Your thoughts: $input
|
Your earlier conversation with the user: $(vectorOfDictToText(a.chathistory))
|
||||||
Your earlier conversation with the user: $(chatHistoryToString(a))
|
Your thoughts: $(a.memory[:chatbox])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_prompt =
|
_prompt =
|
||||||
@@ -1099,31 +1137,31 @@ function generatechat(a::T1, input::T2) where {T1<:agent, T2<:AbstractString}
|
|||||||
|
|
||||||
for attempt in 1:5
|
for attempt in 1:5
|
||||||
try
|
try
|
||||||
response = text2textInstructLLM(prompt)
|
response = a.text2textInstructLLM(prompt)
|
||||||
responsedict = GeneralUtils.textToDict(response,
|
responsedict = GeneralUtils.textToDict(response,
|
||||||
["chat"],
|
["chat"],
|
||||||
rightmarker=":", symbolkey=true)
|
rightmarker=":", symbolkey=true)
|
||||||
|
|
||||||
# check if dict has all required value
|
for i ∈ [:chat]
|
||||||
evaluationtext::AbstractString = responsedict[:evaluation]
|
if length(JSON3.write(responsedict[i])) == 0
|
||||||
responsedict[:score] = parse(Int, responsedict[:score]) # convert string "5" into integer 5
|
error("$i is empty ", @__LINE__)
|
||||||
score::Integer = responsedict[:score]
|
end
|
||||||
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
|
|
||||||
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
|
catch e
|
||||||
io = IOBuffer()
|
io = IOBuffer()
|
||||||
showerror(io, e)
|
showerror(io, e)
|
||||||
@@ -1134,7 +1172,7 @@ function generatechat(a::T1, input::T2) where {T1<:agent, T2<:AbstractString}
|
|||||||
println("")
|
println("")
|
||||||
end
|
end
|
||||||
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}}
|
chathistory::Vector{Dict{Symbol, Any}}
|
||||||
shortmem::Dict{Symbol, Any}
|
memory::Dict{Symbol, Any}
|
||||||
|
|
||||||
# communication function
|
# communication function
|
||||||
text2textInstructLLM::Function
|
text2textInstructLLM::Function
|
||||||
@@ -105,7 +105,7 @@ function sommelier(
|
|||||||
name::String= "Assistant",
|
name::String= "Assistant",
|
||||||
id::String= string(uuid4()),
|
id::String= string(uuid4()),
|
||||||
maxHistoryMsg::Integer= 20,
|
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
|
tools = Dict( # update input format
|
||||||
@@ -127,13 +127,18 @@ function sommelier(
|
|||||||
# ),
|
# ),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
memory = Dict{Symbol, Any}(
|
||||||
|
:chatbox=> "",
|
||||||
|
:shortmem=> Vector{Dict{Symbol, String}}()
|
||||||
|
)
|
||||||
|
|
||||||
newAgent = sommelier(
|
newAgent = sommelier(
|
||||||
name,
|
name,
|
||||||
id,
|
id,
|
||||||
tools,
|
tools,
|
||||||
maxHistoryMsg,
|
maxHistoryMsg,
|
||||||
chathistory,
|
chathistory,
|
||||||
Dict{Symbol, Any}(),
|
memory,
|
||||||
text2textInstructLLM,
|
text2textInstructLLM,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
47
src/util.jl
47
src/util.jl
@@ -1,6 +1,6 @@
|
|||||||
module util
|
module util
|
||||||
|
|
||||||
export clearhistory, addNewMessage, chatHistoryToString
|
export clearhistory, addNewMessage, vectorOfDictToText
|
||||||
|
|
||||||
using UUIDs, Dates, DataStructures, HTTP, MQTTClient, JSON3
|
using UUIDs, Dates, DataStructures, HTTP, MQTTClient, JSON3
|
||||||
using GeneralUtils
|
using GeneralUtils
|
||||||
@@ -113,15 +113,43 @@ function addNewMessage(a::T1, name::String, text::T2;
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function chatHistoryToString(a)
|
"""
|
||||||
chatHistoryStr = ""
|
|
||||||
for i in a.chathistory
|
# Arguments
|
||||||
name = i[:name]
|
- `v::Integer`
|
||||||
text = i[:text]
|
dummy variable
|
||||||
chatHistoryStr *= "$name> $text"
|
|
||||||
|
# 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
|
end
|
||||||
|
|
||||||
return chatHistoryStr
|
return text
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -131,9 +159,6 @@ end
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# """ Convert a single chat dictionary into LLM model instruct format.
|
# """ Convert a single chat dictionary into LLM model instruct format.
|
||||||
|
|
||||||
# # Llama 3 instruct format example
|
# # 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."))
|
response = YiemAgent.conversation(a, Dict(:text=> "Hello, I would like a get a bottle of wine."))
|
||||||
println("---> YiemAgent: ", response)
|
println("---> YiemAgent: ", response)
|
||||||
|
|
||||||
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=> "I'm having a graduation party this evening. I'll pay at most 30 bucks."))
|
||||||
:select=> nothing,
|
response = YiemAgent.conversation(a, Dict(:text=> "What type of wine do you recommend for a celebration?"))
|
||||||
:reward=> 0,
|
|
||||||
:isterminal=> false,
|
|
||||||
) )
|
|
||||||
println("---> YiemAgent: ", response)
|
println("---> YiemAgent: ", response)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user