update
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,18 @@
|
||||
name = "YiemAgent"
|
||||
uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2"
|
||||
authors = ["narawat lamaiin <narawat@outlook.com>"]
|
||||
version = "0.1.0"
|
||||
|
||||
[deps]
|
||||
CondaPkg = "992eb4ea-22a4-4c89-a5bb-47a3300528ab"
|
||||
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
|
||||
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||
GeneralUtils = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
|
||||
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
|
||||
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
|
||||
MQTTClient = "985f35cc-2c3d-4943-b8c1-f0931d5f0959"
|
||||
PrettyPrinting = "54e16d92-306c-5ea0-a30b-337be88ac337"
|
||||
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
|
||||
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
||||
URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
|
||||
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
||||
name = "YiemAgent"
|
||||
uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2"
|
||||
authors = ["narawat lamaiin <narawat@outlook.com>"]
|
||||
version = "0.1.0"
|
||||
|
||||
[deps]
|
||||
CondaPkg = "992eb4ea-22a4-4c89-a5bb-47a3300528ab"
|
||||
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
|
||||
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||
GeneralUtils = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
|
||||
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
|
||||
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
|
||||
MQTTClient = "985f35cc-2c3d-4943-b8c1-f0931d5f0959"
|
||||
PrettyPrinting = "54e16d92-306c-5ea0-a30b-337be88ac337"
|
||||
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
|
||||
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
||||
URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
|
||||
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,50 +1,50 @@
|
||||
module YiemAgent
|
||||
|
||||
# export agent
|
||||
|
||||
|
||||
""" Order by dependencies of each file. The 1st included file must not depend on any other
|
||||
files and each file can only depend on the file included before it.
|
||||
"""
|
||||
|
||||
include("type.jl")
|
||||
using .type
|
||||
|
||||
include("util.jl")
|
||||
using .util
|
||||
|
||||
include("llmfunction.jl")
|
||||
using .llmfunction
|
||||
|
||||
include("mcts.jl")
|
||||
using .mcts
|
||||
|
||||
include("interface.jl")
|
||||
using .interface
|
||||
|
||||
|
||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end # module YiemAgent_v1
|
||||
module YiemAgent
|
||||
|
||||
# export agent
|
||||
|
||||
|
||||
""" Order by dependencies of each file. The 1st included file must not depend on any other
|
||||
files and each file can only depend on the file included before it.
|
||||
"""
|
||||
|
||||
include("type.jl")
|
||||
using .type
|
||||
|
||||
include("util.jl")
|
||||
using .util
|
||||
|
||||
include("llmfunction.jl")
|
||||
using .llmfunction
|
||||
|
||||
include("mcts.jl")
|
||||
using .mcts
|
||||
|
||||
include("interface.jl")
|
||||
using .interface
|
||||
|
||||
|
||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end # module YiemAgent_v1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,235 +1,235 @@
|
||||
module type
|
||||
|
||||
export agent, sommelier
|
||||
|
||||
using Dates, UUIDs, DataStructures, JSON3
|
||||
using GeneralUtils
|
||||
|
||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||
|
||||
abstract type agent end
|
||||
|
||||
|
||||
""" A sommelier agent.
|
||||
|
||||
# Arguments
|
||||
- `mqttClient::Client`
|
||||
MQTTClient's client
|
||||
- `msgMeta::Dict{Symbol, Any}`
|
||||
A dict contain info about a message.
|
||||
- `config::Dict{Symbol, Any}`
|
||||
Config info for an agent. Contain mqtt topic for internal use and other info.
|
||||
|
||||
# Keyword Arguments
|
||||
- `name::String`
|
||||
Agent's name
|
||||
- `id::String`
|
||||
Agent's ID
|
||||
- `tools::Dict{Symbol, Any}`
|
||||
Agent's tools
|
||||
- `maxHistoryMsg::Integer`
|
||||
max history message
|
||||
|
||||
# Return
|
||||
- `nothing`
|
||||
|
||||
# Example
|
||||
```jldoctest
|
||||
julia> using YiemAgent, MQTTClient, GeneralUtils
|
||||
julia> msgMeta = GeneralUtils.generate_msgMeta(
|
||||
"N/A",
|
||||
replyTopic = "/testtopic/prompt"
|
||||
)
|
||||
julia> tools= Dict(
|
||||
:chatbox=>Dict(
|
||||
:name => "chatbox",
|
||||
:description => "Useful only for when you need to ask the user for more info or context. Do not ask the user their own question.",
|
||||
:input => "Input should be a text.",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
)
|
||||
julia> agentConfig = Dict(
|
||||
:receiveprompt=>Dict(
|
||||
:mqtttopic=> "/testtopic/prompt", # topic to receive prompt i.e. frontend send msg to this topic
|
||||
),
|
||||
:receiveinternal=>Dict(
|
||||
:mqtttopic=> "/testtopic/internal", # receive topic for model's internal
|
||||
),
|
||||
:text2text=>Dict(
|
||||
:mqtttopic=> "/text2text/receive",
|
||||
),
|
||||
)
|
||||
julia> client, connection = MakeConnection("test.mosquitto.org", 1883)
|
||||
julia> agent = YiemAgent.bsommelier(
|
||||
client,
|
||||
msgMeta,
|
||||
agentConfig,
|
||||
name= "assistant",
|
||||
id= "555", # agent instance id
|
||||
tools=tools,
|
||||
)
|
||||
```
|
||||
|
||||
# TODO
|
||||
- [] update docstring
|
||||
- [x] implement the function
|
||||
|
||||
# Signature
|
||||
"""
|
||||
mutable struct sommelier <: agent
|
||||
name::String # agent name
|
||||
id::String # agent id
|
||||
config::Dict # agent config
|
||||
tools::Dict
|
||||
maxiterations::Integer # how many thinking round
|
||||
totalsample::Integer # how many sample in each thinking round
|
||||
maxDepth::Integer # how many step ahead to be simulated start from current state into the future
|
||||
maxHistoryMsg::Integer # 21th and earlier messages will get summarized
|
||||
|
||||
""" Memory
|
||||
Ref: Chat prompt format https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGML/discussions/3
|
||||
NO "system" message in chathistory because I want to add it at the inference time
|
||||
chathistory= [
|
||||
Dict(:name=>"user", :text=> "Wassup!", :timestamp=> Dates.now()),
|
||||
Dict(:name=>"assistant", :text=> "Hi I'm your assistant.", :timestamp=> Dates.now()),
|
||||
]
|
||||
|
||||
"""
|
||||
chathistory::Vector{Dict{Symbol, Any}}
|
||||
keywordinfo::Dict{Symbol, Any}
|
||||
|
||||
# 1-historyPoint is in Dict{Symbol, Any} and compose of:
|
||||
# state, statevalue, thought, action, observation
|
||||
plan::Dict{Symbol, Any}
|
||||
mctsWorkDict::Dict{Symbol, Any}
|
||||
end
|
||||
|
||||
function sommelier(
|
||||
config::Dict = Dict(
|
||||
:mqttServerInfo=> Dict(
|
||||
:broker=> nothing,
|
||||
:port=> nothing,
|
||||
),
|
||||
:receivemsg=> Dict(
|
||||
:prompt=> nothing, # topic to receive prompt i.e. frontend send msg to this topic
|
||||
:internal=> nothing,
|
||||
),
|
||||
:thirdPartyService=> Dict(
|
||||
:text2textinstruct=> nothing,
|
||||
:text2textchat=> nothing,
|
||||
),
|
||||
)
|
||||
;
|
||||
name::String= "Assistant",
|
||||
id::String= string(uuid4()),
|
||||
tools::Dict= Dict(
|
||||
:chatbox=> Dict(
|
||||
:name => "chatbox",
|
||||
:description => "Useful for when you need to communicate with the user.",
|
||||
:input => "Input should be a conversation to the user.",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
),
|
||||
maxiterations::Integer= 3,
|
||||
totalsample::Integer= 3,
|
||||
maxDepth::Integer= 3,
|
||||
maxHistoryMsg::Integer= 20,
|
||||
chathistory::Vector{Dict{Symbol, Any}} = Vector{Dict{Symbol, Any}}(),
|
||||
keywordinfo::Dict{Symbol, Any} = Dict{Symbol, Any}(
|
||||
:customerinfo => Dict{Symbol, Any}(),
|
||||
:storeinfo => Dict{Symbol, Any}(),
|
||||
),
|
||||
plan::Dict{Symbol, Any} = Dict{Symbol, Any}(
|
||||
|
||||
# store 3 to 5 best plan AI frequently used to avoid having to search MCTS all the time
|
||||
# each plan is in [historyPoint_1, historyPoint_2, ...] format
|
||||
:existingplan => Vector(),
|
||||
|
||||
:activeplan => Dict{Symbol, Any}(), # current using plan
|
||||
:currenttrajectory=> Dict{Symbol, Any}(), # store question, thought, action, observation, ...
|
||||
),
|
||||
mctsWorkDict::Dict{Symbol, Any} = Dict{Symbol, Any}()
|
||||
)
|
||||
|
||||
#[NEXTVERSION] publish to a.config[:configtopic] to get a config.
|
||||
#[NEXTVERSION] get a config message in a.mqttMsg_internal
|
||||
#[NEXTVERSION] set agent according to config
|
||||
|
||||
newAgent = sommelier(
|
||||
name,
|
||||
id,
|
||||
config,
|
||||
tools,
|
||||
maxiterations,
|
||||
totalsample,
|
||||
maxDepth,
|
||||
maxHistoryMsg,
|
||||
chathistory,
|
||||
keywordinfo,
|
||||
plan,
|
||||
mctsWorkDict,
|
||||
)
|
||||
|
||||
return newAgent
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module type
|
||||
|
||||
export agent, sommelier
|
||||
|
||||
using Dates, UUIDs, DataStructures, JSON3
|
||||
using GeneralUtils
|
||||
|
||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||
|
||||
abstract type agent end
|
||||
|
||||
|
||||
""" A sommelier agent.
|
||||
|
||||
# Arguments
|
||||
- `mqttClient::Client`
|
||||
MQTTClient's client
|
||||
- `msgMeta::Dict{Symbol, Any}`
|
||||
A dict contain info about a message.
|
||||
- `config::Dict{Symbol, Any}`
|
||||
Config info for an agent. Contain mqtt topic for internal use and other info.
|
||||
|
||||
# Keyword Arguments
|
||||
- `name::String`
|
||||
Agent's name
|
||||
- `id::String`
|
||||
Agent's ID
|
||||
- `tools::Dict{Symbol, Any}`
|
||||
Agent's tools
|
||||
- `maxHistoryMsg::Integer`
|
||||
max history message
|
||||
|
||||
# Return
|
||||
- `nothing`
|
||||
|
||||
# Example
|
||||
```jldoctest
|
||||
julia> using YiemAgent, MQTTClient, GeneralUtils
|
||||
julia> msgMeta = GeneralUtils.generate_msgMeta(
|
||||
"N/A",
|
||||
replyTopic = "/testtopic/prompt"
|
||||
)
|
||||
julia> tools= Dict(
|
||||
:chatbox=>Dict(
|
||||
:name => "chatbox",
|
||||
:description => "Useful only for when you need to ask the user for more info or context. Do not ask the user their own question.",
|
||||
:input => "Input should be a text.",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
)
|
||||
julia> agentConfig = Dict(
|
||||
:receiveprompt=>Dict(
|
||||
:mqtttopic=> "/testtopic/prompt", # topic to receive prompt i.e. frontend send msg to this topic
|
||||
),
|
||||
:receiveinternal=>Dict(
|
||||
:mqtttopic=> "/testtopic/internal", # receive topic for model's internal
|
||||
),
|
||||
:text2text=>Dict(
|
||||
:mqtttopic=> "/text2text/receive",
|
||||
),
|
||||
)
|
||||
julia> client, connection = MakeConnection("test.mosquitto.org", 1883)
|
||||
julia> agent = YiemAgent.bsommelier(
|
||||
client,
|
||||
msgMeta,
|
||||
agentConfig,
|
||||
name= "assistant",
|
||||
id= "555", # agent instance id
|
||||
tools=tools,
|
||||
)
|
||||
```
|
||||
|
||||
# TODO
|
||||
- [] update docstring
|
||||
- [x] implement the function
|
||||
|
||||
# Signature
|
||||
"""
|
||||
mutable struct sommelier <: agent
|
||||
name::String # agent name
|
||||
id::String # agent id
|
||||
config::Dict # agent config
|
||||
tools::Dict
|
||||
maxiterations::Integer # how many thinking round
|
||||
totalsample::Integer # how many sample in each thinking round
|
||||
maxDepth::Integer # how many step ahead to be simulated start from current state into the future
|
||||
maxHistoryMsg::Integer # 21th and earlier messages will get summarized
|
||||
|
||||
""" Memory
|
||||
Ref: Chat prompt format https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGML/discussions/3
|
||||
NO "system" message in chathistory because I want to add it at the inference time
|
||||
chathistory= [
|
||||
Dict(:name=>"user", :text=> "Wassup!", :timestamp=> Dates.now()),
|
||||
Dict(:name=>"assistant", :text=> "Hi I'm your assistant.", :timestamp=> Dates.now()),
|
||||
]
|
||||
|
||||
"""
|
||||
chathistory::Vector{Dict{Symbol, Any}}
|
||||
keywordinfo::Dict{Symbol, Any}
|
||||
|
||||
# 1-historyPoint is in Dict{Symbol, Any} and compose of:
|
||||
# state, statevalue, thought, action, observation
|
||||
plan::Dict{Symbol, Any}
|
||||
mctsWorkDict::Dict{Symbol, Any}
|
||||
end
|
||||
|
||||
function sommelier(
|
||||
config::Dict = Dict(
|
||||
:mqttServerInfo=> Dict(
|
||||
:broker=> nothing,
|
||||
:port=> nothing,
|
||||
),
|
||||
:receivemsg=> Dict(
|
||||
:prompt=> nothing, # topic to receive prompt i.e. frontend send msg to this topic
|
||||
:internal=> nothing,
|
||||
),
|
||||
:thirdPartyService=> Dict(
|
||||
:text2textinstruct=> nothing,
|
||||
:text2textchat=> nothing,
|
||||
),
|
||||
)
|
||||
;
|
||||
name::String= "Assistant",
|
||||
id::String= string(uuid4()),
|
||||
tools::Dict= Dict(
|
||||
:chatbox=> Dict(
|
||||
:name => "chatbox",
|
||||
:description => "Useful for when you need to communicate with the user.",
|
||||
:input => "Input should be a conversation to the user.",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
),
|
||||
maxiterations::Integer= 3,
|
||||
totalsample::Integer= 3,
|
||||
maxDepth::Integer= 3,
|
||||
maxHistoryMsg::Integer= 20,
|
||||
chathistory::Vector{Dict{Symbol, Any}} = Vector{Dict{Symbol, Any}}(),
|
||||
keywordinfo::Dict{Symbol, Any} = Dict{Symbol, Any}(
|
||||
:customerinfo => Dict{Symbol, Any}(),
|
||||
:storeinfo => Dict{Symbol, Any}(),
|
||||
),
|
||||
plan::Dict{Symbol, Any} = Dict{Symbol, Any}(
|
||||
|
||||
# store 3 to 5 best plan AI frequently used to avoid having to search MCTS all the time
|
||||
# each plan is in [historyPoint_1, historyPoint_2, ...] format
|
||||
:existingplan => Vector(),
|
||||
|
||||
:activeplan => Dict{Symbol, Any}(), # current using plan
|
||||
:currenttrajectory=> Dict{Symbol, Any}(), # store question, thought, action, observation, ...
|
||||
),
|
||||
mctsWorkDict::Dict{Symbol, Any} = Dict{Symbol, Any}()
|
||||
)
|
||||
|
||||
#[NEXTVERSION] publish to a.config[:configtopic] to get a config.
|
||||
#[NEXTVERSION] get a config message in a.mqttMsg_internal
|
||||
#[NEXTVERSION] set agent according to config
|
||||
|
||||
newAgent = sommelier(
|
||||
name,
|
||||
id,
|
||||
config,
|
||||
tools,
|
||||
maxiterations,
|
||||
totalsample,
|
||||
maxDepth,
|
||||
maxHistoryMsg,
|
||||
chathistory,
|
||||
keywordinfo,
|
||||
plan,
|
||||
mctsWorkDict,
|
||||
)
|
||||
|
||||
return newAgent
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end # module type
|
||||
@@ -1,373 +1,373 @@
|
||||
module util
|
||||
|
||||
export clearhistory, addNewMessage, formatLLMtext, iterativeprompting,
|
||||
formatLLMtext_llama3instruct, formatLLMtext_phi3instruct
|
||||
|
||||
using UUIDs, Dates, DataStructures, HTTP, MQTTClient, JSON3
|
||||
using GeneralUtils
|
||||
using ..type
|
||||
|
||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||
|
||||
""" Clear agent chat history.
|
||||
|
||||
# Arguments
|
||||
- `a::agent`
|
||||
an agent
|
||||
|
||||
# Return
|
||||
- nothing
|
||||
|
||||
# Example
|
||||
```jldoctest
|
||||
julia> using YiemAgent, MQTTClient, GeneralUtils
|
||||
julia> client, connection = MakeConnection("test.mosquitto.org", 1883)
|
||||
julia> connect(client, connection)
|
||||
julia> msgMeta = GeneralUtils.generate_msgMeta("testtopic")
|
||||
julia> agentConfig = Dict(
|
||||
:receiveprompt=>Dict(
|
||||
:mqtttopic=> "testtopic/receive",
|
||||
),
|
||||
:receiveinternal=>Dict(
|
||||
:mqtttopic=> "testtopic/internal",
|
||||
),
|
||||
:text2text=>Dict(
|
||||
:mqtttopic=> "testtopic/text2text",
|
||||
),
|
||||
)
|
||||
julia> a = YiemAgent.sommelier(
|
||||
client,
|
||||
msgMeta,
|
||||
agentConfig,
|
||||
)
|
||||
julia> YiemAgent.addNewMessage(a, "user", "hello")
|
||||
julia> YiemAgent.clearhistory(a)
|
||||
```
|
||||
|
||||
# Signature
|
||||
"""
|
||||
function clearhistory(a::T) where {T<:agent}
|
||||
empty!(a.chathistory)
|
||||
empty!(a.mctstree)
|
||||
empty!(a.plan[:activeplan])
|
||||
empty!(a.plan[:currenttrajectory])
|
||||
end
|
||||
|
||||
|
||||
""" Add new message to agent.
|
||||
|
||||
Arguments\n
|
||||
-----
|
||||
a::agent
|
||||
an agent
|
||||
role::String
|
||||
message sender role i.e. system, user or assistant
|
||||
text::String
|
||||
message text
|
||||
|
||||
Return\n
|
||||
-----
|
||||
nothing
|
||||
|
||||
Example\n
|
||||
-----
|
||||
```jldoctest
|
||||
julia> using YiemAgent, MQTTClient, GeneralUtils
|
||||
julia> client, connection = MakeConnection("test.mosquitto.org", 1883)
|
||||
julia> connect(client, connection)
|
||||
julia> msgMeta = GeneralUtils.generate_msgMeta("testtopic")
|
||||
julia> agentConfig = Dict(
|
||||
:receiveprompt=>Dict(
|
||||
:mqtttopic=> "testtopic/receive",
|
||||
),
|
||||
:receiveinternal=>Dict(
|
||||
:mqtttopic=> "testtopic/internal",
|
||||
),
|
||||
:text2text=>Dict(
|
||||
:mqtttopic=> "testtopic/text2text",
|
||||
),
|
||||
)
|
||||
julia> a = YiemAgent.sommelier(
|
||||
client,
|
||||
msgMeta,
|
||||
agentConfig,
|
||||
)
|
||||
julia> YiemAgent.addNewMessage(a, "user", "hello")
|
||||
```
|
||||
|
||||
Signature\n
|
||||
-----
|
||||
"""
|
||||
function addNewMessage(a::T1, name::String, text::T2;
|
||||
maximumMsg::Integer=20) where {T1<:agent, T2<:AbstractString}
|
||||
if name ∉ ["system", "user", "assistant"] # guard against typo
|
||||
error("name is not in agent.availableRole $(@__LINE__)")
|
||||
end
|
||||
|
||||
#[] summarize the oldest 10 message
|
||||
if length(a.chathistory) > maximumMsg
|
||||
summarize(a.chathistory)
|
||||
else
|
||||
d = Dict(:name=> name, :text=> text, :timestamp=> Dates.now())
|
||||
push!(a.chathistory, d)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
""" Convert a single chat dictionary into LLM model instruct format.
|
||||
|
||||
# Llama 3 instruct format example
|
||||
<|system|>
|
||||
You are a helpful AI assistant.<|end|>
|
||||
<|user|>
|
||||
I am going to Paris, what should I see?<|end|>
|
||||
<|assistant|>
|
||||
Paris, the capital of France, is known for its stunning architecture, art museums."<|end|>
|
||||
<|user|>
|
||||
What is so great about #1?<|end|>
|
||||
<|assistant|>
|
||||
|
||||
|
||||
# Arguments
|
||||
- `name::T`
|
||||
message owner name e.f. "system", "user" or "assistant"
|
||||
- `text::T`
|
||||
|
||||
# Return
|
||||
- `formattedtext::String`
|
||||
text formatted to model format
|
||||
|
||||
# Example
|
||||
```jldoctest
|
||||
julia> using Revise
|
||||
julia> using YiemAgent
|
||||
julia> d = Dict(:name=> "system",:text=> "You are a helpful, respectful and honest assistant.",)
|
||||
julia> formattedtext = YiemAgent.formatLLMtext_phi3instruct(d[:name], d[:text])
|
||||
|
||||
```
|
||||
|
||||
Signature
|
||||
"""
|
||||
function formatLLMtext_phi3instruct(name::T, text::T) where {T<:AbstractString}
|
||||
formattedtext =
|
||||
"""
|
||||
<|$name|>
|
||||
$text<|end|>\n
|
||||
"""
|
||||
|
||||
return formattedtext
|
||||
end
|
||||
|
||||
|
||||
""" Convert a single chat dictionary into LLM model instruct format.
|
||||
|
||||
# Llama 3 instruct format example
|
||||
<|begin_of_text|>
|
||||
<|start_header_id|>system<|end_header_id|>
|
||||
You are a helpful assistant.
|
||||
<|eot_id|>
|
||||
<|start_header_id|>user<|end_header_id|>
|
||||
Get me an icecream.
|
||||
<|eot_id|>
|
||||
<|start_header_id|>assistant<|end_header_id|>
|
||||
Go buy it yourself at 7-11.
|
||||
<|eot_id|>
|
||||
|
||||
# Arguments
|
||||
- `name::T`
|
||||
message owner name e.f. "system", "user" or "assistant"
|
||||
- `text::T`
|
||||
|
||||
# Return
|
||||
- `formattedtext::String`
|
||||
text formatted to model format
|
||||
|
||||
# Example
|
||||
```jldoctest
|
||||
julia> using Revise
|
||||
julia> using YiemAgent
|
||||
julia> d = Dict(:name=> "system",:text=> "You are a helpful, respectful and honest assistant.",)
|
||||
julia> formattedtext = YiemAgent.formatLLMtext_llama3instruct(d[:name], d[:text])
|
||||
"<|begin_of_text|>\n <|start_header_id|>system<|end_header_id|>\n You are a helpful, respectful and honest assistant.\n <|eot_id|>\n"
|
||||
```
|
||||
|
||||
Signature
|
||||
"""
|
||||
function formatLLMtext_llama3instruct(name::T, text::T) where {T<:AbstractString}
|
||||
formattedtext =
|
||||
if name == "system"
|
||||
"""
|
||||
<|begin_of_text|>
|
||||
<|start_header_id|>$name<|end_header_id|>
|
||||
$text
|
||||
<|eot_id|>
|
||||
"""
|
||||
else
|
||||
"""
|
||||
<|start_header_id|>$name<|end_header_id|>
|
||||
$text
|
||||
<|eot_id|>
|
||||
"""
|
||||
end
|
||||
|
||||
return formattedtext
|
||||
end
|
||||
|
||||
|
||||
|
||||
""" Convert a chat messages in vector of dictionary into LLM model instruct format.
|
||||
|
||||
# Arguments
|
||||
- `messages::Vector{Dict{Symbol, T}}`
|
||||
message owner name e.f. "system", "user" or "assistant"
|
||||
- `formatname::T`
|
||||
format name to be used
|
||||
|
||||
# Return
|
||||
- `formattedtext::String`
|
||||
text formatted to model format
|
||||
|
||||
# Example
|
||||
```jldoctest
|
||||
julia> using Revise
|
||||
julia> using YiemAgent
|
||||
julia> chatmessage = [
|
||||
Dict(:name=> "system",:text=> "You are a helpful, respectful and honest assistant.",),
|
||||
Dict(:name=> "user",:text=> "list me all planets in our solar system.",),
|
||||
Dict(:name=> "assistant",:text=> "I'm sorry. I don't know. You tell me.",),
|
||||
]
|
||||
julia> formattedtext = YiemAgent.formatLLMtext(chatmessage, "llama3instruct")
|
||||
"<|begin_of_text|>\n <|start_header_id|>system<|end_header_id|>\n You are a helpful, respectful and honest assistant.\n <|eot_id|>\n <|start_header_id|>user<|end_header_id|>\n list me all planets in our solar system.\n <|eot_id|>\n <|start_header_id|>assistant<|end_header_id|>\n I'm sorry. I don't know. You tell me.\n <|eot_id|>\n"
|
||||
```
|
||||
|
||||
# Signature
|
||||
"""
|
||||
function formatLLMtext(messages::Vector{Dict{Symbol, T}},
|
||||
formatname::String="llama3instruct") where {T<:Any}
|
||||
f = if formatname == "llama3instruct"
|
||||
formatLLMtext_llama3instruct
|
||||
elseif formatname == "mistral"
|
||||
# not define yet
|
||||
elseif formatname == "phi3instruct"
|
||||
formatLLMtext_phi3instruct
|
||||
else
|
||||
error("$formatname template not define yet")
|
||||
end
|
||||
|
||||
str = ""
|
||||
for t in messages
|
||||
str *= f(t[:name], t[:text])
|
||||
end
|
||||
|
||||
# add <|assistant|> so that the model don't generate it and I don't need to clean it up later
|
||||
if formatname == "phi3instruct"
|
||||
str *= "<|assistant|>\n"
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
|
||||
"""
|
||||
|
||||
Arguments\n
|
||||
-----
|
||||
|
||||
Return\n
|
||||
-----
|
||||
|
||||
Example\n
|
||||
-----
|
||||
```jldoctest
|
||||
julia>
|
||||
```
|
||||
|
||||
TODO\n
|
||||
-----
|
||||
[] update docstring
|
||||
[PENDING] implement the function
|
||||
|
||||
Signature\n
|
||||
-----
|
||||
"""
|
||||
function iterativeprompting(a::T, prompt::String, verification::Function) where {T<:agent}
|
||||
msgMeta = GeneralUtils.generate_msgMeta(
|
||||
a.config[:externalService][:text2textinstruct],
|
||||
senderName= "iterativeprompting",
|
||||
senderId= a.id,
|
||||
receiverName= "text2textinstruct",
|
||||
)
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> prompt,
|
||||
)
|
||||
)
|
||||
|
||||
success = nothing
|
||||
result = nothing
|
||||
critique = ""
|
||||
|
||||
# iteration loop
|
||||
while true
|
||||
# send prompt to LLM
|
||||
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg)
|
||||
error("--> iterativeprompting")
|
||||
# check for correctness and get feedback
|
||||
success, _critique = verification(response)
|
||||
|
||||
if success
|
||||
result = response
|
||||
break
|
||||
else
|
||||
# add critique to prompt
|
||||
critique *= _critique * "\n"
|
||||
replace!(prompt, "Critique: ..." => "Critique: $critique")
|
||||
end
|
||||
end
|
||||
|
||||
return (success=success, result=result)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module util
|
||||
|
||||
export clearhistory, addNewMessage, formatLLMtext, iterativeprompting,
|
||||
formatLLMtext_llama3instruct, formatLLMtext_phi3instruct
|
||||
|
||||
using UUIDs, Dates, DataStructures, HTTP, MQTTClient, JSON3
|
||||
using GeneralUtils
|
||||
using ..type
|
||||
|
||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||
|
||||
""" Clear agent chat history.
|
||||
|
||||
# Arguments
|
||||
- `a::agent`
|
||||
an agent
|
||||
|
||||
# Return
|
||||
- nothing
|
||||
|
||||
# Example
|
||||
```jldoctest
|
||||
julia> using YiemAgent, MQTTClient, GeneralUtils
|
||||
julia> client, connection = MakeConnection("test.mosquitto.org", 1883)
|
||||
julia> connect(client, connection)
|
||||
julia> msgMeta = GeneralUtils.generate_msgMeta("testtopic")
|
||||
julia> agentConfig = Dict(
|
||||
:receiveprompt=>Dict(
|
||||
:mqtttopic=> "testtopic/receive",
|
||||
),
|
||||
:receiveinternal=>Dict(
|
||||
:mqtttopic=> "testtopic/internal",
|
||||
),
|
||||
:text2text=>Dict(
|
||||
:mqtttopic=> "testtopic/text2text",
|
||||
),
|
||||
)
|
||||
julia> a = YiemAgent.sommelier(
|
||||
client,
|
||||
msgMeta,
|
||||
agentConfig,
|
||||
)
|
||||
julia> YiemAgent.addNewMessage(a, "user", "hello")
|
||||
julia> YiemAgent.clearhistory(a)
|
||||
```
|
||||
|
||||
# Signature
|
||||
"""
|
||||
function clearhistory(a::T) where {T<:agent}
|
||||
empty!(a.chathistory)
|
||||
empty!(a.mctstree)
|
||||
empty!(a.plan[:activeplan])
|
||||
empty!(a.plan[:currenttrajectory])
|
||||
end
|
||||
|
||||
|
||||
""" Add new message to agent.
|
||||
|
||||
Arguments\n
|
||||
-----
|
||||
a::agent
|
||||
an agent
|
||||
role::String
|
||||
message sender role i.e. system, user or assistant
|
||||
text::String
|
||||
message text
|
||||
|
||||
Return\n
|
||||
-----
|
||||
nothing
|
||||
|
||||
Example\n
|
||||
-----
|
||||
```jldoctest
|
||||
julia> using YiemAgent, MQTTClient, GeneralUtils
|
||||
julia> client, connection = MakeConnection("test.mosquitto.org", 1883)
|
||||
julia> connect(client, connection)
|
||||
julia> msgMeta = GeneralUtils.generate_msgMeta("testtopic")
|
||||
julia> agentConfig = Dict(
|
||||
:receiveprompt=>Dict(
|
||||
:mqtttopic=> "testtopic/receive",
|
||||
),
|
||||
:receiveinternal=>Dict(
|
||||
:mqtttopic=> "testtopic/internal",
|
||||
),
|
||||
:text2text=>Dict(
|
||||
:mqtttopic=> "testtopic/text2text",
|
||||
),
|
||||
)
|
||||
julia> a = YiemAgent.sommelier(
|
||||
client,
|
||||
msgMeta,
|
||||
agentConfig,
|
||||
)
|
||||
julia> YiemAgent.addNewMessage(a, "user", "hello")
|
||||
```
|
||||
|
||||
Signature\n
|
||||
-----
|
||||
"""
|
||||
function addNewMessage(a::T1, name::String, text::T2;
|
||||
maximumMsg::Integer=20) where {T1<:agent, T2<:AbstractString}
|
||||
if name ∉ ["system", "user", "assistant"] # guard against typo
|
||||
error("name is not in agent.availableRole $(@__LINE__)")
|
||||
end
|
||||
|
||||
#[] summarize the oldest 10 message
|
||||
if length(a.chathistory) > maximumMsg
|
||||
summarize(a.chathistory)
|
||||
else
|
||||
d = Dict(:name=> name, :text=> text, :timestamp=> Dates.now())
|
||||
push!(a.chathistory, d)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
""" Convert a single chat dictionary into LLM model instruct format.
|
||||
|
||||
# Llama 3 instruct format example
|
||||
<|system|>
|
||||
You are a helpful AI assistant.<|end|>
|
||||
<|user|>
|
||||
I am going to Paris, what should I see?<|end|>
|
||||
<|assistant|>
|
||||
Paris, the capital of France, is known for its stunning architecture, art museums."<|end|>
|
||||
<|user|>
|
||||
What is so great about #1?<|end|>
|
||||
<|assistant|>
|
||||
|
||||
|
||||
# Arguments
|
||||
- `name::T`
|
||||
message owner name e.f. "system", "user" or "assistant"
|
||||
- `text::T`
|
||||
|
||||
# Return
|
||||
- `formattedtext::String`
|
||||
text formatted to model format
|
||||
|
||||
# Example
|
||||
```jldoctest
|
||||
julia> using Revise
|
||||
julia> using YiemAgent
|
||||
julia> d = Dict(:name=> "system",:text=> "You are a helpful, respectful and honest assistant.",)
|
||||
julia> formattedtext = YiemAgent.formatLLMtext_phi3instruct(d[:name], d[:text])
|
||||
|
||||
```
|
||||
|
||||
Signature
|
||||
"""
|
||||
function formatLLMtext_phi3instruct(name::T, text::T) where {T<:AbstractString}
|
||||
formattedtext =
|
||||
"""
|
||||
<|$name|>
|
||||
$text<|end|>\n
|
||||
"""
|
||||
|
||||
return formattedtext
|
||||
end
|
||||
|
||||
|
||||
""" Convert a single chat dictionary into LLM model instruct format.
|
||||
|
||||
# Llama 3 instruct format example
|
||||
<|begin_of_text|>
|
||||
<|start_header_id|>system<|end_header_id|>
|
||||
You are a helpful assistant.
|
||||
<|eot_id|>
|
||||
<|start_header_id|>user<|end_header_id|>
|
||||
Get me an icecream.
|
||||
<|eot_id|>
|
||||
<|start_header_id|>assistant<|end_header_id|>
|
||||
Go buy it yourself at 7-11.
|
||||
<|eot_id|>
|
||||
|
||||
# Arguments
|
||||
- `name::T`
|
||||
message owner name e.f. "system", "user" or "assistant"
|
||||
- `text::T`
|
||||
|
||||
# Return
|
||||
- `formattedtext::String`
|
||||
text formatted to model format
|
||||
|
||||
# Example
|
||||
```jldoctest
|
||||
julia> using Revise
|
||||
julia> using YiemAgent
|
||||
julia> d = Dict(:name=> "system",:text=> "You are a helpful, respectful and honest assistant.",)
|
||||
julia> formattedtext = YiemAgent.formatLLMtext_llama3instruct(d[:name], d[:text])
|
||||
"<|begin_of_text|>\n <|start_header_id|>system<|end_header_id|>\n You are a helpful, respectful and honest assistant.\n <|eot_id|>\n"
|
||||
```
|
||||
|
||||
Signature
|
||||
"""
|
||||
function formatLLMtext_llama3instruct(name::T, text::T) where {T<:AbstractString}
|
||||
formattedtext =
|
||||
if name == "system"
|
||||
"""
|
||||
<|begin_of_text|>
|
||||
<|start_header_id|>$name<|end_header_id|>
|
||||
$text
|
||||
<|eot_id|>
|
||||
"""
|
||||
else
|
||||
"""
|
||||
<|start_header_id|>$name<|end_header_id|>
|
||||
$text
|
||||
<|eot_id|>
|
||||
"""
|
||||
end
|
||||
|
||||
return formattedtext
|
||||
end
|
||||
|
||||
|
||||
|
||||
""" Convert a chat messages in vector of dictionary into LLM model instruct format.
|
||||
|
||||
# Arguments
|
||||
- `messages::Vector{Dict{Symbol, T}}`
|
||||
message owner name e.f. "system", "user" or "assistant"
|
||||
- `formatname::T`
|
||||
format name to be used
|
||||
|
||||
# Return
|
||||
- `formattedtext::String`
|
||||
text formatted to model format
|
||||
|
||||
# Example
|
||||
```jldoctest
|
||||
julia> using Revise
|
||||
julia> using YiemAgent
|
||||
julia> chatmessage = [
|
||||
Dict(:name=> "system",:text=> "You are a helpful, respectful and honest assistant.",),
|
||||
Dict(:name=> "user",:text=> "list me all planets in our solar system.",),
|
||||
Dict(:name=> "assistant",:text=> "I'm sorry. I don't know. You tell me.",),
|
||||
]
|
||||
julia> formattedtext = YiemAgent.formatLLMtext(chatmessage, "llama3instruct")
|
||||
"<|begin_of_text|>\n <|start_header_id|>system<|end_header_id|>\n You are a helpful, respectful and honest assistant.\n <|eot_id|>\n <|start_header_id|>user<|end_header_id|>\n list me all planets in our solar system.\n <|eot_id|>\n <|start_header_id|>assistant<|end_header_id|>\n I'm sorry. I don't know. You tell me.\n <|eot_id|>\n"
|
||||
```
|
||||
|
||||
# Signature
|
||||
"""
|
||||
function formatLLMtext(messages::Vector{Dict{Symbol, T}},
|
||||
formatname::String="llama3instruct") where {T<:Any}
|
||||
f = if formatname == "llama3instruct"
|
||||
formatLLMtext_llama3instruct
|
||||
elseif formatname == "mistral"
|
||||
# not define yet
|
||||
elseif formatname == "phi3instruct"
|
||||
formatLLMtext_phi3instruct
|
||||
else
|
||||
error("$formatname template not define yet")
|
||||
end
|
||||
|
||||
str = ""
|
||||
for t in messages
|
||||
str *= f(t[:name], t[:text])
|
||||
end
|
||||
|
||||
# add <|assistant|> so that the model don't generate it and I don't need to clean it up later
|
||||
if formatname == "phi3instruct"
|
||||
str *= "<|assistant|>\n"
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
|
||||
"""
|
||||
|
||||
Arguments\n
|
||||
-----
|
||||
|
||||
Return\n
|
||||
-----
|
||||
|
||||
Example\n
|
||||
-----
|
||||
```jldoctest
|
||||
julia>
|
||||
```
|
||||
|
||||
TODO\n
|
||||
-----
|
||||
[] update docstring
|
||||
[PENDING] implement the function
|
||||
|
||||
Signature\n
|
||||
-----
|
||||
"""
|
||||
function iterativeprompting(a::T, prompt::String, verification::Function) where {T<:agent}
|
||||
msgMeta = GeneralUtils.generate_msgMeta(
|
||||
a.config[:externalService][:text2textinstruct],
|
||||
senderName= "iterativeprompting",
|
||||
senderId= a.id,
|
||||
receiverName= "text2textinstruct",
|
||||
)
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> prompt,
|
||||
)
|
||||
)
|
||||
|
||||
success = nothing
|
||||
result = nothing
|
||||
critique = ""
|
||||
|
||||
# iteration loop
|
||||
while true
|
||||
# send prompt to LLM
|
||||
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg)
|
||||
error("--> iterativeprompting")
|
||||
# check for correctness and get feedback
|
||||
success, _critique = verification(response)
|
||||
|
||||
if success
|
||||
result = response
|
||||
break
|
||||
else
|
||||
# add critique to prompt
|
||||
critique *= _critique * "\n"
|
||||
replace!(prompt, "Critique: ..." => "Critique: $critique")
|
||||
end
|
||||
end
|
||||
|
||||
return (success=success, result=result)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end # module util
|
||||
@@ -1,159 +1,159 @@
|
||||
using Revise
|
||||
using YiemAgent, GeneralUtils, JSON3, DataStructures
|
||||
|
||||
thoughtDict = OrderedDict(
|
||||
:Question=> "Hello, I would like a get a bottle of wine",
|
||||
:Thought_1=> "The customer wants to buy a bottle of wine, but we need more information about their preferences.",
|
||||
:Action_1=> Dict(
|
||||
:name=> "chatbox",
|
||||
:input=> "What occasion are you buying the wine for?",
|
||||
),
|
||||
:Observation_1=> "We are having a wedding pary this weekend.",
|
||||
|
||||
:Thought_2=> "A wedding party is a great occasion to have a good bottle of wine.",
|
||||
:Action_2=> Dict(
|
||||
:name=> "chatbox",
|
||||
:input=> "What type of food will you be serving with the wine?",
|
||||
),
|
||||
:Observation_2=> "I think it is Thai dishes",
|
||||
|
||||
:Thought_3=> "Now that I know the occasion and food, I need to ask about the budget.",
|
||||
:Action_3=> Dict(
|
||||
:name=> "chatbox",
|
||||
:input=> "What is your budget for this wine?",
|
||||
),
|
||||
:Observation_3=> "50 bucks",
|
||||
|
||||
:Thought_4=> "With a budget of \$50, we have a wide range of options. Now that I know it's a wedding party and Thai dishes, I need to ask about the type of wine they prefer.",
|
||||
:Action_4=> Dict(
|
||||
:name=> "chatbox",
|
||||
:input=> "What type of wine are you looking for? (Red, White, Sparkling, Rose, Dessert, Fortified)",
|
||||
),
|
||||
:Observation_4=> "Sparkling please.",
|
||||
|
||||
:Thought_5=> "Now that I know the occasion, food, budget and preferred type of wine, it's time to check our inventory for the best matching wine.",
|
||||
:Action_5=> Dict(
|
||||
:name=> "winestock",
|
||||
:input=> "wine with budget \$50, Thai dishes, sparkling, wedding party",
|
||||
),
|
||||
:Observation_5=> "I found the following wine in stock {1 : Zena Crown Vista, 2 : Schrader Cabernet Sauvignon}",
|
||||
|
||||
:Thought_6=> "Now that I have all the information, it's time to recommend a wine that fits their preferences.",
|
||||
:Action_6=> Dict(
|
||||
:name=> "recommendation",
|
||||
:input=> "I recommend Zena Crown Vista for its sparkling and affordable price.",
|
||||
),
|
||||
:Observation_6=> "I don't like it. Do you have another option?",
|
||||
)
|
||||
|
||||
_thoughtJsonStr = JSON3.write(thoughtDict)
|
||||
thoughtJsonStr = _thoughtJsonStr[1:end-1] # remove } at the end
|
||||
# @show thoughtJsonStr
|
||||
|
||||
_, latestThoughtIndice = GeneralUtils.findHighestIndexKey(thoughtDict, "Thought")
|
||||
nextThoughtIndice = latestThoughtIndice + 1
|
||||
|
||||
_prompt =
|
||||
"""
|
||||
You are a helpful sommelier working for a wine store.
|
||||
Your goal is to reccommend the best wine from your inventory that match the user preferences.
|
||||
|
||||
You must follow the following criteria:
|
||||
1) Get to know what occasion the user is buying wine for
|
||||
2) Get to know what food the user will have with wine
|
||||
3) Get to know how much the user willing to spend
|
||||
4) Get to know type of wine the user is looking for e.g. Red, White, Sparkling, Rose, Dessert, Fortified
|
||||
5) Get to know what characteristics of wine the user is looking for
|
||||
e.g. tannin, sweetness, intensity, acidity
|
||||
6) Check your inventory for the best wine that match the user preference
|
||||
7) Recommend wine to the user
|
||||
|
||||
You should only respond with interleaving Thought, Action, Observation steps.
|
||||
Thought can reason about the current situation, and Action can be three types:
|
||||
1) winestock[query], which you can use to find wine in your inventory. The more input data the better.
|
||||
2) chatbox[text], which you can use to interact with the user.
|
||||
3) recommendation[answer], which returns your wine reccommendation to the user.
|
||||
|
||||
You should only respond in JSON format as describe below:
|
||||
{
|
||||
"Thought": "your reasoning",
|
||||
"Action": {"name": "action to take", "input": "Action input"},
|
||||
"Observation": "result of the action"
|
||||
}
|
||||
|
||||
Here are some examples:
|
||||
{
|
||||
"Question": "I would like to buy a sedan with 8 seats.",
|
||||
"Thought_1": "Our showroom carries various vehicle model. But I'm not sure whether we have a models that fits the user demand, I need to check our inventory.",
|
||||
"Action_1": {"name": "inventory", "input": "sedan with 8 seats."},
|
||||
"Observation_1": "Several model has 8 seats. Available color are black, red green"
|
||||
}
|
||||
{
|
||||
"Thought_2": "I have to ask the user what color he likes.",
|
||||
"Action_2": {"name": "chatbox", "input": "Which color do you like?"}
|
||||
"Observation_2": "I'll take black."
|
||||
}
|
||||
{
|
||||
"Thought_3": "There is only one model that fits the user preference. It's Yiem model A",
|
||||
"Action_3": {"name": "recommendation", "input": "I recommend a Yiem model A"}
|
||||
}
|
||||
|
||||
Let's begin!
|
||||
|
||||
$(JSON3.write(thoughtDict))
|
||||
{Thought_$nextThoughtIndice
|
||||
"""
|
||||
|
||||
prompt = YiemAgent.formatLLMtext_llama3instruct("system", _prompt)
|
||||
@show prompt
|
||||
msgMeta = Dict(:requestResponse => nothing,
|
||||
:msgPurpose => nothing,
|
||||
:receiverId => nothing,
|
||||
:getPost => nothing,
|
||||
:msgId => "4c7111e0-c30e-44c3-8f85-1c8b3f03a8be",
|
||||
:acknowledgestatus => nothing,
|
||||
:replyToMsgId => nothing,
|
||||
:msgFormatVersion => nothing,
|
||||
:mqttServerInfo => Dict(:port => 1883, :broker => "mqtt.yiem.cc"),
|
||||
:sendTopic => "/loadbalancer/requestingservice",
|
||||
:receiverName => "text2textinstruct",
|
||||
:replyTopic => nothing,
|
||||
:senderName => "decisionMaker",
|
||||
:senderSelfnote => nothing,
|
||||
:senderId => "testingSessionID",
|
||||
:timeStamp => "2024-05-04T08:06:23.561"
|
||||
)
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> prompt,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
_response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg)
|
||||
thoughtJsonStr = _response[:response][:text]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
using Revise
|
||||
using YiemAgent, GeneralUtils, JSON3, DataStructures
|
||||
|
||||
thoughtDict = OrderedDict(
|
||||
:Question=> "Hello, I would like a get a bottle of wine",
|
||||
:Thought_1=> "The customer wants to buy a bottle of wine, but we need more information about their preferences.",
|
||||
:Action_1=> Dict(
|
||||
:name=> "chatbox",
|
||||
:input=> "What occasion are you buying the wine for?",
|
||||
),
|
||||
:Observation_1=> "We are having a wedding pary this weekend.",
|
||||
|
||||
:Thought_2=> "A wedding party is a great occasion to have a good bottle of wine.",
|
||||
:Action_2=> Dict(
|
||||
:name=> "chatbox",
|
||||
:input=> "What type of food will you be serving with the wine?",
|
||||
),
|
||||
:Observation_2=> "I think it is Thai dishes",
|
||||
|
||||
:Thought_3=> "Now that I know the occasion and food, I need to ask about the budget.",
|
||||
:Action_3=> Dict(
|
||||
:name=> "chatbox",
|
||||
:input=> "What is your budget for this wine?",
|
||||
),
|
||||
:Observation_3=> "50 bucks",
|
||||
|
||||
:Thought_4=> "With a budget of \$50, we have a wide range of options. Now that I know it's a wedding party and Thai dishes, I need to ask about the type of wine they prefer.",
|
||||
:Action_4=> Dict(
|
||||
:name=> "chatbox",
|
||||
:input=> "What type of wine are you looking for? (Red, White, Sparkling, Rose, Dessert, Fortified)",
|
||||
),
|
||||
:Observation_4=> "Sparkling please.",
|
||||
|
||||
:Thought_5=> "Now that I know the occasion, food, budget and preferred type of wine, it's time to check our inventory for the best matching wine.",
|
||||
:Action_5=> Dict(
|
||||
:name=> "winestock",
|
||||
:input=> "wine with budget \$50, Thai dishes, sparkling, wedding party",
|
||||
),
|
||||
:Observation_5=> "I found the following wine in stock {1 : Zena Crown Vista, 2 : Schrader Cabernet Sauvignon}",
|
||||
|
||||
:Thought_6=> "Now that I have all the information, it's time to recommend a wine that fits their preferences.",
|
||||
:Action_6=> Dict(
|
||||
:name=> "recommendation",
|
||||
:input=> "I recommend Zena Crown Vista for its sparkling and affordable price.",
|
||||
),
|
||||
:Observation_6=> "I don't like it. Do you have another option?",
|
||||
)
|
||||
|
||||
_thoughtJsonStr = JSON3.write(thoughtDict)
|
||||
thoughtJsonStr = _thoughtJsonStr[1:end-1] # remove } at the end
|
||||
# @show thoughtJsonStr
|
||||
|
||||
_, latestThoughtIndice = GeneralUtils.findHighestIndexKey(thoughtDict, "Thought")
|
||||
nextThoughtIndice = latestThoughtIndice + 1
|
||||
|
||||
_prompt =
|
||||
"""
|
||||
You are a helpful sommelier working for a wine store.
|
||||
Your goal is to reccommend the best wine from your inventory that match the user preferences.
|
||||
|
||||
You must follow the following criteria:
|
||||
1) Get to know what occasion the user is buying wine for
|
||||
2) Get to know what food the user will have with wine
|
||||
3) Get to know how much the user willing to spend
|
||||
4) Get to know type of wine the user is looking for e.g. Red, White, Sparkling, Rose, Dessert, Fortified
|
||||
5) Get to know what characteristics of wine the user is looking for
|
||||
e.g. tannin, sweetness, intensity, acidity
|
||||
6) Check your inventory for the best wine that match the user preference
|
||||
7) Recommend wine to the user
|
||||
|
||||
You should only respond with interleaving Thought, Action, Observation steps.
|
||||
Thought can reason about the current situation, and Action can be three types:
|
||||
1) winestock[query], which you can use to find wine in your inventory. The more input data the better.
|
||||
2) chatbox[text], which you can use to interact with the user.
|
||||
3) recommendation[answer], which returns your wine reccommendation to the user.
|
||||
|
||||
You should only respond in JSON format as describe below:
|
||||
{
|
||||
"Thought": "your reasoning",
|
||||
"Action": {"name": "action to take", "input": "Action input"},
|
||||
"Observation": "result of the action"
|
||||
}
|
||||
|
||||
Here are some examples:
|
||||
{
|
||||
"Question": "I would like to buy a sedan with 8 seats.",
|
||||
"Thought_1": "Our showroom carries various vehicle model. But I'm not sure whether we have a models that fits the user demand, I need to check our inventory.",
|
||||
"Action_1": {"name": "inventory", "input": "sedan with 8 seats."},
|
||||
"Observation_1": "Several model has 8 seats. Available color are black, red green"
|
||||
}
|
||||
{
|
||||
"Thought_2": "I have to ask the user what color he likes.",
|
||||
"Action_2": {"name": "chatbox", "input": "Which color do you like?"}
|
||||
"Observation_2": "I'll take black."
|
||||
}
|
||||
{
|
||||
"Thought_3": "There is only one model that fits the user preference. It's Yiem model A",
|
||||
"Action_3": {"name": "recommendation", "input": "I recommend a Yiem model A"}
|
||||
}
|
||||
|
||||
Let's begin!
|
||||
|
||||
$(JSON3.write(thoughtDict))
|
||||
{Thought_$nextThoughtIndice
|
||||
"""
|
||||
|
||||
prompt = YiemAgent.formatLLMtext_llama3instruct("system", _prompt)
|
||||
@show prompt
|
||||
msgMeta = Dict(:requestResponse => nothing,
|
||||
:msgPurpose => nothing,
|
||||
:receiverId => nothing,
|
||||
:getPost => nothing,
|
||||
:msgId => "4c7111e0-c30e-44c3-8f85-1c8b3f03a8be",
|
||||
:acknowledgestatus => nothing,
|
||||
:replyToMsgId => nothing,
|
||||
:msgFormatVersion => nothing,
|
||||
:mqttServerInfo => Dict(:port => 1883, :broker => "mqtt.yiem.cc"),
|
||||
:sendTopic => "/loadbalancer/requestingservice",
|
||||
:receiverName => "text2textinstruct",
|
||||
:replyTopic => nothing,
|
||||
:senderName => "decisionMaker",
|
||||
:senderSelfnote => nothing,
|
||||
:senderId => "testingSessionID",
|
||||
:timeStamp => "2024-05-04T08:06:23.561"
|
||||
)
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> prompt,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
_response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg)
|
||||
thoughtJsonStr = _response[:response][:text]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,87 +1,87 @@
|
||||
using Revise # remove when this package is completed
|
||||
using YiemAgent, GeneralUtils, JSON3, MQTTClient, Dates, UUIDs, DataStructures
|
||||
using Base.Threads
|
||||
|
||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||
|
||||
config = copy(JSON3.read("config.json"))
|
||||
|
||||
instanceInternalTopic = config[:serviceInternalTopic][:mqtttopic] * "/1"
|
||||
|
||||
client, connection = MakeConnection(config[:mqttServerInfo][:broker],
|
||||
config[:mqttServerInfo][:port])
|
||||
|
||||
receiveUserMsgChannel = Channel{Dict}(4)
|
||||
receiveInternalMsgChannel = Channel{Dict}(4)
|
||||
|
||||
msgMeta = GeneralUtils.generate_msgMeta(
|
||||
"N/A",
|
||||
replyTopic = config[:servicetopic][:mqtttopic] # ask frontend reply to this instance_chat_topic
|
||||
)
|
||||
|
||||
agentConfig = Dict(
|
||||
:mqttServerInfo=> config[:mqttServerInfo],
|
||||
:receivemsg=> Dict(
|
||||
:prompt=> config[:servicetopic][:mqtttopic], # topic to receive prompt i.e. frontend send msg to this topic
|
||||
:internal=> instanceInternalTopic,
|
||||
),
|
||||
:externalservice=> config[:externalservice],
|
||||
)
|
||||
|
||||
# Instantiate an agent
|
||||
tools=Dict( # update input format
|
||||
"askbox"=> Dict(
|
||||
:description => "<askbox tool description>Useful for when you need to ask the user for more context. Do not ask the user their own question.</askbox tool description>",
|
||||
:input => """<input>Input is a text in JSON format.</input><input example>{\"Q1\": \"How are you doing?\", \"Q2\": \"How may I help you?\"}</input example>""",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
# "winestock"=> Dict(
|
||||
# :description => "<winestock tool description>A handy tool for searching wine in your inventory that match the user preferences.</winestock tool description>",
|
||||
# :input => """<input>Input is a JSON-formatted string that contains a detailed and precise search query.</input><input example>{\"wine type\": \"rose\", \"price\": \"max 35\", \"sweetness level\": \"sweet\", \"intensity level\": \"light bodied\", \"Tannin level\": \"low\", \"Acidity level\": \"low\"}</input example>""",
|
||||
# :output => """<output>Output are wines that match the search query in JSON format.""",
|
||||
# :func => ChatAgent.winestock,
|
||||
# ),
|
||||
"finalanswer"=> Dict(
|
||||
:description => "<tool description>Useful for when you are ready to recommend wines to the user.</tool description>",
|
||||
:input => """<input format>{\"finalanswer\": \"some text\"}.</input format><input example>{\"finalanswer\": \"I recommend Zena Crown Vista\"}</input example>""",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
)
|
||||
|
||||
a = YiemAgent.sommelier(
|
||||
receiveUserMsgChannel,
|
||||
receiveInternalMsgChannel,
|
||||
agentConfig,
|
||||
name= "assistant",
|
||||
id= "testingSessionID", # agent instance id
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
input =
|
||||
OrderedDict{Symbol, Any}(:question => "Hello, I would like a get a bottle of wine", :thought_1 => "It's great that the user is looking for a bottle of wine. To give them a personalized recommendation, I need to know more about their preferences.", :action_1 => Dict{Symbol, Any}(:name => "chatbox", :input => "What occasion are you planning to use this wine for?"), :observation_1 => "We are holding a wedding party", :thought_2 => "A wedding party is a great occasion for a special bottle of wine. I need to know what type of food will be served, and how much the user is willing to spend.", :action_2 => Dict{Symbol, Any}(:name => "chatbox", :input => "What type of food will you be serving at the wedding?"), :observation_2 => "It will be Thai dishes.", :thought_3 => "The type of wine that pairs well with Thai dishes is usually a crisp and refreshing white wine, but I also need to consider the budget and personal preferences.", :action_3 => Dict{Symbol, Any}(:name => "chatbox", :input => "How much are you willing to spend on this bottle of wine?"), :observation_3 => "I would spend up to 50 bucks.", :thought_4 => "I have a good idea of the occasion, food, and budget. Now I need to know what type of wine the user is looking for.", :action_4 => Dict{Symbol, Any}(:name => "chatbox", :input => "What type of wine are you usually looking for? Red, White, Sparkling, Rose, Dessert or Fortified?"), :observation_4 => "I like full-bodied Red wine with low tannin.", :thought_5 => "Now that I have all the necessary information, I can start searching for a suitable wine in our inventory.", :action_5 => Dict{Symbol, Any}(:name => "winestock", :input => "red wine with low tannins"), :observation_5 => "I found the following wines in our stock: \n{\n 1: El Enemigo Cabernet Franc 2019\n2: Tantara Chardonnay 2017\n\n}\n", :thought_6 => "Now that I have the information about the wine, it's time to make a recommendation.", :action_6 => Dict{Symbol, Any}(:name => "recommendbox", :input => "El Enemigo Cabernet Franc 2019"), :observation_6 => "I don't like the one you recommend. I want dry wine.")
|
||||
|
||||
|
||||
result = YiemAgent.jsoncorrection(a, input)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
using Revise # remove when this package is completed
|
||||
using YiemAgent, GeneralUtils, JSON3, MQTTClient, Dates, UUIDs, DataStructures
|
||||
using Base.Threads
|
||||
|
||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||
|
||||
config = copy(JSON3.read("config.json"))
|
||||
|
||||
instanceInternalTopic = config[:serviceInternalTopic][:mqtttopic] * "/1"
|
||||
|
||||
client, connection = MakeConnection(config[:mqttServerInfo][:broker],
|
||||
config[:mqttServerInfo][:port])
|
||||
|
||||
receiveUserMsgChannel = Channel{Dict}(4)
|
||||
receiveInternalMsgChannel = Channel{Dict}(4)
|
||||
|
||||
msgMeta = GeneralUtils.generate_msgMeta(
|
||||
"N/A",
|
||||
replyTopic = config[:servicetopic][:mqtttopic] # ask frontend reply to this instance_chat_topic
|
||||
)
|
||||
|
||||
agentConfig = Dict(
|
||||
:mqttServerInfo=> config[:mqttServerInfo],
|
||||
:receivemsg=> Dict(
|
||||
:prompt=> config[:servicetopic][:mqtttopic], # topic to receive prompt i.e. frontend send msg to this topic
|
||||
:internal=> instanceInternalTopic,
|
||||
),
|
||||
:externalservice=> config[:externalservice],
|
||||
)
|
||||
|
||||
# Instantiate an agent
|
||||
tools=Dict( # update input format
|
||||
"askbox"=> Dict(
|
||||
:description => "<askbox tool description>Useful for when you need to ask the user for more context. Do not ask the user their own question.</askbox tool description>",
|
||||
:input => """<input>Input is a text in JSON format.</input><input example>{\"Q1\": \"How are you doing?\", \"Q2\": \"How may I help you?\"}</input example>""",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
# "winestock"=> Dict(
|
||||
# :description => "<winestock tool description>A handy tool for searching wine in your inventory that match the user preferences.</winestock tool description>",
|
||||
# :input => """<input>Input is a JSON-formatted string that contains a detailed and precise search query.</input><input example>{\"wine type\": \"rose\", \"price\": \"max 35\", \"sweetness level\": \"sweet\", \"intensity level\": \"light bodied\", \"Tannin level\": \"low\", \"Acidity level\": \"low\"}</input example>""",
|
||||
# :output => """<output>Output are wines that match the search query in JSON format.""",
|
||||
# :func => ChatAgent.winestock,
|
||||
# ),
|
||||
"finalanswer"=> Dict(
|
||||
:description => "<tool description>Useful for when you are ready to recommend wines to the user.</tool description>",
|
||||
:input => """<input format>{\"finalanswer\": \"some text\"}.</input format><input example>{\"finalanswer\": \"I recommend Zena Crown Vista\"}</input example>""",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
)
|
||||
|
||||
a = YiemAgent.sommelier(
|
||||
receiveUserMsgChannel,
|
||||
receiveInternalMsgChannel,
|
||||
agentConfig,
|
||||
name= "assistant",
|
||||
id= "testingSessionID", # agent instance id
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
input =
|
||||
OrderedDict{Symbol, Any}(:question => "Hello, I would like a get a bottle of wine", :thought_1 => "It's great that the user is looking for a bottle of wine. To give them a personalized recommendation, I need to know more about their preferences.", :action_1 => Dict{Symbol, Any}(:name => "chatbox", :input => "What occasion are you planning to use this wine for?"), :observation_1 => "We are holding a wedding party", :thought_2 => "A wedding party is a great occasion for a special bottle of wine. I need to know what type of food will be served, and how much the user is willing to spend.", :action_2 => Dict{Symbol, Any}(:name => "chatbox", :input => "What type of food will you be serving at the wedding?"), :observation_2 => "It will be Thai dishes.", :thought_3 => "The type of wine that pairs well with Thai dishes is usually a crisp and refreshing white wine, but I also need to consider the budget and personal preferences.", :action_3 => Dict{Symbol, Any}(:name => "chatbox", :input => "How much are you willing to spend on this bottle of wine?"), :observation_3 => "I would spend up to 50 bucks.", :thought_4 => "I have a good idea of the occasion, food, and budget. Now I need to know what type of wine the user is looking for.", :action_4 => Dict{Symbol, Any}(:name => "chatbox", :input => "What type of wine are you usually looking for? Red, White, Sparkling, Rose, Dessert or Fortified?"), :observation_4 => "I like full-bodied Red wine with low tannin.", :thought_5 => "Now that I have all the necessary information, I can start searching for a suitable wine in our inventory.", :action_5 => Dict{Symbol, Any}(:name => "winestock", :input => "red wine with low tannins"), :observation_5 => "I found the following wines in our stock: \n{\n 1: El Enemigo Cabernet Franc 2019\n2: Tantara Chardonnay 2017\n\n}\n", :thought_6 => "Now that I have the information about the wine, it's time to make a recommendation.", :action_6 => Dict{Symbol, Any}(:name => "recommendbox", :input => "El Enemigo Cabernet Franc 2019"), :observation_6 => "I don't like the one you recommend. I want dry wine.")
|
||||
|
||||
|
||||
result = YiemAgent.jsoncorrection(a, input)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,112 +1,112 @@
|
||||
using Revise # remove when this package is completed
|
||||
using YiemAgent, GeneralUtils, JSON3, MQTTClient, Dates, UUIDs
|
||||
using Base.Threads
|
||||
|
||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||
|
||||
config = copy(JSON3.read("config.json"))
|
||||
|
||||
instanceInternalTopic = config[:serviceInternalTopic][:mqtttopic] * "/1"
|
||||
|
||||
client, connection = MakeConnection(config[:mqttServerInfo][:broker],
|
||||
config[:mqttServerInfo][:port])
|
||||
|
||||
receiveUserMsgChannel = Channel{Dict}(4)
|
||||
receiveInternalMsgChannel = Channel{Dict}(4)
|
||||
|
||||
msgMeta = GeneralUtils.generate_msgMeta(
|
||||
"N/A",
|
||||
replyTopic = config[:servicetopic][:mqtttopic] # ask frontend reply to this instance_chat_topic
|
||||
)
|
||||
|
||||
agentConfig = Dict(
|
||||
:mqttServerInfo=> config[:mqttServerInfo],
|
||||
:receivemsg=> Dict(
|
||||
:prompt=> config[:servicetopic][:mqtttopic], # topic to receive prompt i.e. frontend send msg to this topic
|
||||
:internal=> instanceInternalTopic,
|
||||
),
|
||||
:externalservice=> config[:externalservice],
|
||||
)
|
||||
|
||||
# Instantiate an agent
|
||||
tools=Dict( # update input format
|
||||
"askbox"=> Dict(
|
||||
:description => "<askbox tool description>Useful for when you need to ask the user for more context. Do not ask the user their own question.</askbox tool description>",
|
||||
:input => """<input>Input is a text in JSON format.</input><input example>{\"Q1\": \"How are you doing?\", \"Q2\": \"How may I help you?\"}</input example>""",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
# "winestock"=> Dict(
|
||||
# :description => "<winestock tool description>A handy tool for searching wine in your inventory that match the user preferences.</winestock tool description>",
|
||||
# :input => """<input>Input is a JSON-formatted string that contains a detailed and precise search query.</input><input example>{\"wine type\": \"rose\", \"price\": \"max 35\", \"sweetness level\": \"sweet\", \"intensity level\": \"light bodied\", \"Tannin level\": \"low\", \"Acidity level\": \"low\"}</input example>""",
|
||||
# :output => """<output>Output are wines that match the search query in JSON format.""",
|
||||
# :func => ChatAgent.winestock,
|
||||
# ),
|
||||
"finalanswer"=> Dict(
|
||||
:description => "<tool description>Useful for when you are ready to recommend wines to the user.</tool description>",
|
||||
:input => """<input format>{\"finalanswer\": \"some text\"}.</input format><input example>{\"finalanswer\": \"I recommend Zena Crown Vista\"}</input example>""",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
)
|
||||
|
||||
a = YiemAgent.sommelier(
|
||||
agentConfig,
|
||||
name="assistant",
|
||||
id="testingSessionID", # agent instance id
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
# response = YiemAgent.conversation(a, Dict(:text=> "newtopic",) )
|
||||
|
||||
response = YiemAgent.conversation(a, Dict(:text=> "Hello, I would like a get a bottle of wine",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
) )
|
||||
println("---> YiemAgent: ", response)
|
||||
|
||||
#BUG mcts do not start at current chat history
|
||||
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,
|
||||
) )
|
||||
println("---> YiemAgent: ", response)
|
||||
|
||||
|
||||
|
||||
|
||||
dummyinput = "price below 50, full-bodied red wine with sweetness level 2, low tannin level and medium acidity level, Thai dishes"
|
||||
response = YiemAgent.winestock(a, dummyinput)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
"""
|
||||
Write me SQL command to search the database for wines that fits: {"wine_type": "red","sweetness": 2,"acidity": 3,"tannin": 1,"intensity": 5}
|
||||
"""
|
||||
|
||||
|
||||
mctsparam = Dict{Symbol, Any}()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
using Revise # remove when this package is completed
|
||||
using YiemAgent, GeneralUtils, JSON3, MQTTClient, Dates, UUIDs
|
||||
using Base.Threads
|
||||
|
||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||
|
||||
config = copy(JSON3.read("config.json"))
|
||||
|
||||
instanceInternalTopic = config[:serviceInternalTopic][:mqtttopic] * "/1"
|
||||
|
||||
client, connection = MakeConnection(config[:mqttServerInfo][:broker],
|
||||
config[:mqttServerInfo][:port])
|
||||
|
||||
receiveUserMsgChannel = Channel{Dict}(4)
|
||||
receiveInternalMsgChannel = Channel{Dict}(4)
|
||||
|
||||
msgMeta = GeneralUtils.generate_msgMeta(
|
||||
"N/A",
|
||||
replyTopic = config[:servicetopic][:mqtttopic] # ask frontend reply to this instance_chat_topic
|
||||
)
|
||||
|
||||
agentConfig = Dict(
|
||||
:mqttServerInfo=> config[:mqttServerInfo],
|
||||
:receivemsg=> Dict(
|
||||
:prompt=> config[:servicetopic][:mqtttopic], # topic to receive prompt i.e. frontend send msg to this topic
|
||||
:internal=> instanceInternalTopic,
|
||||
),
|
||||
:externalservice=> config[:externalservice],
|
||||
)
|
||||
|
||||
# Instantiate an agent
|
||||
tools=Dict( # update input format
|
||||
"askbox"=> Dict(
|
||||
:description => "<askbox tool description>Useful for when you need to ask the user for more context. Do not ask the user their own question.</askbox tool description>",
|
||||
:input => """<input>Input is a text in JSON format.</input><input example>{\"Q1\": \"How are you doing?\", \"Q2\": \"How may I help you?\"}</input example>""",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
# "winestock"=> Dict(
|
||||
# :description => "<winestock tool description>A handy tool for searching wine in your inventory that match the user preferences.</winestock tool description>",
|
||||
# :input => """<input>Input is a JSON-formatted string that contains a detailed and precise search query.</input><input example>{\"wine type\": \"rose\", \"price\": \"max 35\", \"sweetness level\": \"sweet\", \"intensity level\": \"light bodied\", \"Tannin level\": \"low\", \"Acidity level\": \"low\"}</input example>""",
|
||||
# :output => """<output>Output are wines that match the search query in JSON format.""",
|
||||
# :func => ChatAgent.winestock,
|
||||
# ),
|
||||
"finalanswer"=> Dict(
|
||||
:description => "<tool description>Useful for when you are ready to recommend wines to the user.</tool description>",
|
||||
:input => """<input format>{\"finalanswer\": \"some text\"}.</input format><input example>{\"finalanswer\": \"I recommend Zena Crown Vista\"}</input example>""",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
)
|
||||
|
||||
a = YiemAgent.sommelier(
|
||||
agentConfig,
|
||||
name="assistant",
|
||||
id="testingSessionID", # agent instance id
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
# response = YiemAgent.conversation(a, Dict(:text=> "newtopic",) )
|
||||
|
||||
response = YiemAgent.conversation(a, Dict(:text=> "Hello, I would like a get a bottle of wine",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
) )
|
||||
println("---> YiemAgent: ", response)
|
||||
|
||||
#BUG mcts do not start at current chat history
|
||||
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,
|
||||
) )
|
||||
println("---> YiemAgent: ", response)
|
||||
|
||||
|
||||
|
||||
|
||||
dummyinput = "price below 50, full-bodied red wine with sweetness level 2, low tannin level and medium acidity level, Thai dishes"
|
||||
response = YiemAgent.winestock(a, dummyinput)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
"""
|
||||
Write me SQL command to search the database for wines that fits: {"wine_type": "red","sweetness": 2,"acidity": 3,"tannin": 1,"intensity": 5}
|
||||
"""
|
||||
|
||||
|
||||
mctsparam = Dict{Symbol, Any}()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,190 +1,190 @@
|
||||
using Revise
|
||||
using YiemAgent, GeneralUtils, JSON3, DataStructures
|
||||
|
||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||
|
||||
msgMeta = Dict(:requestResponse => nothing,
|
||||
:msgPurpose => nothing,
|
||||
:receiverId => nothing,
|
||||
:getPost => nothing,
|
||||
:msgId => "4c7111e0-c30e-44c3-8f85-1c8b3f03a8be",
|
||||
:acknowledgestatus => nothing,
|
||||
:replyToMsgId => "dummyid",
|
||||
:msgFormatVersion => nothing,
|
||||
:mqttServerInfo => Dict(:port => 1883, :broker => "mqtt.yiem.cc"),
|
||||
:sendTopic => "/testingSessionID",
|
||||
:receiverName => "wineassistant",
|
||||
:replyTopic => nothing,
|
||||
:senderName => "test_1",
|
||||
:senderSelfnote => nothing,
|
||||
:senderId => nothing,
|
||||
:timeStamp => "2024-05-04T08:06:23.561"
|
||||
)
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "We are holding a wedding party",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "It will be Thai dishes.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "I would spend up to 50 bucks.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "I like dry, full-bodied red wine with low tannin.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "What do you have?",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "Dry wine please.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "You did not gave me any choice.",
|
||||
:select=> nothing,
|
||||
:reward=> -1,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "You don't need to ask me. Just tell me already!",
|
||||
:select=> nothing,
|
||||
:reward=> -1,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "I like dry wine with fruity flavors.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "OK, I'll take it.",
|
||||
:select=> 1,
|
||||
:reward=> 1,
|
||||
:isterminal=> true,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "Yes.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "I like dry wine with medium acidity.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
using Revise
|
||||
using YiemAgent, GeneralUtils, JSON3, DataStructures
|
||||
|
||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||
|
||||
msgMeta = Dict(:requestResponse => nothing,
|
||||
:msgPurpose => nothing,
|
||||
:receiverId => nothing,
|
||||
:getPost => nothing,
|
||||
:msgId => "4c7111e0-c30e-44c3-8f85-1c8b3f03a8be",
|
||||
:acknowledgestatus => nothing,
|
||||
:replyToMsgId => "dummyid",
|
||||
:msgFormatVersion => nothing,
|
||||
:mqttServerInfo => Dict(:port => 1883, :broker => "mqtt.yiem.cc"),
|
||||
:sendTopic => "/testingSessionID",
|
||||
:receiverName => "wineassistant",
|
||||
:replyTopic => nothing,
|
||||
:senderName => "test_1",
|
||||
:senderSelfnote => nothing,
|
||||
:senderId => nothing,
|
||||
:timeStamp => "2024-05-04T08:06:23.561"
|
||||
)
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "We are holding a wedding party",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "It will be Thai dishes.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "I would spend up to 50 bucks.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "I like dry, full-bodied red wine with low tannin.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "What do you have?",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "Dry wine please.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "You did not gave me any choice.",
|
||||
:select=> nothing,
|
||||
:reward=> -1,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "You don't need to ask me. Just tell me already!",
|
||||
:select=> nothing,
|
||||
:reward=> -1,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "I like dry wine with fruity flavors.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "OK, I'll take it.",
|
||||
:select=> 1,
|
||||
:reward=> 1,
|
||||
:isterminal=> true,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "Yes.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> "I like dry wine with medium acidity.",
|
||||
:select=> nothing,
|
||||
:reward=> 0,
|
||||
:isterminal=> false,
|
||||
)
|
||||
)
|
||||
result = GeneralUtils.sendMqttMsg(outgoingMsg)
|
||||
|
||||
|
||||
|
||||
@@ -1,130 +1,130 @@
|
||||
using Revise # remove when this package is completed
|
||||
using YiemAgent, GeneralUtils, JSON3, MQTTClient, Dates, UUIDs, DataStructures
|
||||
using Base.Threads
|
||||
|
||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||
|
||||
config = copy(JSON3.read("config.json"))
|
||||
|
||||
instanceInternalTopic = config[:serviceInternalTopic][:mqtttopic] * "/1"
|
||||
|
||||
client, connection = MakeConnection(config[:mqttServerInfo][:broker],
|
||||
config[:mqttServerInfo][:port])
|
||||
|
||||
receiveUserMsgChannel = Channel{Dict}(4)
|
||||
receiveInternalMsgChannel = Channel{Dict}(4)
|
||||
|
||||
msgMeta = GeneralUtils.generate_msgMeta(
|
||||
"N/A",
|
||||
replyTopic = config[:servicetopic][:mqtttopic] # ask frontend reply to this instance_chat_topic
|
||||
)
|
||||
|
||||
agentConfig = Dict(
|
||||
:mqttServerInfo=> config[:mqttServerInfo],
|
||||
:receivemsg=> Dict(
|
||||
:prompt=> config[:servicetopic][:mqtttopic], # topic to receive prompt i.e. frontend send msg to this topic
|
||||
:internal=> instanceInternalTopic,
|
||||
),
|
||||
:externalservice=> config[:externalservice],
|
||||
)
|
||||
|
||||
# Instantiate an agent
|
||||
tools=Dict( # update input format
|
||||
"askbox"=> Dict(
|
||||
:description => "<askbox tool description>Useful for when you need to ask the user for more context. Do not ask the user their own question.</askbox tool description>",
|
||||
:input => """<input>Input is a text in JSON format.</input><input example>{\"Q1\": \"How are you doing?\", \"Q2\": \"How may I help you?\"}</input example>""",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
# "winestock"=> Dict(
|
||||
# :description => "<winestock tool description>A handy tool for searching wine in your inventory that match the user preferences.</winestock tool description>",
|
||||
# :input => """<input>Input is a JSON-formatted string that contains a detailed and precise search query.</input><input example>{\"wine type\": \"rose\", \"price\": \"max 35\", \"sweetness level\": \"sweet\", \"intensity level\": \"light bodied\", \"Tannin level\": \"low\", \"Acidity level\": \"low\"}</input example>""",
|
||||
# :output => """<output>Output are wines that match the search query in JSON format.""",
|
||||
# :func => ChatAgent.winestock,
|
||||
# ),
|
||||
"finalanswer"=> Dict(
|
||||
:description => "<tool description>Useful for when you are ready to recommend wines to the user.</tool description>",
|
||||
:input => """<input format>{\"finalanswer\": \"some text\"}.</input format><input example>{\"finalanswer\": \"I recommend Zena Crown Vista\"}</input example>""",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
)
|
||||
|
||||
a = YiemAgent.sommelier(
|
||||
receiveUserMsgChannel,
|
||||
receiveInternalMsgChannel,
|
||||
agentConfig,
|
||||
name= "assistant",
|
||||
id= "testingSessionID", # agent instance id
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
|
||||
input =
|
||||
OrderedDict{Symbol, Any}(
|
||||
:question => "Hello, I would like a get a bottle of wine",
|
||||
:thought_1 => "A customer wants to buy a bottle of wine. Before making a recommendation, I need to know more about their preferences.",
|
||||
:action_1 => Dict{Symbol, Any}(
|
||||
:name => "chatbox",
|
||||
:input => "What is the occasion for which you're buying this wine?"
|
||||
),
|
||||
:observation_1 => "We are holding a wedding party",
|
||||
|
||||
:thought_2 => "A wedding party, that's a great occasion! The customer might be looking for a celebratory drink. Let me ask some more questions to narrow down the options.",
|
||||
:action_2 => Dict{Symbol, Any}(
|
||||
:name => "chatbox",
|
||||
:input => "What type of food will you be serving at the wedding?"
|
||||
),
|
||||
:observation_2 => "It will be Thai dishes.",
|
||||
|
||||
:thought_3 => "With Thai food, I should recommend a wine that complements its spicy and savory flavors. And since it's a celebratory occasion, the customer might prefer a full-bodied wine.",
|
||||
:action_3 => Dict{Symbol, Any}(
|
||||
:name => "chatbox",
|
||||
:input => "What is your budget for this bottle of wine?"
|
||||
),
|
||||
:observation_3 => "I would spend up to 50 bucks.",
|
||||
|
||||
:thought_4 => "Now that I have some more information, it's time to narrow down the options.",
|
||||
:action_4 => Dict{Symbol, Any}(
|
||||
:name => "winestock",
|
||||
:input => "red wine with full body, pairs well with spicy food, budget \$50"),
|
||||
:observation_4 => "I found the following wines in our stock: \n{\n 1: El Enemigo Cabernet Franc 2019\n2: Tantara Chardonnay 2017\n\n}\n",
|
||||
|
||||
:thought_5 => "Now that I have a list of potential wines, I need to know more about the customer's taste preferences.",
|
||||
:action_5 => Dict{Symbol, Any}(
|
||||
:name => "chatbox",
|
||||
:input => "What type of wine characteristics are you looking for? (e.g. t.e.g. tannin level, sweetness, intensity, acidity)"
|
||||
),
|
||||
:observation_5 => "I like full-bodied Red wine with low tannin.",
|
||||
|
||||
:thought_6 => "Now that I have more information about the customer's preferences, it's time to make a recommendation.",
|
||||
:action_6 => Dict{Symbol, Any}(
|
||||
:name => "recommendbox",
|
||||
:input => "El Enemigo Cabernet Franc 2019"
|
||||
),
|
||||
:observation_6 => "I don't like the one you recommend. I want dry wine."
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
result = YiemAgent.reflector(a, input)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
using Revise # remove when this package is completed
|
||||
using YiemAgent, GeneralUtils, JSON3, MQTTClient, Dates, UUIDs, DataStructures
|
||||
using Base.Threads
|
||||
|
||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
||||
|
||||
config = copy(JSON3.read("config.json"))
|
||||
|
||||
instanceInternalTopic = config[:serviceInternalTopic][:mqtttopic] * "/1"
|
||||
|
||||
client, connection = MakeConnection(config[:mqttServerInfo][:broker],
|
||||
config[:mqttServerInfo][:port])
|
||||
|
||||
receiveUserMsgChannel = Channel{Dict}(4)
|
||||
receiveInternalMsgChannel = Channel{Dict}(4)
|
||||
|
||||
msgMeta = GeneralUtils.generate_msgMeta(
|
||||
"N/A",
|
||||
replyTopic = config[:servicetopic][:mqtttopic] # ask frontend reply to this instance_chat_topic
|
||||
)
|
||||
|
||||
agentConfig = Dict(
|
||||
:mqttServerInfo=> config[:mqttServerInfo],
|
||||
:receivemsg=> Dict(
|
||||
:prompt=> config[:servicetopic][:mqtttopic], # topic to receive prompt i.e. frontend send msg to this topic
|
||||
:internal=> instanceInternalTopic,
|
||||
),
|
||||
:externalservice=> config[:externalservice],
|
||||
)
|
||||
|
||||
# Instantiate an agent
|
||||
tools=Dict( # update input format
|
||||
"askbox"=> Dict(
|
||||
:description => "<askbox tool description>Useful for when you need to ask the user for more context. Do not ask the user their own question.</askbox tool description>",
|
||||
:input => """<input>Input is a text in JSON format.</input><input example>{\"Q1\": \"How are you doing?\", \"Q2\": \"How may I help you?\"}</input example>""",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
# "winestock"=> Dict(
|
||||
# :description => "<winestock tool description>A handy tool for searching wine in your inventory that match the user preferences.</winestock tool description>",
|
||||
# :input => """<input>Input is a JSON-formatted string that contains a detailed and precise search query.</input><input example>{\"wine type\": \"rose\", \"price\": \"max 35\", \"sweetness level\": \"sweet\", \"intensity level\": \"light bodied\", \"Tannin level\": \"low\", \"Acidity level\": \"low\"}</input example>""",
|
||||
# :output => """<output>Output are wines that match the search query in JSON format.""",
|
||||
# :func => ChatAgent.winestock,
|
||||
# ),
|
||||
"finalanswer"=> Dict(
|
||||
:description => "<tool description>Useful for when you are ready to recommend wines to the user.</tool description>",
|
||||
:input => """<input format>{\"finalanswer\": \"some text\"}.</input format><input example>{\"finalanswer\": \"I recommend Zena Crown Vista\"}</input example>""",
|
||||
:output => "" ,
|
||||
:func => nothing,
|
||||
),
|
||||
)
|
||||
|
||||
a = YiemAgent.sommelier(
|
||||
receiveUserMsgChannel,
|
||||
receiveInternalMsgChannel,
|
||||
agentConfig,
|
||||
name= "assistant",
|
||||
id= "testingSessionID", # agent instance id
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
|
||||
input =
|
||||
OrderedDict{Symbol, Any}(
|
||||
:question => "Hello, I would like a get a bottle of wine",
|
||||
:thought_1 => "A customer wants to buy a bottle of wine. Before making a recommendation, I need to know more about their preferences.",
|
||||
:action_1 => Dict{Symbol, Any}(
|
||||
:name => "chatbox",
|
||||
:input => "What is the occasion for which you're buying this wine?"
|
||||
),
|
||||
:observation_1 => "We are holding a wedding party",
|
||||
|
||||
:thought_2 => "A wedding party, that's a great occasion! The customer might be looking for a celebratory drink. Let me ask some more questions to narrow down the options.",
|
||||
:action_2 => Dict{Symbol, Any}(
|
||||
:name => "chatbox",
|
||||
:input => "What type of food will you be serving at the wedding?"
|
||||
),
|
||||
:observation_2 => "It will be Thai dishes.",
|
||||
|
||||
:thought_3 => "With Thai food, I should recommend a wine that complements its spicy and savory flavors. And since it's a celebratory occasion, the customer might prefer a full-bodied wine.",
|
||||
:action_3 => Dict{Symbol, Any}(
|
||||
:name => "chatbox",
|
||||
:input => "What is your budget for this bottle of wine?"
|
||||
),
|
||||
:observation_3 => "I would spend up to 50 bucks.",
|
||||
|
||||
:thought_4 => "Now that I have some more information, it's time to narrow down the options.",
|
||||
:action_4 => Dict{Symbol, Any}(
|
||||
:name => "winestock",
|
||||
:input => "red wine with full body, pairs well with spicy food, budget \$50"),
|
||||
:observation_4 => "I found the following wines in our stock: \n{\n 1: El Enemigo Cabernet Franc 2019\n2: Tantara Chardonnay 2017\n\n}\n",
|
||||
|
||||
:thought_5 => "Now that I have a list of potential wines, I need to know more about the customer's taste preferences.",
|
||||
:action_5 => Dict{Symbol, Any}(
|
||||
:name => "chatbox",
|
||||
:input => "What type of wine characteristics are you looking for? (e.g. t.e.g. tannin level, sweetness, intensity, acidity)"
|
||||
),
|
||||
:observation_5 => "I like full-bodied Red wine with low tannin.",
|
||||
|
||||
:thought_6 => "Now that I have more information about the customer's preferences, it's time to make a recommendation.",
|
||||
:action_6 => Dict{Symbol, Any}(
|
||||
:name => "recommendbox",
|
||||
:input => "El Enemigo Cabernet Franc 2019"
|
||||
),
|
||||
:observation_6 => "I don't like the one you recommend. I want dry wine."
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
result = YiemAgent.reflector(a, input)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user