update
This commit is contained in:
101
previousVersion/0.0.5/src/ChatAgent.jl
Executable file
101
previousVersion/0.0.5/src/ChatAgent.jl
Executable file
@@ -0,0 +1,101 @@
|
||||
module ChatAgent
|
||||
|
||||
# export agent, addNewMessage, clearMessage
|
||||
|
||||
|
||||
""" 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("utils.jl")
|
||||
using .utils
|
||||
|
||||
include("llmfunction.jl")
|
||||
using .llmfunction
|
||||
|
||||
include("interface.jl")
|
||||
using .interface
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------------------------100
|
||||
|
||||
""" version 0.0.5
|
||||
Todo:
|
||||
[WORKING] add formulateUserRespond to AI tools
|
||||
|
||||
Change from version: 0.0.4
|
||||
-
|
||||
|
||||
"""
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end # module ChatAgent
|
||||
1393
previousVersion/0.0.5/src/interface.jl
Executable file
1393
previousVersion/0.0.5/src/interface.jl
Executable file
File diff suppressed because it is too large
Load Diff
141
previousVersion/0.0.5/src/llmfunction.jl
Normal file
141
previousVersion/0.0.5/src/llmfunction.jl
Normal file
@@ -0,0 +1,141 @@
|
||||
module llmfunction
|
||||
|
||||
export wikisearch, winestock
|
||||
|
||||
using HTTP, JSON3
|
||||
using GeneralUtils
|
||||
using ..type, ..utils
|
||||
#------------------------------------------------------------------------------------------------100
|
||||
|
||||
"""
|
||||
Search wikipedia.
|
||||
|
||||
Arguments:
|
||||
query (string): The query to search for
|
||||
|
||||
Returns:
|
||||
string: The search result text from wikipedia
|
||||
```jldoctest
|
||||
julia> using HTTP, JSON3
|
||||
julia> result = wikisearch("AMD")
|
||||
"Advanced Micro Devices, Inc., commonly abbreviated as AMD, is an ..."
|
||||
```
|
||||
"""
|
||||
function wikisearch(a::agentReflex, phrase::T) where {T<:AbstractString}
|
||||
phrase = phrase[1] == " " ? phrase[2:end] : phrase
|
||||
# prepare input phrase
|
||||
if occursin("\"", phrase)
|
||||
phrase = GeneralUtils.getStringBetweenCharacters(phrase, "\"", "\"")
|
||||
end
|
||||
phrase = replace(phrase, "\n"=>"")
|
||||
|
||||
url = "https://en.wikipedia.org/w/api.php?action=query&format=json&prop=extracts&titles=$(replace(phrase, " " => "%20"))&exintro=1&explaintext=1"
|
||||
@show url
|
||||
response = HTTP.get(url)
|
||||
json_data = JSON3.read(String(response.body))
|
||||
page_id = first(keys(json_data["query"]["pages"]))
|
||||
if page_id == "-1"
|
||||
return "Sorry, I couldn't find any Wikipedia page for the given phrase."
|
||||
end
|
||||
|
||||
result = nothing
|
||||
try
|
||||
result = json_data["query"]["pages"][page_id]["extract"]
|
||||
wiki = result
|
||||
@show wiki
|
||||
catch
|
||||
result = "No info available for your search query."
|
||||
end
|
||||
|
||||
# if result == ""
|
||||
# result = "No info available for your search query."
|
||||
# else
|
||||
# result = makeSummary(a, result)
|
||||
# end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function winestock(a::agentReflex, phrase::T) where {T<:AbstractString}
|
||||
# result = [
|
||||
# Dict(
|
||||
# "name" => "Louis Latou - Corton-Charlamagne - Chardonnay",
|
||||
# "description" => "Corton-Charlemagne 2018 is a powerful, complex wine. Its nose is intense, with notes of white stone fruits such as white peach, fresh hazelnut, vanilla, and almond paste. The wine is full-bodied for the palate, and the vanilla is complemented by aromas of fresh almond and lime blossom. The experience ends with a very fine aromatic aftertaste that has subtle saline notes.",
|
||||
# "price" => "49",
|
||||
# "ID" => "ws-114"
|
||||
# ),
|
||||
# Dict(
|
||||
# "name" => "Louis Latou - Corton-Charlamagne - Chardonnay",
|
||||
# "description" => "Corton-Charlemagne 2018 is a powerful, complex wine. Its nose is intense, with notes of white stone fruits such as white peach, fresh hazelnut, vanilla, and almond paste. The wine is full-bodied for the palate, and the vanilla is complemented by aromas of fresh almond and lime blossom. The experience ends with a very fine aromatic aftertaste that has subtle saline notes.",
|
||||
# "price" => "49",
|
||||
# "ID" => "ws-114"
|
||||
# )
|
||||
# ]
|
||||
|
||||
result =
|
||||
"""
|
||||
1. Name: Louis Latou - Corton-Charlamagne - Chardonnay,
|
||||
Description: Corton-Charlemagne 2018 is a powerful, complex wine. Its nose is intense, with notes of white stone fruits such as white peach, fresh hazelnut, vanilla, and almond paste. The wine is full-bodied for the palate, and the vanilla is complemented by aromas of fresh almond and lime blossom. The experience ends with a very fine aromatic aftertaste that has subtle saline notes.,
|
||||
Price: 55 dollars,
|
||||
ID: ws-114
|
||||
2. Name: Chateau de Beaucastel Hommage Jacques Perrin Chateauneuf-du-Pape,
|
||||
Year: 2019,
|
||||
Description: The quintessence of Château de Beaucastel, Hommage à Jacques Perrin delights us every year, and the 2019 vintage is no exception. To the eye it offers a splendid deep red color, verging on black. Full of power and supremely elegant, the nose is of magnificent aromatic complexity with notes of black fruit and spices that offer all the characteristic expression of Mourvèdre. Perfectly balanced by an incredible freshness, the mouth is eminently elegant with intense and complex aromas of great subtlety, a full, refined texture, subtle tannins of great finesse, and infinite length. A great classic Hommage à Jacques Perrin.,
|
||||
Price: 40,
|
||||
ID: ed-23
|
||||
"""
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end # end module
|
||||
309
previousVersion/0.0.5/src/type.jl
Normal file
309
previousVersion/0.0.5/src/type.jl
Normal file
@@ -0,0 +1,309 @@
|
||||
module type
|
||||
|
||||
export agent, agentReflex
|
||||
|
||||
using Dates, UUIDs, DataStructures
|
||||
using CommUtils
|
||||
|
||||
#------------------------------------------------------------------------------------------------100
|
||||
|
||||
|
||||
abstract type agent end
|
||||
|
||||
""" A LLM agent with self reflect capabilities.
|
||||
|
||||
# Example
|
||||
```jldoctest
|
||||
julia> using ChatAgent
|
||||
julia> mqttClientSpec = (
|
||||
clientName= "someclient", # name of this client
|
||||
clientID= "$(uuid4())",
|
||||
broker= "mqtt.yiem.ai",
|
||||
pubtopic= (imgAI="img/api/v0.0.1/gpu/request",
|
||||
txtAI="txt/api/v0.1.0/gpu/request"), # this is where LLM server located
|
||||
subtopic= (imgAI="agent/api/v0.1.0/img/respond",
|
||||
txtAI="agent/api/v0.1.0/txt/respond"), # this is where this agent located
|
||||
keepalive= 30,
|
||||
)
|
||||
julia> msgMeta = Dict(
|
||||
:msgPurpose=> "updateStatus",
|
||||
:from=> "agent",
|
||||
:to=> "llmAI",
|
||||
:requestrespond=> "request",
|
||||
:sendto=> "", # destination topic
|
||||
:replyTo=> "agent/api/v0.1.0/txt/respond", # requester ask responder to send reply to this topic
|
||||
:repondToMsgId=> "", # responder is responding to this msg id
|
||||
:taskstatus=> "", # "complete", "fail", "waiting" or other status
|
||||
:timestamp=> Dates.now(),
|
||||
:msgId=> "$(uuid4())",
|
||||
)
|
||||
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,
|
||||
),
|
||||
:wikisearch=>Dict(
|
||||
:name => "wikisearch",
|
||||
:description => "Useful for when you need to search an encyclopedia.",
|
||||
:input => "Input is keywords and not a question.",
|
||||
:output => "",
|
||||
:func => ChatAgent.wikisearch, # put function here
|
||||
),
|
||||
:winestock=>Dict(
|
||||
:name => "wineStock",
|
||||
:description => "useful for when you need to search your wine stock by wine description, price, name or ID.",
|
||||
:input => "Input is a search query.",
|
||||
:output => "Output are Wine name, description, price and ID" ,
|
||||
:func => ChatAgent.winestock,
|
||||
),
|
||||
)
|
||||
julia> agent = ChatAgent.agentReflex(
|
||||
"Jene",
|
||||
role=:assistant,
|
||||
mqttClientSpec=mqttClientSpec,
|
||||
msgMeta=msgMeta,
|
||||
tools=tools
|
||||
)
|
||||
```
|
||||
"""
|
||||
@kwdef mutable struct agentReflex <: agent
|
||||
availableRole::AbstractVector = ["system", "user", "assistant"]
|
||||
agentName::String = "Jene" # ex. Jene
|
||||
maxUserMsg::Int = 30
|
||||
earlierConversation::String = "N/A" # summary of earlier conversation
|
||||
mqttClient::Union{mqttClient, Nothing} = nothing
|
||||
msgMeta::Union{Dict, Nothing} = nothing
|
||||
|
||||
""" Dict(Role=> Content) ; Role can be system, user, assistant
|
||||
Example:
|
||||
messages=[
|
||||
Dict(:role=>"system", :content=> "You are a helpful assistant."),
|
||||
Dict(:role=>"assistant", :content=> "How may I help you"),
|
||||
Dict(:role=>"user", :content=> "Hello, how are you"),
|
||||
]
|
||||
"""
|
||||
role::Symbol = :assistant
|
||||
roles::Dict = Dict(:assistant => "You are a helpful assistant.",)
|
||||
|
||||
# Ref: Chat prompt format https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGML/discussions/3
|
||||
# messages= [Dict(:role=>"system", :content=> "", :timestamp=> Dates.now()),]
|
||||
messages = Vector{Dict{Symbol, Any}}()
|
||||
tools::Union{Dict, Nothing} = nothing
|
||||
newplan::Bool = false # if true, new plan will be generated
|
||||
attemptlimit::Int = 5 # thinking round limit
|
||||
attempt::Int = 1 # attempted number
|
||||
step::Int = 1 # step number
|
||||
env::AbstractString = "N/A"
|
||||
thinkingFormat::Union{Dict, Nothing} = nothing
|
||||
memory::Dict = Dict(
|
||||
:shortterm=> OrderedDict{String, Any}(),
|
||||
:longterm=> OrderedDict{String, Any}(),
|
||||
:log=> OrderedDict{String, Any}(), # span from user stimulus -> multiples attempts -> final respond
|
||||
)
|
||||
end
|
||||
|
||||
function agentReflex(
|
||||
agentName::String;
|
||||
mqttClientSpec::NamedTuple=(
|
||||
clientName= "someclient", # name of this client
|
||||
clientID= "$(uuid4())",
|
||||
broker= "mqtt.yiem.ai",
|
||||
pubtopic= (imgAI="img/api/v0.0.1/gpu/request",
|
||||
txtAI="txt/api/v0.1.0/gpu/request"),
|
||||
subtopic= (imgAI="agent/api/v0.1.0/img/respond",
|
||||
txtAI="agent/api/v0.1.0/txt/respond"),
|
||||
keepalive= 30,),
|
||||
role::Symbol=:assistant,
|
||||
roles::Dict=Dict(
|
||||
:assistant =>
|
||||
"""
|
||||
You are a helpful assistant who respond to user as best you can.
|
||||
""",
|
||||
:sommelier =>
|
||||
"""
|
||||
You are a sommelier at an online wine reseller who always help users choosing their wine from your store.
|
||||
You don't know other people personal info previously.
|
||||
""",
|
||||
# :sommelier =>
|
||||
# """
|
||||
# You are a sommelier at an online wine reseller who always ask user for wine relevant info before you could help them choosing wine.
|
||||
# You provide a personalized recommendation of up to two wines based on the user's preference, and you describe the benefits of each wine in detail.
|
||||
# You don't know other people personal info previously.
|
||||
|
||||
# Info used to select wine:
|
||||
# - type of food
|
||||
# - occasion
|
||||
# - user's personal taste of wine
|
||||
# - wine price range
|
||||
# - temperature at the serving location
|
||||
# - wine we have in stock
|
||||
# """,
|
||||
),
|
||||
thinkingFormat::Dict=Dict(
|
||||
:react=>
|
||||
"""
|
||||
Use the following format:
|
||||
Question: the input question your user is asking and you must answer
|
||||
Plan: first you should always think about the question and the info you have thoroughly then extract and devise a complete plan to find the answer (pay attention to variables and their corresponding numerals).
|
||||
Thought: ask yourself do you have all the info you need? And what to do according to the plan (pay attention to correct numeral calculation and commonsense).
|
||||
Act: the tool that match your thought, should be one of {toolnames}
|
||||
Actinput: the input to the action (pay attention to the tool's input)
|
||||
Obs: the result of the action
|
||||
... (this Plan/Thought/Act/Actinput/Obs can repeat N times until you know the answer.)
|
||||
Thought: I think I know the answer
|
||||
Answer: Answer of the original question
|
||||
|
||||
Begin!""",
|
||||
:planner=>
|
||||
"""
|
||||
Use the following format:
|
||||
Stimulus: the input user gives to you and you must respond
|
||||
Plan: first you should always think about the stimulus, the info you need and the info you have thoroughly then extract and devise a step by step plan (pay attention to correct numeral calculation and commonsense).
|
||||
P.S.1 each step should be a single action.
|
||||
""",
|
||||
:actor=>
|
||||
"""
|
||||
Your task is to do the following:
|
||||
Thought: using step {step} of the plan as a guideline, what to do? (pay attention to correct numeral calculation and commonsense).
|
||||
Act: the action to take based on your thought, must be one of [{toolnames}]
|
||||
Actinput: your input to the action you chose (pay attention to the tool's input)
|
||||
Obs: observed result of the action
|
||||
""",
|
||||
:actorOriginal=>
|
||||
"""
|
||||
Use the following format:
|
||||
Thought: you should always think about do you have all the required info and what to do according to step {step} of the plan and the info you have (pay attention to correct numeral calculation and commonsense).
|
||||
Act: the action to take that match your thought, should be one of [{toolnames}]
|
||||
Actinput: the input to the action (pay attention to the tool's input)
|
||||
Obs: the result of the action
|
||||
""",
|
||||
),
|
||||
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,
|
||||
),
|
||||
# :wikisearch=>Dict(
|
||||
# :name => "wikisearch",
|
||||
# :description => "Useful for when you need to search an encyclopedia",
|
||||
# :input => "Input is keywords and not a question.",
|
||||
# :output => "",
|
||||
# :func => wikisearch, # put function here
|
||||
# ),
|
||||
# :wineStock=>Dict(
|
||||
# :name => "wineStock",
|
||||
# :description => "useful for when you need to search for wine by your description, price, name or ID.",
|
||||
# :input => "Input should be a search query with as much details as possible.",
|
||||
# :output => "" ,
|
||||
# :func => nothing,
|
||||
# ),
|
||||
# :NTHING=>Dict(
|
||||
# :name => "NTHING",
|
||||
# :description => "useful for when you don't need to use tools or actions",
|
||||
# :input => "No input is needed",
|
||||
# :output => "" ,
|
||||
# :func => nothing,
|
||||
# ),
|
||||
),
|
||||
msgMeta::Dict=Dict(
|
||||
:msgPurpose=> "updateStatus",
|
||||
:from=> "chatbothub",
|
||||
:to=> "llmAI",
|
||||
:requestrespond=> "request",
|
||||
:sendto=> "", # destination topic
|
||||
:replyTo=> "agent/api/v0.1.0/txt/respond", # requester ask responder to send reply to this topic
|
||||
:repondToMsgId=> "", # responder is responding to this msg id
|
||||
:taskstatus=> "", # "complete", "fail", "waiting" or other status
|
||||
:timestamp=> Dates.now(),
|
||||
:msgId=> "$(uuid4())",
|
||||
),
|
||||
availableRole::AbstractArray=["system", "user", "assistant"],
|
||||
maxUserMsg::Int=10,)
|
||||
|
||||
newAgent = agentReflex()
|
||||
newAgent.availableRole = availableRole
|
||||
newAgent.maxUserMsg = maxUserMsg
|
||||
newAgent.mqttClient = CommUtils.mqttClient(mqttClientSpec)
|
||||
newAgent.msgMeta = msgMeta
|
||||
newAgent.tools = tools
|
||||
newAgent.role = role
|
||||
newAgent.roles = roles
|
||||
newAgent.thinkingFormat = thinkingFormat
|
||||
newAgent.agentName = agentName
|
||||
|
||||
return newAgent
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end # end module
|
||||
|
||||
|
||||
|
||||
1084
previousVersion/0.0.5/src/utils.jl
Normal file
1084
previousVersion/0.0.5/src/utils.jl
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user