update
This commit is contained in:
308
src/interface.jl
308
src/interface.jl
@@ -308,100 +308,6 @@ function updatePlan(a::agentReflex)
|
||||
|
||||
end
|
||||
|
||||
# function selfAwareness(a::agentReflex)
|
||||
|
||||
# getonlykeys = ["Actinput", "Obs"]
|
||||
# worknoplan = similar(a.memory[:shortterm])
|
||||
# for (k, v) in a.memory[:shortterm]
|
||||
# count = 0
|
||||
# for i in getonlykeys
|
||||
# if occursin(i, k)
|
||||
# count += 1
|
||||
# end
|
||||
# end
|
||||
# if count != 0
|
||||
# worknoplan[k] = v
|
||||
# end
|
||||
# end
|
||||
|
||||
# work = dictToString(worknoplan)
|
||||
|
||||
# aboutYourself =
|
||||
# """
|
||||
# Your name is $(a.agentName)
|
||||
# $(a.roles[a.role])
|
||||
|
||||
# """
|
||||
|
||||
# prompt =
|
||||
# """
|
||||
# <|system|>
|
||||
# <About yourself>
|
||||
# $aboutYourself
|
||||
# $(a.roleSpecificInstruction[a.role])
|
||||
# </About yourself>
|
||||
# <Your earlier work>
|
||||
# $work
|
||||
# </Your earlier work>
|
||||
# <Your keyword memory>
|
||||
# $(JSON3.write(a.memory[:keyword]))
|
||||
# </Your keyword memory>
|
||||
# <Your job>
|
||||
# Use the following format strictly:
|
||||
# Info extraction: repeat all important info from the latest observed result thoroughly
|
||||
# Info mapping: based on extracted info, explicitly state what each info could match which keyword memory's key
|
||||
# Info matching: using JSON format, what key in my memory matches which info
|
||||
# </Your job>
|
||||
|
||||
# <Example>
|
||||
# <Your earlier work>
|
||||
# The user wants to buy an electric SUV car under 20000 dollars.
|
||||
# </Your earlier work>
|
||||
# <Your keyword memory>
|
||||
# {"car type": null, "color": null, "financing": null}
|
||||
# </Your keyword memory>
|
||||
# Info extraction:
|
||||
# - The user is buying an electric SUV car.
|
||||
# Info mapping:
|
||||
# - SUV could matches "car type" key
|
||||
# - electric could matches "engine type" key
|
||||
# Info matching: {"car type": "SUV", "engine type": "electric motor", "color": null, "financing": null}
|
||||
# </Example>
|
||||
# </s>
|
||||
# <|assistant|>
|
||||
# Info extraction:
|
||||
# """
|
||||
# response = sendReceivePrompt(a, prompt, max_tokens=1024, temperature=0.2, timeout=180,
|
||||
# stopword=["/n/n", "END", "End", "Obs", "<|", "</"])
|
||||
# response = split(response, "<|")[1]
|
||||
# response = split(response, "</")[1]
|
||||
# response = "Info extraction:" * response
|
||||
|
||||
# println("")
|
||||
# @show selfaware_1 = response
|
||||
|
||||
# headerToDetect = ["Info extraction:", "Info mapping:", "Info matching:", "Actinput"]
|
||||
# headers = detectCharacters(response, headerToDetect)
|
||||
|
||||
# # headers[1:2] is for when LLM generate more than a paire of "Info extraction" and "Info matching", discard the rest
|
||||
# chunkedtext = chunktext(response, headers[1:3])
|
||||
# println("")
|
||||
# _infomatch = chunkedtext["Info matching:"]
|
||||
# _infomatch = GeneralUtils.getStringBetweenCharacters(_infomatch, '{', '}', endCharLocation="next")
|
||||
# infomatch = copy(JSON3.read(_infomatch))
|
||||
|
||||
# println("")
|
||||
# @show chunkedtext
|
||||
|
||||
# keywordMemoryUpdate!(a.memory[:keyword], infomatch)
|
||||
|
||||
# response = "What I know about user:" * JSON3.write(a.memory[:keyword]) # * response
|
||||
# println("")
|
||||
# @show selfaware_2 = response
|
||||
|
||||
|
||||
# return response
|
||||
# end
|
||||
|
||||
function selfAwareness(a::agentReflex)
|
||||
|
||||
@@ -433,7 +339,7 @@ function selfAwareness(a::agentReflex)
|
||||
$(a.roles[a.role])
|
||||
|
||||
"""
|
||||
#WORKING may be I need to use "- $k is $v" because LLM skip the key for sweetness
|
||||
|
||||
prompt =
|
||||
"""
|
||||
<s>
|
||||
@@ -514,6 +420,189 @@ function selfAwareness(a::agentReflex)
|
||||
return response
|
||||
end
|
||||
|
||||
function sentenceToKeywordMemory(a::agentReflex)
|
||||
|
||||
getonlykeys = ["Actinput", "Obs"]
|
||||
worknoplan = similar(a.memory[:shortterm])
|
||||
worklength = length(a.memory[:shortterm])
|
||||
for (i, (k, v)) in enumerate(a.memory[:shortterm])
|
||||
if i >= worklength - 1
|
||||
count = 0
|
||||
for i in getonlykeys
|
||||
if occursin(i, k)
|
||||
count += 1
|
||||
end
|
||||
end
|
||||
if count != 0
|
||||
worknoplan[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
println("")
|
||||
@show worknoplan
|
||||
|
||||
work = dictToString(worknoplan)
|
||||
|
||||
aboutYourself =
|
||||
"""
|
||||
Your name is $(a.agentName)
|
||||
$(a.roles[a.role])
|
||||
|
||||
"""
|
||||
|
||||
prompt =
|
||||
"""
|
||||
<s>
|
||||
<|system|>
|
||||
<About yourself>
|
||||
$aboutYourself
|
||||
$(a.roleSpecificInstruction[a.role])
|
||||
</About yourself>
|
||||
<Your job>
|
||||
Use the following format strictly:
|
||||
Info extraction: repeat all important info from the latest observed result thoroughly
|
||||
Info mapping: based on extracted info, explicitly state what each info could match which keyword memory's key
|
||||
Info matching: using JSON format, what key in my memory matches which info
|
||||
</Your job>
|
||||
</|system|>
|
||||
<Example>
|
||||
<Your earlier work>
|
||||
The user wants to buy an electric SUV car under 20000 dollars.
|
||||
</Your earlier work>
|
||||
<Your keyword memory>
|
||||
{\"car type\": null, \"engine type\": null, \"price\": null, \"color\": null, \"financing\": null}
|
||||
</Your keyword memory>
|
||||
<|assistant|>
|
||||
Info extraction:
|
||||
- The user is buying an electric SUV car.
|
||||
- price is under 20000 dollars
|
||||
Info mapping:
|
||||
- "SUV" could matches "car type" key
|
||||
- "electric" could matches "engine type" key
|
||||
- "under 20000 dollars" could match "price" key
|
||||
Info matching: {\"car type\": \"SUV\", \"engine type\": \"electric motor\", \"price\": \"under 20000\", \"color\": null, \"financing\": null}
|
||||
</|assistant|>
|
||||
</Example>
|
||||
</s>
|
||||
<Your earlier work>
|
||||
$work
|
||||
</Your earlier work>
|
||||
<Your keyword memory>
|
||||
$(JSON3.write(a.memory[:keyword]))
|
||||
</Your keyword memory>
|
||||
<|assistant|>
|
||||
Info extraction:
|
||||
"""
|
||||
response = sendReceivePrompt(a, prompt, max_tokens=1024, temperature=0.2, timeout=180,
|
||||
stopword=["/n/n", "END", "End", "Obs", "<|", "</"])
|
||||
response = split(response, "<|")[1]
|
||||
response = split(response, "</")[1]
|
||||
response = split(response, "</|assistant|>")[1]
|
||||
response = "Info extraction:" * response
|
||||
|
||||
println("")
|
||||
@show selfaware_1 = response
|
||||
|
||||
headerToDetect = ["Info extraction:", "Info mapping:", "Info matching:", "Actinput"]
|
||||
headers = detectCharacters(response, headerToDetect)
|
||||
|
||||
# headers[1:2] is for when LLM generate more than a paire of "Info extraction" and "Info matching", discard the rest
|
||||
chunkedtext = chunktext(response, headers[1:3])
|
||||
println("")
|
||||
_infomatch = chunkedtext["Info matching:"]
|
||||
_infomatch = GeneralUtils.getStringBetweenCharacters(_infomatch, '{', '}', endCharLocation="end")
|
||||
infomatch = GeneralUtils.JSON3read_stringKey(_infomatch)
|
||||
# infomatch = copy(JSON3.read(_infomatch))
|
||||
|
||||
println("")
|
||||
@show chunkedtext
|
||||
|
||||
println("")
|
||||
@show infomatch
|
||||
|
||||
keywordMemoryUpdate!(a.memory[:keyword], infomatch)
|
||||
end
|
||||
|
||||
function keywordMemoryToPlanMatching(a::agentReflex)
|
||||
|
||||
aboutYourself =
|
||||
"""
|
||||
Your name is $(a.agentName)
|
||||
$(a.roles[a.role])
|
||||
|
||||
"""
|
||||
|
||||
prompt =
|
||||
"""
|
||||
<s>
|
||||
<|system|>
|
||||
<About yourself>
|
||||
$aboutYourself
|
||||
$(a.roleSpecificInstruction[a.role])
|
||||
</About yourself>
|
||||
<Your job>
|
||||
Use the following format strictly:
|
||||
Info mapping: explicitly state what each step of the plan could match which keyword memory's key
|
||||
Info matching: using JSON format, what key in my memory matches which info
|
||||
</Your job>
|
||||
</|system|>
|
||||
<Example 1>
|
||||
<My plan>
|
||||
1. ask the user for car type,
|
||||
2. ask the user for color
|
||||
</My plan>
|
||||
<User info>
|
||||
{\"car type\": "SUV", \"color\": null}
|
||||
</User info>
|
||||
<|assistant|>
|
||||
Info mapping:
|
||||
-In step 1 of the plan, I need to ask the user about the car type. From user info, the car type is "SUV". Therefore this step is done.
|
||||
-In step 2 of the plan, I need to ask the user about the color . From user info, the color is null. Therefore this step is not done yet and I'll need to do this step.
|
||||
</|assistant|>
|
||||
</Example 1>
|
||||
</s>
|
||||
<Your earlier work>
|
||||
$work
|
||||
</Your earlier work>
|
||||
<User info>
|
||||
$(JSON3.write(a.memory[:keyword]))
|
||||
</User info>
|
||||
<|assistant|>
|
||||
Info mapping:
|
||||
"""
|
||||
response = sendReceivePrompt(a, prompt, max_tokens=1024, temperature=0.2, timeout=180,
|
||||
stopword=["/n/n", "END", "End", "Obs", "<|", "</"])
|
||||
response = split(response, "<|")[1]
|
||||
response = split(response, "</")[1]
|
||||
response = split(response, "</|assistant|>")[1]
|
||||
response = "Info mapping:" * response
|
||||
|
||||
println("")
|
||||
@show keywordMemoryToPlanMatching = response
|
||||
|
||||
error(1111)
|
||||
|
||||
headerToDetect = ["Info extraction:", "Info mapping:", "Info matching:", "Actinput"]
|
||||
headers = detectCharacters(response, headerToDetect)
|
||||
|
||||
# headers[1:2] is for when LLM generate more than a paire of "Info extraction" and "Info matching", discard the rest
|
||||
chunkedtext = chunktext(response, headers[1:3])
|
||||
println("")
|
||||
_infomatch = chunkedtext["Info matching:"]
|
||||
_infomatch = GeneralUtils.getStringBetweenCharacters(_infomatch, '{', '}', endCharLocation="end")
|
||||
infomatch = GeneralUtils.JSON3read_stringKey(_infomatch)
|
||||
# infomatch = copy(JSON3.read(_infomatch))
|
||||
|
||||
println("")
|
||||
@show chunkedtext
|
||||
|
||||
println("")
|
||||
@show infomatch
|
||||
|
||||
keywordMemoryUpdate!(a.memory[:keyword], infomatch)
|
||||
end
|
||||
|
||||
# function actor_mistral_openorca(a::agentReflex, selfaware=nothing)
|
||||
# getonlykeys = ["Actinput", "Obs"]
|
||||
# worknoplan = similar(a.memory[:shortterm])
|
||||
@@ -844,37 +933,19 @@ function actor_mistral_openorca(a::agentReflex, selfaware=nothing)
|
||||
</You have access to the following tools>
|
||||
<Your job>
|
||||
Use the following format:
|
||||
Thought: based on what you know about the user, where are you at according to the plan? what to do next?. (PS. 1. let's think only one thing at a time. 2. pay attention to correct numeral calculation and commonsense.)
|
||||
Thought: based on your user info, think about what to do to next according to the plan. (PS. 1. let's think only one thing at a time. 2. pay attention to correct numeral calculation and commonsense.)
|
||||
Act: based on your thought what action to choose?, must be one of [{toolnames}].
|
||||
Actinput: your input to the action using JSON format (pay attention to the tool's input)
|
||||
Obs: observed result of the action
|
||||
</Your job>
|
||||
</|system|>
|
||||
<Example 1>
|
||||
<my plan>
|
||||
I'll ask the user for car type, brand, price, color, financing method and luxury level before I'll give them any advice.
|
||||
</my plan>
|
||||
<What I know about the user>
|
||||
- Car type is SUV
|
||||
- Brand is Lexus
|
||||
- Price is 20k dollar
|
||||
- No info on the car color yet
|
||||
- No info on the financing method yet
|
||||
- Luxury level is high
|
||||
</What I know about the user>
|
||||
<|assistant|>
|
||||
Thought: after checking what I know about the user against my plan, I still don't know the color and financing method yet. Next, I need to know what color the user like.
|
||||
Act: askbox
|
||||
Actinput:
|
||||
</|assistant|>
|
||||
</Example 1>
|
||||
</s>
|
||||
<My plan>
|
||||
$(a.memory[:shortterm]["Plan 1:"])
|
||||
</My plan>
|
||||
<What I know about the user>
|
||||
$keywordmemory)
|
||||
</What I know about the user>
|
||||
<User info>
|
||||
$keywordmemory
|
||||
</User info>
|
||||
<|assistant|>
|
||||
Thought:
|
||||
"""
|
||||
@@ -890,7 +961,7 @@ function actor_mistral_openorca(a::agentReflex, selfaware=nothing)
|
||||
|
||||
while true # while Thought or Act is empty, run actor again
|
||||
|
||||
response = sendReceivePrompt(a, prompt, max_tokens=1024, temperature=0.4, timeout=300,
|
||||
response = sendReceivePrompt(a, prompt, max_tokens=1024, temperature=0.0, timeout=300,
|
||||
stopword=["Thought:", "Obs:", "<|system|>", "</s>", "<|end|>"],
|
||||
seed=rand(1000000:2000000))
|
||||
println("")
|
||||
@@ -1246,6 +1317,7 @@ function actor(a::agentReflex)
|
||||
selfaware = nothing
|
||||
if length(a.memory[:shortterm]) > 2 # must have User:, Plan:, Thought:, Act:, Actinput: already
|
||||
selfaware = selfAwareness(a)
|
||||
# result = keywordMemoryToPlanMatching(a)
|
||||
end
|
||||
|
||||
actorResult = actor_mistral_openorca(a, selfaware)
|
||||
|
||||
@@ -174,29 +174,29 @@ function winestock(a::agentReflex, input::NamedTuple)
|
||||
Dessert = table for wine type "dessert"
|
||||
Fortified = table for wine type "fortified"
|
||||
Intensity level:
|
||||
intensity = 1, light bodied
|
||||
intensity = 2, semi-light bodied
|
||||
intensity = 3, medium bodied
|
||||
intensity = 4, semi-full bodied
|
||||
intensity = 5, full bodied
|
||||
light bodied = 1
|
||||
semi-light bodied = 2
|
||||
medium bodied = 3
|
||||
semi-full bodied = 4
|
||||
full bodied = 5
|
||||
Sweetness level:
|
||||
sweetness = 1, dry
|
||||
sweetness = 2, off-dry
|
||||
sweetness = 3, semi-sweet
|
||||
sweetness = 4, sweet
|
||||
sweetness = 5, very sweet
|
||||
dry = 1
|
||||
off-dry = 2
|
||||
semi-sweet = 3
|
||||
sweet = 4
|
||||
very sweet = 5
|
||||
Tannin level:
|
||||
tannin = 1, low tannin
|
||||
tannin = 2, semi-low tannin
|
||||
tannin = 3, medium tannin
|
||||
tannin = 4, semi-high tannin
|
||||
tannin = 5, high tannin
|
||||
low tannin = 1
|
||||
semi-low tannin = 2
|
||||
medium tannin = 3
|
||||
semi-high tannin = 4
|
||||
high tannin = 4
|
||||
Acidity level:
|
||||
acidity = 1, low acidity
|
||||
acidity = 2, semi-low acidity
|
||||
acidity = 3, medium acidity
|
||||
acidity = 4, semi-high acidity
|
||||
acidity = 5, high acidity
|
||||
low acidity = 1
|
||||
semi-low acidity = 2
|
||||
medium acidity = 3
|
||||
semi-high acidity = 4
|
||||
high acidity = 5
|
||||
</You have the following conversion table>
|
||||
<Your job>
|
||||
Write a specific SQL command from a query using a conversion table
|
||||
@@ -270,15 +270,13 @@ function winestock(a::agentReflex, input::NamedTuple)
|
||||
body = newsql
|
||||
uri = URI(scheme="http", host="192.168.88.12", port="9010", path="/sql", userinfo="root:root")
|
||||
r = HTTP.request("POST", uri, ["Accept" => "application/json", "NS"=>"yiem", "DB"=>"Blossom_wines"], body)
|
||||
println("")
|
||||
@show r
|
||||
|
||||
a.memory[:r] = r
|
||||
result = copy(JSON3.read(r.body))
|
||||
|
||||
|
||||
wines = shuffle(result[1][:result]) # shuffle in case there are more than 1 result
|
||||
println("")
|
||||
@show wines
|
||||
|
||||
|
||||
# choose only 2 wines
|
||||
if length(wines) > 2
|
||||
@@ -286,6 +284,9 @@ function winestock(a::agentReflex, input::NamedTuple)
|
||||
wines = wines[1:2]
|
||||
end
|
||||
|
||||
println("")
|
||||
@show wines
|
||||
|
||||
result = nothing
|
||||
if length(wines) == 0
|
||||
result =
|
||||
|
||||
@@ -152,7 +152,7 @@ function agentReflex(
|
||||
"""
|
||||
Request the user’s input for the following info initially, and use alternative sources of information only if they are unable to provide it:
|
||||
- wine price range: ask the user
|
||||
- wine type (Rose, White, Red, Rose, Sparkling, Dessert)
|
||||
- wine type (rose, white, red, sparkling, dessert)
|
||||
- food type that will be served with wine
|
||||
- wine sweetness level (dry to very sweet)
|
||||
- wine intensity level (light to full bodied)
|
||||
|
||||
Reference in New Issue
Block a user