Files
YiemAgent/test/runtest.jl
narawat lamaiin 232202d1ca update
2024-08-25 11:50:50 +07:00

279 lines
7.8 KiB
Julia

using Revise # remove when this package is completed
using YiemAgent, GeneralUtils, JSON3, MQTTClient, Dates, UUIDs, LibPQ, Base64, DataFrames
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)
# println(typeof(connection))
# msgMeta = GeneralUtils.generate_msgMeta(
# "N/A",
# replyTopic = config[:servicetopic][:mqtttopic] # ask frontend reply to this instance_chat_topic
# )
function executeSQL(sql::T) where {T<:AbstractString}
DBconnection = LibPQ.Connection("host=192.168.88.12 port=5432 dbname=yiem_wine_assistant user=yiem password=yiem@Postgres_0.0")
result = LibPQ.execute(DBconnection, sql)
close(DBconnection)
return result
end
function text2textInstructLLM(prompt::String)
msgMeta = GeneralUtils.generate_msgMeta(
config[:externalservice][:text2textinstruct][:mqtttopic];
msgPurpose= "inference",
senderName= "yiemagent",
senderId= string(uuid4()),
receiverName= "text2textinstruct",
mqttBrokerAddress= config[:mqttServerInfo][:broker],
mqttBrokerPort= config[:mqttServerInfo][:port],
)
outgoingMsg = Dict(
:msgMeta=> msgMeta,
:payload=> Dict(
:text=> prompt,
:kwargs=> Dict(
:max_tokens=> 2048,
:stop=> ["<|eot_id|>"],
:temperature=> 0.2,
)
)
)
_response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120)
response = _response[:response][:text]
return response
end
function executeSQLVectorDB(sql)
DBconnection = LibPQ.Connection("host=192.168.88.12 port=5433 dbname=SQLVectorDB user=yiemtechnologies@gmail.com password=yiem@Postgres_0.0")
result = LibPQ.execute(DBconnection, sql)
close(DBconnection)
return result
end
function addSQLVectorDB(state)
# get embedding of the query
query = [state[:thoughtHistory][:question]]
msgMeta = GeneralUtils.generate_msgMeta(
config[:externalservice][:text2textinstruct][:mqtttopic];
msgPurpose= "embedding",
senderName= "yiemagent",
senderId= string(uuid4()),
receiverName= "text2textinstruct",
mqttBrokerAddress= config[:mqttServerInfo][:broker],
mqttBrokerPort= config[:mqttServerInfo][:port],
)
outgoingMsg = Dict(
:msgMeta=> msgMeta,
:payload=> Dict(
:text=> query
)
)
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg)
embedding = response[:response][:embeddings][1]
# check whether there is close enough vector already store in vectorDB. if no, add, else skip
sql =
"""
SELECT *, embedding <-> '$embedding' as distance
FROM sql_statement_repository
ORDER BY distance LIMIT 1;
"""
response = executeSQLVectorDB(sql)
df = DataFrame(response)
row, col = size(df)
distance = row == 0 ? Inf : df[1, :distance]
if row == 0 || distance > 10 # no close enough SQL stored in the database
latestKey, _ = GeneralUtils.findHighestIndexKey(state[:thoughtHistory], :action_input)
_sqlStatement = state[:thoughtHistory][latestKey]
if occursin("SELECT", _sqlStatement) # make sure it is an SQL statement before adding into DB
sqlStatementBase64 = base64encode(_sqlStatement)
sqlStatement = replace(_sqlStatement, "'"=>"")
sql =
"""
INSERT INTO sql_statement_repository (question, sql_statement, sql_statement_base64, embedding) VALUES ('$query', '$sqlStatement', '$sqlStatementBase64', '$embedding');
"""
_ = executeSQLVectorDB(sql)
println("--> added new SQL statement to vectorDB ", @__FILE__, " ", @__LINE__)
println(sqlStatement)
end
end
end
function querySQLVectorDB(state)
# provide similarSQL at the first time thinking only
latestKey, _ = GeneralUtils.findHighestIndexKey(state[:thoughtHistory], :action_input)
if latestKey === nothing
# get embedding of the query
query = [state[:thoughtHistory][:question]]
msgMeta = GeneralUtils.generate_msgMeta(
config[:externalservice][:text2textinstruct][:mqtttopic];
msgPurpose= "embedding",
senderName= "yiemagent",
senderId= string(uuid4()),
receiverName= "text2textinstruct",
mqttBrokerAddress= config[:mqttServerInfo][:broker],
mqttBrokerPort= config[:mqttServerInfo][:port],
)
outgoingMsg = Dict(
:msgMeta=> msgMeta,
:payload=> Dict(
:text=> query
)
)
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg)
embedding = response[:response][:embeddings][1]
# check whether there is close enough vector already store in vectorDB. if no, add, else skip
sql =
"""
SELECT *, embedding <-> '$embedding' as distance
FROM sql_statement_repository
ORDER BY distance LIMIT 1;
"""
response = executeSQLVectorDB(sql)
df = DataFrame(response)
row, col = size(df)
distance = row == 0 ? Inf : df[1, :distance]
if row != 0 && distance < 100
# if there is usable SQL, return it.
sqlStatementBase64 = df[1, :sql_statement_base64]
sqlStatement = String(base64decode(sqlStatementBase64))
println("--> getting SQL statement from vectorDB ", @__FILE__, " ", @__LINE__)
println(sqlStatement)
return sqlStatement
else
return nothing
end
end
return nothing
end
# Instantiate an agent
a = YiemAgent.sommelier(
text2textInstructLLM,
executeSQL,
querySQLVectorDB,
addSQLVectorDB;
name= "Janie",
id= sessionId, # agent instance id
)
function main()
for i in 1:10
userinput = ""
for i in 1:3
if userinput == ""
println("")
println("--> user input:")
userinput = readline()
else
break
end
end
response = YiemAgent.conversation(a, Dict(:text=> userinput))
println("")
println("--> assistant response: \n", response)
end
end
main()
"""
I'm joining a graduation party this evening. I want a bottle of dry white wine from the US. I'm ok with any price range.
Well, the party is small casual with close friends and no food serving.
I'm open to suggestion since I have no specific idea.
I'm ok with any region.
The input is instructions on how you want the presentation to be conducted.
"""
# response = YiemAgent.conversation(a, Dict(:text=> "newtopic",) )
# response = YiemAgent.conversation(a, Dict(:text=> "Hello, I would like a get a bottle of wine."))
# println("---> YiemAgent: ", response)
# response = YiemAgent.conversation(a, Dict(:text=> "I'm having a graduation party this evening. I'll pay at most 30 bucks."))
# # input = "query=\"off dry, medium tannin, French Rosé\""
# input = "Search the database for wine type: white, country: France, sweetness level: 1"
# YiemAgent.winestock(a, input)
# input = "French dry white wines with medium body"
# input = "query=\"medium-bodied dry white wine\""
# # input = "the customer is looking for a medium-bodied, dry white wine."
# result = YiemAgent.checkinventory(a, input)
error("test done")
function run_with_timeout(f, args...; timeout=5)
result = Ref{Any}()
task = Threads.@spawn try
result[] = f(args...)
catch e
println("Task interrupted: ", e)
end
Timer(timeout) do _
if !istaskdone(task)
schedule(task, InterruptException())
println("Task did not complete in time. Aborting.")
else
println("Task completed within the timeout.")
end
end
return result[]
end
# Example function that takes arguments and returns a value
function example_function(x, y)
sleep(10) # Simulate a long-running task
return x + y
end
# Example usage
result = run_with_timeout(example_function, 3, 4; timeout=5)
println("Result: ", result)