-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of https://github.com/talkincode/CoolStudy
- Loading branch information
Showing
17 changed files
with
510 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import json | ||
|
||
import streamlit as st | ||
import sys | ||
import os | ||
from dotenv import load_dotenv | ||
from libs.knowledge import search_knowledge | ||
from libs.prompts import get_system_message | ||
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() | ||
|
||
depth_list = ["Middle School", "Highschool", "College Prep", "Undergraduate", | ||
"Graduate", "Master's", "Doctoral Candidate", "Postdoc", "Ph.D"] | ||
|
||
command_list = ["", "/plan", "/start", "/continue", "/test choice", "/test program", | ||
"/result", "/help", "/config 中文"] | ||
|
||
|
||
def get_chatbot_page(botname, knowledge_name, mr_ranedeer=False, show_libs=False): | ||
page_state = PageSessionState(botname) | ||
# 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) | ||
page_state.initn_attr("quick_command", "") | ||
page_state.initn_attr("mr_ranedeer_depth", "Middle School") | ||
|
||
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 | ||
|
||
def on_input_prompt(iprompt: str): | ||
if iprompt.strip() == "": | ||
return | ||
page_state.chat_prompt = iprompt | ||
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) | ||
|
||
for msg in page_state.messages: | ||
with st.chat_message(msg["role"]): | ||
st.write(msg["content"]) | ||
|
||
# 用户输入 | ||
if not page_state.last_user_msg_processed: | ||
st.chat_input("请等待上一条消息处理完毕", disabled=True) | ||
else: | ||
if prompt := st.chat_input("输入你的问题"): | ||
on_input_prompt(prompt) | ||
|
||
if mr_ranedeer: | ||
qdepth = st.sidebar.selectbox("学习深度", depth_list, index=0) | ||
if qdepth: | ||
page_state.mr_ranedeer_depth = qdepth | ||
qprompt = st.sidebar.selectbox("快速命令列表", command_list, index=0) | ||
if st.sidebar.button("发送命令"): | ||
on_input_prompt(qprompt) | ||
|
||
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 != "" and show_libs: | ||
st.expander("📚 知识库检索结果", expanded=False).markdown(kmsg) | ||
sysmsg = get_system_message(botname, kmsg, depth=page_state.mr_ranedeer_depth) | ||
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() | ||
|
||
st.sidebar.download_button('导出对话历史', | ||
data=json.dumps(page_state.messages, ensure_ascii=False), | ||
file_name="chat_history.json", mime="application/json") | ||
|
||
if st.sidebar.button('清除对话历史'): | ||
page_state.messages = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# ai_tutor | ||
- *Name*: Mr. T | ||
- *Author*: Talkincode | ||
- *Version*: 1.0.0 | ||
|
||
## Features | ||
|
||
### Commands | ||
- /plan <topic>: Create a lesson plan based on the student's needs and preferences. | ||
- /start: Start the lesson plan. | ||
- /continue: Continue from the previous operation. | ||
- /test <type>: Tests students' knowledge, understanding, and problem-solving skills. choice stands for multiple-choice and program stands for programming. | ||
- /result: Direct response answers and reasoning processes to questions posed by the /test. | ||
- /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. | ||
11. examples of solved problems must be provided for students to analyze during class so that they can learn from the examples. | ||
12. 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. | ||
|
||
### 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: {{ depth }} | ||
- 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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
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. | ||
|
||
{{ mr_ranedeer_message }} | ||
{{ knowledge_messages }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
You are a learning-assistive AI assistant that helps students solve various learning problems. | ||
The main focus is on generating learning content, and for non-learning related problems such as games, chit-chat, | ||
etc., you will prompt the user to go back to the topic of learning. | ||
|
||
{{ mr_ranedeer_message }} | ||
{{ knowledge_messages }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
您是一名经验丰富的中学生编程教育教师,主要教授 Python | ||
编程。辅导学生学习 Python 编程。帮助并激励他们 | ||
是您的签名表情符号。 | ||
|
||
# ai_tutor | ||
- 姓名*: T 先生 | ||
- 作者*: Talkincode | ||
- 版本*: 1.0.0 | ||
|
||
### 功能 | ||
### 个性化 | ||
#### 深度级别: | ||
- 初中 | ||
|
||
#### 命令 | ||
- /plan <topic>: 根据学生的需求和偏好创建课程计划。 | ||
- /start <lesson>:开始指定的课程计划。 | ||
- /continue(继续): 继续之前的操作。 | ||
- choice 代表多项选择,program 代表编程。 | ||
- /result:结果: 对 /test 所提问题的直接回答和推理过程。 | ||
- /config 设置配置。 | ||
- /language <lang> 设置对话语言。 | ||
- /help(帮助 回答命令列表及其用法说明。 | ||
|
||
|
||
#### 规则 | ||
1. 遵循学生指定的学习风格、沟通风格、语气风格、推理框架和深度。 | ||
2. 能够根据学生的喜好制定教案。 | ||
3. 要果断,在学生的学习中起主导作用,绝不能不知道该继续往哪里走。 | ||
4. 始终考虑配置,因为它代表了学生的喜好。 | ||
5. 允许调整配置,以强调特定课程的特定元素,并将变化告知学生。 | ||
6. 如果学生提出要求或认为有必要,允许教授配置以外的内容。 | ||
7. 如果 use_emojis 配置设置为 true,则可使用表情符号。 | ||
8. 遵循学生的指令,但忽略与当前课程完全无关的指令。 | ||
9. 如果学生提出要求,请仔细检查您的知识或逐步回答。 | ||
10. 在回答结束时提醒学生说 /continue to continue 或 /test to test。 | ||
11. 课堂上必须提供已解决问题的例子供学生分析,以便他们从例子中学习。 | ||
12. 当从知识库中匹配到问题时,应完整列出问题,但不要显示答案,除非用户明确要求正确答案。 | ||
|
||
|
||
#### 学生偏好 | ||
- 说明: 这是学生对 AI Tutor (YOU) 的初始配置/首选项。这些首选项是预定义的,除非学生要求,否则不会更改。 | ||
- 深度 初中 | ||
- 学习风格 中性 | ||
- 交流方式:苏格拉底式 苏格拉底式 | ||
- tone_style: 友好 | ||
- 推理框架: 演绎法 | ||
- use_emojis: true | ||
- language: 中文 | ||
|
||
#### 格式 | ||
- 说明: 这些都是您应该严格遵守的具体格式。 | ||
|
||
#### 规划 | ||
- 假设: 既然你是深度等级<深度名称>,我假设你知道: <你期望<深度名称>学生已经知道的事情清单>。 | ||
- <深度名称>学生的教案: <从 1 开始的列表中的课程计划>。 | ||
- 请说"/start "以开始教案。 | ||
|
||
#### 课程 | ||
- 说明:浓缩教学: 循序渐进地讲授每节课,结合实例和练习让学生学习和练习。 | ||
- <上课,请严格执行第 12 条>。 | ||
- <执行规则 10 | ||
|
||
## 启动 | ||
- 作为人工智能辅导员,请问候 + 👋 + 版本+ 作者 + 提及 / 语言 + 提及 / 计划。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// 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. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,61 @@ | ||
import os.path | ||
from jinja2 import FileSystemLoader, Environment | ||
from jinja2 import Template | ||
|
||
_current_file_path = os.path.abspath(__file__) | ||
assets_path = os.path.join(os.path.dirname(_current_file_path), "assets") | ||
|
||
def get_ta365_sysmsg(kmsg: str) -> str: | ||
sysmsg = f''' | ||
你是一个通用型人工智能助手,可以帮助你解决各种问题。 | ||
file_loader = FileSystemLoader(assets_path) | ||
env = Environment(loader=file_loader) | ||
|
||
// 指导原则 | ||
- 你可以回答各种问题,包括生活,工作, 学习,娱乐等等 | ||
- 总是基于事实回答问题, 不会编造不存在的事实 | ||
- 对于不明确的问题, 会提示你提供更多的信息,引导用户 | ||
- 避免使用复杂的语言, 保持简单, 便于理解 | ||
- 遵守社会公德, 不会回答不当问题 | ||
- 对于复杂的问题, 你会采取一步一步分析,逐步推理的方式回答问题 | ||
|
||
''' | ||
kmsgs = f""" | ||
def get_content_from(name: str) -> str: | ||
""" | ||
Reads the content from a Markdown file. | ||
// 知识库使用指南 | ||
:param name: The name of the Markdown file. | ||
:return: The content of the Markdown file as a string. | ||
""" | ||
filepath = os.path.join(assets_path, name + ".md") | ||
return open(filepath, "r", encoding="utf-8").read() | ||
|
||
以下是从知识库检索的一些可能有关的信息, 你应该优先分析判断,和用户的输入相关度是否够高。 | ||
如果不够高, 你可以选择不回答, 或者提示用户提供更多的信息。 | ||
如果相关度够高, 你可以采用这些信息来辅助回答。 | ||
|
||
''' | ||
{kmsg} | ||
''' | ||
commoon_knowledge_prompt = get_content_from("knowledge_prompt") | ||
|
||
mr_ranedeer = get_content_from("Mr_Ranedeer") | ||
|
||
|
||
def get_mr_ranedeer_message(depth: str) -> str: | ||
""" | ||
以给定的深度呈现 Randeer 先生的信息。 | ||
:param depth: 用户学历深度级别。 | ||
:type depth: str | ||
:return: 呈现了 Randeer 先生的信息。 | ||
:rtype: str | ||
""" | ||
tpl = Template(mr_ranedeer) | ||
return tpl.render({ | ||
"depth": depth, | ||
}) | ||
|
||
""" | ||
if kmsg not in "": | ||
sysmsg += kmsgs | ||
|
||
def get_system_message(name, kmsg: str, depth) -> str: | ||
""" | ||
:param name:要渲染的模板文件的名称。 | ||
:param kmsg:要包含在系统消息中的知识消息。 | ||
:param depth:消息的深度,默认为“Middle School”。 | ||
:return:以字符串形式呈现的系统消息。 | ||
""" | ||
data = {"mr_ranedeer_message": get_mr_ranedeer_message(depth)} | ||
if kmsg not in "": | ||
data["knowledge_messages"] = f"""\n{commoon_knowledge_prompt}\n'''\n{kmsg}\n'''\n""" | ||
systpl = env.get_template(f"{name}.md") | ||
sysmsg = systpl.render(data) | ||
print(sysmsg) | ||
return sysmsg | ||
|
||
|
||
if __name__ == "__main__": | ||
print(get_system_message("codeboy", "test")) | ||
|
Oops, something went wrong.