library(reticulate)
library(stringr)
# Load OpenAI API
print(getwd())
path<- "../../scripts/qianwen.py"
print(path)
#使用指定的Conda虚拟环境"openai"运行Python程序
use_condaenv(condaenv="base", conda = "/usr/lib64/anaconda3/bin/conda", required = TRUE)
source_python(path)
context<-data.frame("role"=character(),"content"=character())
context<-rbind(context, list(role="system",content="You are a helpful assistant."))
function(input, output, session) {
ifContext<- reactive({
input$ifContext
})
prompt<- reactive({
input$prompt
})
observeEvent(input$clearContext,{
session$userData$context<- context
updateTextAreaInput(session, "context", value = "")
})
observeEvent(input$sendout,{
if(ifContext() && ! is.null(session$userData$context)){
temp<-session$userData$context
} else{
temp<- context
}
temp<-rbind(temp, list(role="user",content=prompt()))
# Show notification while querying.
id <- showNotification("正在咨询通义千问...", duration = NULL, closeButton = FALSE)
on.exit(removeNotification(id), add = TRUE)
response<- CallAPI(temp)
#browser()
temp<-rbind(temp, list(role="assistant",content=response))
session$userData$context<- temp
# 格式化输出,插入对话者身份前缀。
outStr<-""
for(i in 2: dim(temp)[[1]]){
if (i%%2==0){
outStr<-paste(outStr,"User: ",temp[i,2],"\n",sep="")
}else{
outStr<-paste(outStr,"AI: ",temp[i,2],"\n\n",sep="")
}
}
updateTextAreaInput(session, "context", value = outStr)
updateTextAreaInput(session, "prompt", value = "")
# 对话上下文自动滚动到底部
session$sendCustomMessage(type = 'scrollToBottom', message = '')
})
observeEvent(input$restoreContext,{
if(! is.null(session$userData$context)){
temp<-session$userData$context
# 格式化输出,插入对话者身份前缀。
outStr<-""
for(i in 2: dim(temp)[[1]]){
if (i%%2==0){
outStr<-paste(outStr,"User: ",temp[i,2],"\n",sep="")
}else{
outStr<-paste(outStr,"AI: ",temp[i,2],"\n\n",sep="")
}
}
updateTextAreaInput(session, "context", value = outStr)
updateTextAreaInput(session, "prompt", value = "")
}
})
}
# 在输出文本中包含滚动条的另一种方式。
# https://stackoverflow.com/questions/61007632/container-settings-in-text-output-shiny
fluidPage(
# 对话上下文自动滚动到底部的JavaScript函数
tags$script(HTML("
function scrollToBottom() {
var textarea = document.getElementById('context');
console.log('Before scroll:', textarea.scrollTop, textarea.scrollHeight);
setTimeout(function() {
textarea.scrollTop = textarea.scrollHeight;
}, 100); // 可以根据需要调整延迟时间
console.log('After scroll:', textarea.scrollTop, textarea.scrollHeight);
}
Shiny.addCustomMessageHandler('scrollToBottom', function(message) {
scrollToBottom();
});
")),
sidebarLayout(
# Sidebar
sidebarPanel(
# Application title
tags$h3("通义千问聊天机器人"),
checkboxInput("ifContext","是否包括上下文:", value = TRUE),
actionButton("clearContext", "清除上下文", class = "btn-cleear"),
actionButton("restoreContext", "恢复中断对话", class = "btn-success"),
# 1/6
width = 3
),
# Main
mainPanel(
textAreaInput("context","对话记录",width="100%", rows =26, resize="vertical", value =""),
# 插入javascript,禁止自己修改 context textAreaInput
tags$script(HTML("
var context = document.getElementById('context');
context.readOnly = true;
")),
tags$h6(" "),
textAreaInput("prompt","输入:",width="100%", rows =4, resize="vertical", value =""),
actionButton("sendout", "提交", class = "btn-success"),
# 5/6
# width = 10
)
)
)