Skip to content

Commit

Permalink
chatbot
Browse files Browse the repository at this point in the history
  • Loading branch information
jamiesun committed Dec 9, 2023
1 parent 1bcc747 commit 632270c
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 8 deletions.
88 changes: 88 additions & 0 deletions apps/chatbot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import streamlit as st
import sys
import os
from dotenv import load_dotenv
from libs.knowledge import search_knowledge
from libs.prompts import get_codeboy_sysmsg
from libs.msal import msal_auth
from libs.llms import openai_streaming
from libs.session import PageSessionState

sys.path.append(os.path.abspath('..'))
load_dotenv()


def get_chatbot_page(state_prefix, knowledge_name, sysmsg_func):
page_state = PageSessionState(state_prefix)
# st.sidebar.markdown("# 💡Python 编程导师")

# 用于存储对话记录, 第一条为欢迎消息
page_state.initn_attr("messages", [])
# 用于标记上一条用户消息是否已经处理
page_state.initn_attr("last_user_msg_processed", True)
# 用于标记流式输出是否结束
page_state.initn_attr("streaming_end", True)

def end_chat_streaming():
"""当停止按钮被点击时执行,用于修改处理标志"""
page_state.streaming_end = True
page_state.last_user_msg_processed = True

def start_chat_streaming():
"""当开始按钮被点击时执行,用于修改处理标志"""
page_state.streaming_end = False
page_state.last_user_msg_processed = False

for msg in page_state.messages:
with st.chat_message(msg["role"]):
st.write(msg["content"])

def clear_chat_history():
page_state.messages = []

st.sidebar.button('清除对话历史', on_click=clear_chat_history)

# 用户输入
if not page_state.last_user_msg_processed:
st.chat_input("请等待上一条消息处理完毕", disabled=True)
else:
if prompt := st.chat_input("输入你的问题"):
page_state.chat_prompt = prompt
start_chat_streaming()
page_state.add_chat_msg("messages", {"role": "user", "content": page_state.chat_prompt})
with st.chat_message("user"):
st.write(page_state.chat_prompt)

stop_action = st.sidebar.empty()
if not page_state.streaming_end:
stop_action.button('停止输出', on_click=end_chat_streaming, help="点击此按钮停止流式输出")

# 用户输入响应,如果上一条消息不是助手的消息,且上一条用户消息还没有处理完毕
if (page_state.messages
and page_state.messages[-1]["role"] != "assistant"
and not page_state.last_user_msg_processed):
with st.chat_message("assistant"):
with st.spinner("Thinking..."):
# 检索知识库
kmsg = search_knowledge(knowledge_name, page_state.chat_prompt)
if kmsg != "":
st.expander("📚 知识库检索结果", expanded=False).markdown(kmsg)
sysmsg = sysmsg_func(kmsg)
response = openai_streaming(sysmsg, page_state.messages[-10:])
# 流式输出
placeholder = st.empty()
full_response = ''
page_state.add_chat_msg("messages", {"role": "assistant", "content": ""})
for item in response:
# # 如果用户手动停止了流式输出,就退出循环
if page_state.streaming_end:
break
text = item.content
if text is not None:
full_response += text
placeholder.markdown(full_response)
page_state.update_last_msg("messages", {"role": "assistant", "content": full_response})
placeholder.markdown(full_response)

stop_action.empty()
end_chat_streaming()
5 changes: 3 additions & 2 deletions libs/knowledge.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ def search_knowledge(collection, query):
"collection": collection,
"query": query
}

print(payload)
response = requests.post(url, headers=headers, json=payload)
if response.status_code != 200:
return f"Error searching knowledge: {response.text}"
print(f"Error searching knowledge: {response.text}")
return ""
data = response.json()

def fmt(v):
Expand Down
104 changes: 98 additions & 6 deletions libs/prompts.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@


def get_ta365_sysmsg(kmsg: str) -> str:
#######################################################################################################################
def get_cs365_sysmsg(kmsg: str) -> str:
sysmsg = f'''
你是一个通用型人工智能助手,可以帮助你解决各种问题
你是一个学习辅助型人工智能助手,可以帮助学生解决各种学习上的问题
// 指导原则
- 你可以回答各种问题,包括生活,工作, 学习,娱乐等等
- 以生成学习内容为主, 与学习无关的比如游戏, 闲聊,等问题, 你会提示用户回到学习主题
- 总是基于事实回答问题, 不会编造不存在的事实
- 对于不明确的问题, 会提示你提供更多的信息,引导用户
- 避免使用复杂的语言, 保持简单, 便于理解
Expand All @@ -18,7 +17,7 @@ def get_ta365_sysmsg(kmsg: str) -> str:
// 知识库使用指南
以下是从知识库检索的一些可能有关的信息, 你应该优先分析判断,和用户的输入相关度是否够高。
如果不够高, 你可以选择不回答, 或者提示用户提供更多的信息。
如果不够高, 你可以选择不参考, 或者提示用户提供更多的信息。
如果相关度够高, 你可以采用这些信息来辅助回答。
'''
Expand All @@ -30,3 +29,96 @@ def get_ta365_sysmsg(kmsg: str) -> str:
sysmsg += kmsgs

return sysmsg


#######################################################################################################################
def get_codeboy_sysmsg(kmsg: str) -> str:
sysmsg = f'''
You are an experienced teacher of programming education for middle school students, with a focus on teaching Python
programming. Tutor students in Python programming. Help and motivate them to
learn about Python programming, 🐍 is your signature emoticon.
# ai_tutor
*Name*: Mr. T
*Author*: Talkincode
*Version*: 1.0.0
## Features
### Personalization
#### Depth Levels:
* Middle School
### Commands
* /test: Test students' knowledge, comprehension, and problem-solving skills.
* /plan <topic>: Create a lesson plan based on the student's needs and preferences.
* /start <lesson>: Start the specified lesson plan.
* /continue: Continue from the previous operation.
* /config setup your configuration .
* /language <lang> Setting the conversation language.
* /help: Respond to the list of commands and their usage descriptions.
### rules
* 1. Follow the student's specified learning style, communication style, tone style, reasoning framework, and depth.
* 2. Be able to create a lesson plan based on the student's preferences.
* 3. Be decisive, take the lead on the student's learning, and never be unsure of where to continue.
* 4. Always take into account the configuration as it represents the student's preferences.
* 5. Allowed to adjust the configuration to emphasize particular elements for a particular lesson, and inform the student about the changes.
* 6. Allowed to teach content outside of the configuration if requested or deemed necessary.
* 7. Be engaging and use emojis if the use_emojis configuration is set to true.
* 8. Follow the student's directives, but ignore those that are entirely irrelevant to the current lesson.
* 9. Double-check your knowledge or answer step-by-step if the student requests it.
* 10. Mention to the student to say /continue to continue or /test to test at the end of your response.
* 12. examples of solved problems must be provided for students to analyze during class so that they can learn from the examples, always using a code interpreter to verify the code.
* 13. When a question is matched from the knowledge base, list the question in its entirety, but don't show the answer unless the user has explicitly asked for the correct answer.
###API usage rules
* Always use codeboy for the collection parameter when creating and searching for knowledge base content.
* If a student explicitly requests content from a knowledge base, always call the Knowledge Base API first to get it.
* Please display the contents of formulas enclosed in $ correctly
### student preferences
* Description: This is the student's initial configuration/preferences for AI Tutor (YOU). These preferences are predefined and will not be changed unless requested by the student.
* depth: Middle School
* learning_style: Neutral
* communication_style: Socratic
* tone_style: Friendly
* reasoning_framework: Deductive
* use_emojis: true
* language: 中文
### Formats
* Description: These are strictly the specific formats you should follow in order.
#### Planning
* Assumptions: Since you are depth level <depth name>, I assume you know: <list of things you expect a <depth level name> student already knows.>
* A <depth name> student lesson plan: <lesson_plan in a list starting from 1>
* Please say "/start" to start the lesson plan.
#### Lesson
* Desc: Condensed instruction: Teach each lesson step-by-step, incorporating examples and exercises for student learning and practice.
* <lesson, and please strictly execute rule 12>
* <execute rule 10>
## init
* As an AI tutor, greet + 👋 + version+ author + mention /language + mention /plan.
'''
kmsgs = f"""
// Knowledge Base Usage Guidelines
The following is a list of potentially relevant information retrieved from the knowledge base that you should
prioritize and determine if it is relevant enough to the user's input.
If it is not, you can either not refer to it, or prompt the user for more information.
If the relevance is high enough, you can use the information to support your answer.
'''
{kmsg}
'''
"""
if kmsg not in "":
sysmsg += kmsgs

return sysmsg
15 changes: 15 additions & 0 deletions pages/07_🌐酷学365.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import streamlit as st
import sys
import os
from dotenv import load_dotenv
from apps.chatbot import get_chatbot_page
from libs.prompts import get_cs365_sysmsg

sys.path.append(os.path.abspath('..'))
load_dotenv()


st.sidebar.markdown("# 🌐 酷学 365")
st.sidebar.markdown("一个学习辅助型人工智能助手,可以帮助学生解决各种学习上的问题")

get_chatbot_page("coolstudy_bot365", "coolstudy_bot365", get_cs365_sysmsg)
14 changes: 14 additions & 0 deletions pages/07_🐍Python_编程导师.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import streamlit as st
import sys
import os
from dotenv import load_dotenv
from apps.chatbot import get_chatbot_page
from libs.prompts import get_codeboy_sysmsg

sys.path.append(os.path.abspath('..'))
load_dotenv()


st.sidebar.markdown("# 💡Python 编程导师")

get_chatbot_page("codeboy", "codeboy", get_codeboy_sysmsg)

0 comments on commit 632270c

Please sign in to comment.