Skip to content

Commit

Permalink
added answer answeryouth and answerkid commands
Browse files Browse the repository at this point in the history
  • Loading branch information
eliranwong committed Nov 11, 2024
1 parent 70e4416 commit f63d410
Show file tree
Hide file tree
Showing 9 changed files with 288 additions and 3 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
# https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/
setup(
name=package,
version="0.1.65",
version="0.1.69",
python_requires=">=3.8, <3.13",
description=f"UniqueBible App is a cross-platform & offline bible application, integrated with high-quality resources and unique features. Developers: Eliran Wong and Oliver Tseng",
long_description=long_description,
Expand Down
3 changes: 3 additions & 0 deletions uniquebible/lang/language_en_GB.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,8 @@
"enableQtMaterial": "Enable Qt-material Theme",
"disableQtMaterial": "Switch to Built-in Theme",
"biblePromises": "Bible Promises",
"bibleAnswers": "Bible Answers",
"experimental": "experimental",
"bibleHarmonies": "Bible Parallels",
"favouriteBooks": "Favourite Books",
"mainWindow": "Bible Window",
Expand Down Expand Up @@ -1046,6 +1048,7 @@
"configure": "Configure",
"exit": "Exit",
"displayChapterVerseAudioIcons": "Display Chapter Verse Audio Icons",
"askAI": "Bible Q&amp;A with AI",
"newDatabase": "New Database",
"openDatabase": "Open Database",
"saveDatabaseAs": "Save Database as ...",
Expand Down
3 changes: 3 additions & 0 deletions uniquebible/lang/language_en_US.py
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,9 @@
"configure": "Configure",
"exit": "Exit",
"displayChapterVerseAudioIcons": "Display Chapter Verse Audio Icons",
"askAI": "Bible Q&amp;A with AI",
"bibleAnswers": "Bible Answers",
"experimental": "experimental",
"newDatabase": "New Database",
"openDatabase": "Open Database",
"saveDatabaseAs": "Save Database as ...",
Expand Down
3 changes: 3 additions & 0 deletions uniquebible/lang/language_zh_HANS.py
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,9 @@
"configure": "配置",
"exit": "退出",
"displayChapterVerseAudioIcons": "显示 Chapter Verse 音频图标",
"askAI": "AI 圣经问答工具",
"bibleAnswers": "圣经解答",
"experimental": "测试中",
"newDatabase": "新建数据库",
"openDatabase": "打开数据库",
"saveDatabaseAs": "将数据库另存为 ...",
Expand Down
3 changes: 3 additions & 0 deletions uniquebible/lang/language_zh_HANT.py
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,9 @@
"configure": "配置",
"exit": "出口",
"displayChapterVerseAudioIcons": "顯示 Chapter Verse 音訊圖示",
"askAI": "AI 聖經問答工具",
"bibleAnswers": "聖經解答",
"experimental": "測試中",
"newDatabase": "新建資料庫",
"openDatabase": "開啟資料庫",
"saveDatabaseAs": "將資料庫另存為 ...",
Expand Down
53 changes: 53 additions & 0 deletions uniquebible/util/ConfigUtil.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,59 @@ def getCurrentVenvDir():
# Check installed and latest versions on startup.""",
True)

# start of groq chat setting
# config.answer_backend
# config.addBibleQnA
# config.groqApi_key
# config.groqApi_systemMessage_general
# config.groqApi_systemMessage_youth
# config.groqApi_systemMessage_kid
# config.groqApi_llmTemperature
# config.groqApi_chat_model
# config.groqApi_chat_model_max_tokens
# config.mistralApi_llmTemperature
# config.mistralApi_chat_model
# config.mistralApi_chat_model_max_tokens
setConfig("answer_backend", """
# Add Bible Q and A Features to web mode navigation menu.""",
"groq")
setConfig("addBibleQnA", """
# Add Bible Q and A Features to web mode navigation menu.""",
False)
setConfig("groqApi_systemMessage_general", """
# Groq Chat System Message""",
"I would like you to speak like a compassionate church pastor who upholds the truths of the Bible.")
setConfig("groqApi_systemMessage_youth", """
# Groq Chat System Message""",
"I would like you to respond as an experienced church youth pastor who is passionate about their faith and dedicated to guiding young people. Speak like you are speaking to a teen.")
setConfig("groqApi_systemMessage_kid", """
# Groq Chat System Message""",
"Please speak like a kind Children's Sunday School pastor who loves the Bible and wants to share its wonderful stories with a five-year-old. Use simple words and a gentle, loving tone.")
setConfig("groqApi_key", """
# Groq Cloud API Keys""",
[])
setConfig("groqApi_chat_model", """
# Groq Chat Model""",
"llama-3.1-70b-versatile")
setConfig("groqApi_chat_model_max_tokens", """
# Groq Chat Maximum Output Tokens""",
8000)
setConfig("groqApi_llmTemperature", """
# Groq Chat Temperature""",
0.3) # 0.2-0.8 is good to use
setConfig("mistralApi_key", """
# Mistral AI API Keys""",
[])
setConfig("mistralApi_chat_model", """
# Mistral AI Chat Model""",
"mistral-large-latest")
setConfig("mistralApi_chat_model_max_tokens", """
# Mistral AI Chat Maximum Output Tokens""",
8000)
setConfig("mistralApi_llmTemperature", """
# Mistral AI Chat Temperature""",
0.3) # 0.2-0.7 is good to use

# Start of api-client mode setting
setConfig("web_api_endpoint", """
# UniqueBible App web API endpoint.""",
Expand Down
83 changes: 82 additions & 1 deletion uniquebible/util/RemoteHttpHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,7 @@ def loadContent(self):
"library": self.libraryContent,
"logout": self.logout,
"search": self.searchContent,
"qna": self.qnaContent,
"maps": self.mapsContent,
"days": self.dailyReadingContent,
"theme": self.swapTheme,
Expand Down Expand Up @@ -1040,13 +1041,15 @@ def getSideNavContent(self):
(config.thisTranslation["menu5_topics"], ".topics"),
(config.thisTranslation["bibleHarmonies"], ".parallels"),
(config.thisTranslation["biblePromises"], ".promises"),
(config.thisTranslation["bibleAnswers"], ".qna") if config.addBibleQnA else None,
(config.thisTranslation["readingPlan"], ".days"),
("{0} &#x1F50E;&#xFE0E;".format(config.thisTranslation["menu_search"]), ".search"),
(config.thisTranslation["download"], ".download"),
(config.thisTranslation["ubaCommands"], ".help"),
)
for item in sideNavItems:
html += """<a href="#" onclick="submitCommand('{1}')">{0}</a>""".format(*item)
if item is not None:
html += """<a href="#" onclick="submitCommand('{1}')">{0}</a>""".format(*item)
html += """<a href="{1}" target="_blank">{0}</a>""".format(config.thisTranslation["userManual"], self.getUserManual())
html += "<hr>"
html += """<a href="traditional.html">繁體中文</a>""" if config.webHomePage != "traditional.html" else ""
Expand Down Expand Up @@ -1847,6 +1850,84 @@ def dailyReadingContent(self):
content += "</p></div>"
return content

def qnaContent(self):
experimental = "" if config.addBibleQnA else f""" [{config.thisTranslation["experimental"]}]"""
content = "<h2>{0}{1}</h2>".format(config.thisTranslation["askAI"], experimental)

if config.displayLanguage == "zh_HANT":
content += """<h3>一般使用者</h3><p>請輸入與聖經相關的提問,然後按下按鈕「{0}」。</p>""".format(config.thisTranslation["send"])
elif config.displayLanguage == "zh_HANS":
content += """<h3>一般使用者</h3><p>请输入与圣经相关的提问,然后按下按钮,然后按下按钮「{0}」。</p>""".format(config.thisTranslation["send"])
else:
content += """<h3>General Inquiry</h3><p>Please enter a bible-related question and click the button '{0}'.</p>""".format(config.thisTranslation["send"])
content += "<p><input type='text' id='bibleQuestion1' style='width:95%' autofocus></p>"
content += """<p><button id='bibleQuestionButton1' type='button' onclick='answer("");' class='ubaButton'>{0}</button></p>""".format(config.thisTranslation["send"])

if config.displayLanguage == "zh_HANT":
content += """<h3>此處供青少年導師使用,參考如何回應青少年的提問</h3><p>請輸入與聖經相關的提問,然後按下按鈕「{0}」。</p>""".format(config.thisTranslation["send"])
elif config.displayLanguage == "zh_HANS":
content += """<h3>此处供青少年导师使用,参考如何回应青少年的提问</h3><p>请输入与圣经相关的提问,然后按下按钮「{0}」。</p>""".format(config.thisTranslation["send"])
else:
content += """<h3>For Youth Ministry Helpers</h3><p>Please enter a bible-related question and click the button '{0}'.</p>""".format(config.thisTranslation["send"])
content += "<p><input type='text' id='bibleQuestion2' style='width:95%' autofocus></p>"
content += """<p><button id='bibleQuestionButton2' type='button' onclick='answer("YOUTH");' class='ubaButton'>{0}</button></p>""".format(config.thisTranslation["send"])

if config.displayLanguage == "zh_HANT":
content += """<h3>此處供兒童主日學導師使用 - 參考如何回應小朋友的提問</h3><p>請輸入與聖經相關的提問,然後按下按鈕「{0}」。</p>""".format(config.thisTranslation["send"])
elif config.displayLanguage == "zh_HANS":
content += """<h3>此处供儿童主日学导师使用 - 参考如何回应小朋友的提问</h3><p>请输入与圣经相关的提问,然后按下按钮「{0}」。</p>""".format(config.thisTranslation["send"])
else:
content += """<h3>For Children Sunday School Teachers</h3><p>Please enter a bible-related question and click the button '{0}'.</p>""".format(config.thisTranslation["send"])
content += "<p><input type='text' id='bibleQuestion3' style='width:95%' autofocus></p>"
content += """<p><button id='bibleQuestionButton3' type='button' onclick='answer("KID");' class='ubaButton'>{0}</button></p>""".format(config.thisTranslation["send"])

content += "<hr>"

if config.displayLanguage == "zh_HANT":
content += """<p><b>免責聲明:</b> 本網站上由 AI 提供支援的聖經功能旨在提供有關聖經的有用信息和見解。然而,它不能代替個人對經文的學習和反思。聖經本身仍然是基督徒真理和權威的最終來源。請僅將此工具提供的資訊用作參考,並始終查閱聖經以獲得有關您問題的明確答案。</p>"""
elif config.displayLanguage == "zh_HANS":
content += """<p><b>免责声明:</b> 本网站上由 AI 提供支持的圣经功能旨在提供有关圣经的有用信息和见解。然而,它不能代替个人对经文的学习和反思。圣经本身仍然是基督徒真理和权威的最终来源。请仅将此工具提供的信息用作参考,并始终查阅圣经以获得有关您问题的明确答案。</p>"""
else:
content += """<p><b>Disclaimer:</b> The AI-powered Bible feature on this website is intended to provide helpful information and insights about the Bible. However, it is not a substitute for personal study and reflection on the scriptures. The Bible itself remains the ultimate source of truth and authority for Christians. Please use the information provided by this tool for reference only, and always consult the Bible for definitive answers to your questions.</p>"""

content += """
<script>
function answer(mode) {0}
inputField = "";
if (mode == "YOUTH") {0}
inputField = "bibleQuestion2";
{1} else if (mode == "KID") {0}
inputField = "bibleQuestion3";
{1} else {0}
inputField = "bibleQuestion1";
{1}
var searchString = document.getElementById(inputField).value;
document.title = "ANSWER"+mode+":::"+searchString;
{1}
var input1 = document.getElementById('bibleQuestion1');
input1.addEventListener('keyup', function(event) {0}
if (event.keyCode === 13) {0}
event.preventDefault();
document.getElementById('bibleQuestionButton1').click();
{1}
{1});
var input2 = document.getElementById('bibleQuestion2');
input2.addEventListener('keyup', function(event) {0}
if (event.keyCode === 13) {0}
event.preventDefault();
document.getElementById('bibleQuestionButton2').click();
{1}
{1});
var input3 = document.getElementById('bibleQuestion3');
input3.addEventListener('keyup', function(event) {0}
if (event.keyCode === 13) {0}
event.preventDefault();
document.getElementById('bibleQuestionButton3').click();
{1}
{1});
</script>""".format("{", "}")
return content

def mapsContent(self):
content = "<h2>{0}</h2>".format(config.thisTranslation["bibleMaps"])
if config.displayLanguage == "zh_HANT":
Expand Down
120 changes: 120 additions & 0 deletions uniquebible/util/TextCommandParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,21 @@ def __init__(self, parent):
# Usage - DAYAUDIOPLUS:::[BIBLE_VERSION(S)]:::[day_number]
# e.g. DAYAUDIOPLUS:::1
# e.g. DAYAUDIOPLUS:::NET:::1"""),
"answer": (self.textAnswerGeneral, """
# [KEYWORD] ANSWER
# Feature - Answer a bible-related question with AI tools.
# Usage - ANSWER:::[INQUIRY]
# e.g. ANSWER:::Who is Jesus"""),
"answeryouth": (self.textAnswerYouth, """
# [KEYWORD] ANSWERYOUTH
# Feature - Answer a young people a bible-related question with AI tools.
# Usage - ANSWERYOUTH:::[INQUIRY]
# e.g. ANSWERYOUTH:::Who is Jesus"""),
"answerkid": (self.textAnswerKid, """
# [KEYWORD] ANSWERKID
# Feature - Answer a kid a bible-related question with AI tools.
# Usage - ANSWERKID:::[INQUIRY]
# e.g. ANSWERKID:::Who is Jesus"""),
"map": (self.textMap, """
# [KEYWORD] MAP
# Feature - Open a Google map with bible locations pinned
Expand Down Expand Up @@ -4392,6 +4407,111 @@ def getLocationsFromReference(self, reference):
else:
return []

# ANSWER::: ANSWERYOUTH::: ANSWERKID:::

def textAnswerGeneral(self, command, source):
return self.textAnswer(command, source, config.groqApi_systemMessage_general)

def textAnswerYouth(self, command, source):
return self.textAnswer(command, source, config.groqApi_systemMessage_youth)

def textAnswerKid(self, command, source):
return self.textAnswer(command, source, config.groqApi_systemMessage_kid)

def textAnswer(self, command, source, systemMessage):
if not config.groqApi_key:
return ("study", "<p>Groq cloud API key not found!</p>", {'tab_title': "Ask"})
elif command.strip():
import markdown
from groq import Groq
from mistralai import Mistral
# edit the following configurations in config.py
# config.answer_backend
# config.groqApi_key
# config.groqApi_systemMessage_general
# config.groqApi_systemMessage_youth
# config.groqApi_systemMessage_kid
# config.groqApi_llmTemperature
# config.groqApi_chat_model
# config.groqApi_chat_model_max_tokens
# config.mistralApi_key
# config.mistralApi_llmTemperature
# config.mistralApi_chat_model
# config.mistralApi_chat_model_max_tokens
def getGroqApi_key():
'''
support multiple grop api keys
User can manually edit config to change the value of config.groqApi_key to a list of multiple api keys instead of a string of a single api key
'''
if config.groqApi_key:
if isinstance(config.groqApi_key, str):
return config.groqApi_key
elif isinstance(config.groqApi_key, list):
if len(config.groqApi_key) > 1:
# rotate multiple api keys
config.groqApi_key = config.groqApi_key[1:] + [config.groqApi_key[0]]
return config.groqApi_key[0]
else:
return ""
else:
return ""
def getMistralApi_key():
'''
support multiple mistral api keys
User can manually edit config to change the value of config.mistralApi_key to a list of multiple api keys instead of a string of a single api key
'''
if config.mistralApi_key:
if isinstance(config.mistralApi_key, str):
return config.mistralApi_key
elif isinstance(config.mistralApi_key, list):
if len(config.mistralApi_key) > 1:
# rotate multiple api keys
config.mistralApi_key = config.mistralApi_key[1:] + [config.mistralApi_key[0]]
return config.mistralApi_key[0]
else:
return ""
else:
return ""
chatMessages = [
{"role": "system", "content": systemMessage},
{"role": "user", "content": command.strip()},
]
try:
if config.answer_backend == "gorq":
completion = Groq(api_key=getGroqApi_key()).chat.completions.create(
model=config.groqApi_chat_model,
messages=chatMessages,
n=1,
temperature=config.groqApi_llmTemperature,
max_tokens=config.groqApi_chat_model_max_tokens,
stream=False,
)
else:
completion = Mistral(api_key=getMistralApi_key()).chat.complete(
model=config.mistralApi_chat_model,
messages=chatMessages,
n=1,
temperature=config.mistralApi_llmTemperature,
max_tokens=config.mistralApi_chat_model_max_tokens,
stream=False,
)
textOutput = completion.choices[0].message.content
except:
textOutput = "Failed to connect! Please try again later."
if not config.rawOutput:
textOutput = markdown.markdown(textOutput)
if config.runMode == "http-server":
textOutput += """<hr><p><button type='button' onclick='document.title=".qna";' class='ubaButton'>{0}</button></p>""".format(config.thisTranslation["youtube_back"])
# Disclaimer
if config.displayLanguage == "zh_HANT":
textOutput += """<p><b>免責聲明:</b> 本網站上由 AI 提供支援的聖經功能旨在提供有關聖經的有用信息和見解。然而,它不能代替個人對經文的學習和反思。聖經本身仍然是基督徒真理和權威的最終來源。請僅將此工具提供的資訊用作參考,並始終查閱聖經以獲得有關您問題的明確答案。</p>"""
elif config.displayLanguage == "zh_HANS":
textOutput += """<p><b>免责声明:</b> 本网站上由 AI 提供支持的圣经功能旨在提供有关圣经的有用信息和见解。然而,它不能代替个人对经文的学习和反思。圣经本身仍然是基督徒真理和权威的最终来源。请仅将此工具提供的信息用作参考,并始终查阅圣经以获得有关您问题的明确答案。</p>"""
else:
textOutput += """<p><b>Disclaimer:</b> The AI-powered Bible feature on this website is intended to provide helpful information and insights about the Bible. However, it is not a substitute for personal study and reflection on the scriptures. The Bible itself remains the ultimate source of truth and authority for Christians. Please use the information provided by this tool for reference only, and always consult the Bible for definitive answers to your questions.</p>"""
return ("study", textOutput, {'tab_title': "Ask"})
return ("study", "<p>Question not given!</p>", {'tab_title': "Ask"})

# MAP:::
def textMap(self, command, source):
verseList = self.extractAllVerses(command)
Expand Down
Loading

0 comments on commit f63d410

Please sign in to comment.