279 lines
7.8 KiB
Julia
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)
|
|
|
|
|
|
|