update
This commit is contained in:
@@ -3,7 +3,7 @@ module llmfunction
|
||||
export virtualWineUserChatbox, jsoncorrection, winestock,
|
||||
virtualWineUserRecommendbox, userChatbox, userRecommendbox
|
||||
|
||||
using HTTP, JSON3, URIs, Random
|
||||
using HTTP, JSON3, URIs, Random, PrettyPrinting
|
||||
using GeneralUtils
|
||||
using ..type, ..util
|
||||
|
||||
@@ -164,28 +164,119 @@ julia>
|
||||
|
||||
# TODO
|
||||
- [] update docs
|
||||
- [x] write a prompt for virtual customer
|
||||
|
||||
# Signature
|
||||
"""
|
||||
function virtualWineUserChatbox(a::T1, input::T2
|
||||
function virtualWineUserChatbox(a::T1, input::T2, virtualCustomerChatHistory
|
||||
)::Union{Tuple{String, Number, Number, Bool}, Tuple{String, Nothing, Number, Bool}} where {T1<:agent, T2<:AbstractString}
|
||||
|
||||
# put in model format
|
||||
virtualWineCustomer = a.config[:externalservice][:virtualWineCustomer_1]
|
||||
llminfo = virtualWineCustomer[:llminfo]
|
||||
prompt =
|
||||
if llminfo[:name] == "llama3instruct"
|
||||
formatLLMtext_llama3instruct("assistant", input)
|
||||
else
|
||||
error("llm model name is not defied yet $(@__LINE__)")
|
||||
previouswines =
|
||||
"""
|
||||
You have the following wines previously:
|
||||
|
||||
"""
|
||||
|
||||
systemmsg =
|
||||
"""
|
||||
You find yourself in a well-stocked wine store, engaged in a conversation with the store's knowledgeable sommelier.
|
||||
You're on a quest to find a bottle of wine that aligns with your specific preferences and requirements.
|
||||
|
||||
The ideal wine you're seeking should meet the following criteria:
|
||||
1. It should fit within your budget.
|
||||
2. It should be suitable for the occasion you're planning.
|
||||
3. It should pair well with the food you intend to serve.
|
||||
4. It should be of a particular type of wine you prefer.
|
||||
5. It should possess certain characteristics, including:
|
||||
- The level of sweetness.
|
||||
- The intensity of its flavor.
|
||||
- The amount of tannin it contains.
|
||||
- Its acidity level.
|
||||
|
||||
Here's the criteria details:
|
||||
{
|
||||
"budget": 50,
|
||||
"occasion": "graduation ceremony",
|
||||
"food pairing": "Thai food",
|
||||
"type of wine": "red",
|
||||
"wine sweetness level": "dry",
|
||||
"wine intensity level": "full-bodied",
|
||||
"wine tannin level": "low",
|
||||
"wine acidity level": "medium",
|
||||
}
|
||||
|
||||
You should only respond with "text", "select", "reward", "isterminal" steps.
|
||||
"text" is your conversation.
|
||||
"select" is an integer. Choose an option when presented with choices, or leave it null if none of the options satisfy you or if no choices are available.
|
||||
"reward" is an integer, it can be three number:
|
||||
1) 1 if you find the right wine.
|
||||
2) 0 if you don’t find the ideal wine.
|
||||
3) -1 if you’re dissatisfied with the sommelier’s response.
|
||||
"isterminal" can be false if you still want to talk with the sommelier, true otherwise.
|
||||
|
||||
You should only respond in JSON format as describe below:
|
||||
{
|
||||
"text": "your conversation",
|
||||
"select": null,
|
||||
"reward": 0,
|
||||
"isterminal": false
|
||||
}
|
||||
|
||||
Here are some examples:
|
||||
{
|
||||
"text": "My budget is 30 USD.",
|
||||
"select": null,
|
||||
"reward": 0,
|
||||
"isterminal": false
|
||||
}
|
||||
{
|
||||
"text": "I like the 2nd option.",
|
||||
"select": 2,
|
||||
"reward": 1,
|
||||
"isterminal": true
|
||||
}
|
||||
|
||||
Let's begin!
|
||||
"""
|
||||
|
||||
pushfirst!(virtualCustomerChatHistory, Dict(:name=> "system", :text=> systemmsg))
|
||||
|
||||
# replace the :user key in chathistory to allow the virtual wine customer AI roleplay
|
||||
chathistory::Vector{Dict{Symbol, Any}} = Vector{Dict{Symbol, Any}}()
|
||||
for i in virtualCustomerChatHistory
|
||||
newdict = Dict()
|
||||
newdict[:name] =
|
||||
if i[:name] == "user"
|
||||
"you"
|
||||
elseif i[:name] == "assistant"
|
||||
"sommelier"
|
||||
else
|
||||
i[:name]
|
||||
end
|
||||
|
||||
newdict[:text] = i[:text]
|
||||
push!(chathistory, newdict)
|
||||
end
|
||||
|
||||
push!(chathistory, Dict(:name=> "assistant", :text=> input))
|
||||
|
||||
# put in model format
|
||||
prompt = formatLLMtext(chathistory, "llama3instruct")
|
||||
prompt *=
|
||||
"""
|
||||
<|start_header_id|>you<|end_header_id|>
|
||||
{"text"
|
||||
"""
|
||||
|
||||
pprint(prompt)
|
||||
externalService = a.config[:externalservice][:text2textinstruct]
|
||||
|
||||
# send formatted input to user using GeneralUtils.sendReceiveMqttMsg
|
||||
msgMeta = GeneralUtils.generate_msgMeta(
|
||||
virtualWineCustomer[:mqtttopic],
|
||||
externalService[:mqtttopic],
|
||||
senderName= "virtualWineUserChatbox",
|
||||
senderId= a.id,
|
||||
receiverName= "virtualWineCustomer",
|
||||
receiverName= "text2textinstruct",
|
||||
mqttBroker= a.config[:mqttServerInfo][:broker],
|
||||
mqttBrokerPort= a.config[:mqttServerInfo][:port],
|
||||
msgId = "dummyid" #CHANGE remove after testing finished
|
||||
@@ -201,10 +292,33 @@ function virtualWineUserChatbox(a::T1, input::T2
|
||||
attempt = 0
|
||||
for attempt in 1:5
|
||||
try
|
||||
result = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120)
|
||||
response = result[:response]
|
||||
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120)
|
||||
_responseJsonStr = response[:response][:text]
|
||||
expectedJsonExample =
|
||||
"""
|
||||
Here is an expected JSON format:
|
||||
{
|
||||
"text": "...",
|
||||
"select": "...",
|
||||
"reward": "...",
|
||||
"isterminal": "..."
|
||||
}
|
||||
"""
|
||||
responseJsonStr = jsoncorrection(a, _responseJsonStr, expectedJsonExample)
|
||||
responseDict = copy(JSON3.read(responseJsonStr))
|
||||
|
||||
return (response[:text], response[:select], response[:reward], response[:isterminal])
|
||||
text = responseDict[:text]
|
||||
select = responseDict[:select] == "null" ? nothing : responseDict[:select]
|
||||
reward = responseDict[:reward]
|
||||
isterminal = responseDict[:isterminal]
|
||||
|
||||
if text != "" && select != "" && reward != "" && isterminal != ""
|
||||
# pass test
|
||||
else
|
||||
error("virtual customer not answer correctly")
|
||||
end
|
||||
|
||||
return (text, select, reward, isterminal)
|
||||
catch e
|
||||
io = IOBuffer()
|
||||
showerror(io, e)
|
||||
@@ -218,6 +332,57 @@ function virtualWineUserChatbox(a::T1, input::T2
|
||||
error("virtualWineUserChatbox failed to get a response")
|
||||
end
|
||||
|
||||
# function virtualWineUserChatbox(a::T1, input::T2
|
||||
# )::Union{Tuple{String, Number, Number, Bool}, Tuple{String, Nothing, Number, Bool}} where {T1<:agent, T2<:AbstractString}
|
||||
|
||||
# # put in model format
|
||||
# virtualWineCustomer = a.config[:externalservice][:virtualWineCustomer_1]
|
||||
# llminfo = virtualWineCustomer[:llminfo]
|
||||
# prompt =
|
||||
# if llminfo[:name] == "llama3instruct"
|
||||
# formatLLMtext_llama3instruct("assistant", input)
|
||||
# else
|
||||
# error("llm model name is not defied yet $(@__LINE__)")
|
||||
# end
|
||||
|
||||
# # send formatted input to user using GeneralUtils.sendReceiveMqttMsg
|
||||
# msgMeta = GeneralUtils.generate_msgMeta(
|
||||
# virtualWineCustomer[:mqtttopic],
|
||||
# senderName= "virtualWineUserChatbox",
|
||||
# senderId= a.id,
|
||||
# receiverName= "virtualWineCustomer",
|
||||
# mqttBroker= a.config[:mqttServerInfo][:broker],
|
||||
# mqttBrokerPort= a.config[:mqttServerInfo][:port],
|
||||
# msgId = "dummyid" #CHANGE remove after testing finished
|
||||
# )
|
||||
|
||||
# outgoingMsg = Dict(
|
||||
# :msgMeta=> msgMeta,
|
||||
# :payload=> Dict(
|
||||
# :text=> prompt,
|
||||
# )
|
||||
# )
|
||||
|
||||
# attempt = 0
|
||||
# for attempt in 1:5
|
||||
# try
|
||||
# result = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120)
|
||||
# response = result[:response]
|
||||
|
||||
# return (response[:text], response[:select], response[:reward], response[:isterminal])
|
||||
# catch e
|
||||
# io = IOBuffer()
|
||||
# showerror(io, e)
|
||||
# errorMsg = String(take!(io))
|
||||
# st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
|
||||
# println("")
|
||||
# @warn "Error occurred: $errorMsg\n$st"
|
||||
# println("")
|
||||
# end
|
||||
# end
|
||||
# error("virtualWineUserChatbox failed to get a response")
|
||||
# end
|
||||
|
||||
|
||||
""" Search wine in stock.
|
||||
|
||||
@@ -239,7 +404,7 @@ julia> result = winestock(agent, input)
|
||||
|
||||
# TODO
|
||||
[] update docs
|
||||
[PENDING] implement the function
|
||||
[WORKING] implement the function
|
||||
|
||||
# Signature
|
||||
"""
|
||||
@@ -302,8 +467,8 @@ function jsoncorrection(a::T1, input::T2,
|
||||
_prompt =
|
||||
"""
|
||||
Your goal are:
|
||||
1) Use the info why the given JSON string failed to load and provide a corrected version that can be loaded by Python's json.load function.
|
||||
2) The user need Corrected JSON string only. Do not provide any other info.
|
||||
1) Use the expected JSON format as a guideline to check why the given JSON string failed to load and provide a corrected version that can be loaded by Python's json.load function.
|
||||
2) Provide Corrected JSON string only. Do not provide any other info.
|
||||
|
||||
$correctJsonExample
|
||||
|
||||
|
||||
Reference in New Issue
Block a user