'commit'
This commit is contained in:
8
dsAi/.idea/.gitignore
generated
vendored
Normal file
8
dsAi/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# 默认忽略的文件
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# 基于编辑器的 HTTP 客户端请求
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
18
dsAi/.idea/compiler.xml
generated
Normal file
18
dsAi/.idea/compiler.xml
generated
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CompilerConfiguration">
|
||||||
|
<annotationProcessing>
|
||||||
|
<profile name="Maven default annotation processors profile" enabled="true">
|
||||||
|
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||||
|
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||||
|
<outputRelativeToContentRoot value="true" />
|
||||||
|
<module name="dsAi" />
|
||||||
|
</profile>
|
||||||
|
</annotationProcessing>
|
||||||
|
</component>
|
||||||
|
<component name="JavacSettings">
|
||||||
|
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||||
|
<module name="dsAi" options="-parameters" />
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
7
dsAi/.idea/encodings.xml
generated
Normal file
7
dsAi/.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||||
|
</component>
|
||||||
|
</project>
|
6
dsAi/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
6
dsAi/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
6
dsAi/.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
dsAi/.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
25
dsAi/.idea/jarRepositories.xml
generated
Normal file
25
dsAi/.idea/jarRepositories.xml
generated
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RemoteRepositoriesConfiguration">
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="central" />
|
||||||
|
<option name="name" value="Central Repository" />
|
||||||
|
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="ali-maven" />
|
||||||
|
<option name="name" value="ali-maven" />
|
||||||
|
<option name="url" value="https://maven.aliyun.com/nexus/content/groups/public" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="central" />
|
||||||
|
<option name="name" value="Maven Central repository" />
|
||||||
|
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="jboss.community" />
|
||||||
|
<option name="name" value="JBoss Community repository" />
|
||||||
|
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||||
|
</remote-repository>
|
||||||
|
</component>
|
||||||
|
</project>
|
12
dsAi/.idea/misc.xml
generated
Normal file
12
dsAi/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="MavenProjectsManager">
|
||||||
|
<option name="originalFiles">
|
||||||
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/pom.xml" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK" />
|
||||||
|
</project>
|
6
dsAi/.idea/vcs.xml
generated
Normal file
6
dsAi/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
28
dsAi/src/main/java/com/dsideal/Ai/Util/JiMeng/Doc/文档.md
Normal file
28
dsAi/src/main/java/com/dsideal/Ai/Util/JiMeng/Doc/文档.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
### 火山引擎
|
||||||
|
|
||||||
|
账号:18686619970
|
||||||
|
密码:短信验证码
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```
|
||||||
|
// API访问凭证
|
||||||
|
protected static final String ak="AKLTZjVlOGU1NzA1YWZkNDExMzkzYzY5YTNlOTRmMTMxODg"; // Access Key
|
||||||
|
protected static final String sk="WkdabU9UTXdNVEJpTmpWbE5HVTJZVGxtTnpWbU5XSTBaRGN5TW1NMk5tRQ=="; // Secret Key
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 使用内容
|
||||||
|
|
||||||
|
1. 即梦AI
|
||||||
|
|
||||||
|
https://www.volcengine.com/docs/85621/1544716
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
2. 视觉识别模型
|
||||||
|
|
||||||
|
开发拍照解题APP,推荐使用**doubao-seed-1-6-thinking(版本250715)** 或 **doubao-1-5-thinking-vision-pro(版本250428)**,二者均支持图像理解与深度推理,可精准解析题目并生成解题步骤。
|
||||||
|
|
||||||
|
|
@@ -37,7 +37,7 @@ async def get_tree_data(request: fastapi.Request):
|
|||||||
prerequisites = prerequisite_data
|
prerequisites = prerequisite_data
|
||||||
else:
|
else:
|
||||||
# 转换为新格式
|
# 转换为新格式
|
||||||
prerequisites = [{{"id": str(id), "title": title}} for id, title in (prerequisite_data or [])] if prerequisite_data else None
|
prerequisites = [{"id": str(id), "title": title} for id, title in (prerequisite_data or [])] if prerequisite_data else None
|
||||||
|
|
||||||
related_data = json.loads(row[5]) if row[5] else []
|
related_data = json.loads(row[5]) if row[5] else []
|
||||||
# 转换相关知识格式
|
# 转换相关知识格式
|
||||||
@@ -46,9 +46,9 @@ async def get_tree_data(request: fastapi.Request):
|
|||||||
related = related_data
|
related = related_data
|
||||||
else:
|
else:
|
||||||
# 转换为新格式
|
# 转换为新格式
|
||||||
related = [{{"id": str(id), "title": title}} for id, title in (related_data or [])] if related_data else None
|
related = [{"id": str(id), "title": title} for id, title in (related_data or [])] if related_data else None
|
||||||
|
|
||||||
node = {{
|
node = {
|
||||||
"id": row[0],
|
"id": row[0],
|
||||||
"title": row[1],
|
"title": row[1],
|
||||||
"parent_id": row[2],
|
"parent_id": row[2],
|
||||||
@@ -56,7 +56,7 @@ async def get_tree_data(request: fastapi.Request):
|
|||||||
"prerequisite": prerequisites,
|
"prerequisite": prerequisites,
|
||||||
"related": related,
|
"related": related,
|
||||||
"children": []
|
"children": []
|
||||||
}}
|
}
|
||||||
nodes[row[0]] = node
|
nodes[row[0]] = node
|
||||||
|
|
||||||
# 构建树结构
|
# 构建树结构
|
||||||
@@ -71,9 +71,9 @@ async def get_tree_data(request: fastapi.Request):
|
|||||||
nodes[parent_id]["children"] = []
|
nodes[parent_id]["children"] = []
|
||||||
nodes[parent_id]["children"].append(node)
|
nodes[parent_id]["children"].append(node)
|
||||||
|
|
||||||
return {{"code": 0, "data": tree_data}}
|
return {"code": 0, "data": tree_data}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {{"code": 1, "msg": str(e)}}
|
return {"code": 1, "msg": str(e)}
|
||||||
|
|
||||||
# 更新知识节点接口
|
# 更新知识节点接口
|
||||||
@router.post("/update-knowledge")
|
@router.post("/update-knowledge")
|
||||||
@@ -96,7 +96,7 @@ async def update_knowledge(request: Request):
|
|||||||
WHERE id = $2
|
WHERE id = $2
|
||||||
""",
|
""",
|
||||||
json.dumps(
|
json.dumps(
|
||||||
[{{"id": p["id"], "title": p["title"]}} for p in knowledge],
|
[{"id": p["id"], "title": p["title"]} for p in knowledge],
|
||||||
ensure_ascii=False
|
ensure_ascii=False
|
||||||
),
|
),
|
||||||
node_id)
|
node_id)
|
||||||
@@ -107,11 +107,11 @@ async def update_knowledge(request: Request):
|
|||||||
WHERE id = $2
|
WHERE id = $2
|
||||||
""",
|
""",
|
||||||
json.dumps(
|
json.dumps(
|
||||||
[{{"id": p["id"], "title": p["title"]}} for p in knowledge],
|
[{"id": p["id"], "title": p["title"]} for p in knowledge],
|
||||||
ensure_ascii=False
|
ensure_ascii=False
|
||||||
),
|
),
|
||||||
node_id)
|
node_id)
|
||||||
|
|
||||||
return {{"code": 0, "msg": "更新成功"}}
|
return {"code": 0, "msg": "更新成功"}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {{"code": 1, "msg": str(e)}}
|
return {"code": 1, "msg": str(e)}
|
@@ -1,406 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="zh-CN">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>浮力AI助手</title>
|
|
||||||
<style>
|
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
font-family: 'Microsoft YaHei', Arial, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.simulation-panel {
|
|
||||||
flex: 0 0 60%;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
overflow: hidden;
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.simulation-panel iframe {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-panel {
|
|
||||||
flex: 0 0 40%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
background-color: white;
|
|
||||||
box-shadow: -2px 0 5px rgba(0,0,0,0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-header {
|
|
||||||
padding: 15px;
|
|
||||||
background-color: #2196F3;
|
|
||||||
color: white;
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-messages {
|
|
||||||
flex: 1;
|
|
||||||
padding: 15px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
max-width: 85%;
|
|
||||||
padding: 10px 15px;
|
|
||||||
border-radius: 18px;
|
|
||||||
word-break: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-message {
|
|
||||||
background-color: #E3F2FD;
|
|
||||||
margin-left: auto;
|
|
||||||
border-top-right-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ai-message {
|
|
||||||
background-color: #f1f1f1;
|
|
||||||
border-top-left-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-content {
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-input {
|
|
||||||
display: flex;
|
|
||||||
padding: 10px;
|
|
||||||
border-top: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-input textarea {
|
|
||||||
flex: 1;
|
|
||||||
padding: 10px 15px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
border-radius: 4px;
|
|
||||||
resize: none;
|
|
||||||
height: 40px;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-input button {
|
|
||||||
padding: 0 15px;
|
|
||||||
background-color: #2196F3;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-input button:hover {
|
|
||||||
background-color: #1976D2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-indicator {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-dot {
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: #2196F3;
|
|
||||||
margin: 0 4px;
|
|
||||||
animation: pulse 1.4s infinite ease-in-out both;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-dot:nth-child(1) {
|
|
||||||
animation-delay: -0.32s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-dot:nth-child(2) {
|
|
||||||
animation-delay: -0.16s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes pulse {
|
|
||||||
0%, 80%, 100% {
|
|
||||||
transform: scale(0);
|
|
||||||
}
|
|
||||||
40% {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 默认问题按钮样式 */
|
|
||||||
.default-questions {
|
|
||||||
padding: 10px 15px;
|
|
||||||
}
|
|
||||||
.question-buttons {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
.default-question-btn {
|
|
||||||
background-color: #E3F2FD;
|
|
||||||
border: 1px solid #2196F3;
|
|
||||||
border-radius: 16px;
|
|
||||||
padding: 6px 12px;
|
|
||||||
font-size: 14px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #2196F3;
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
.default-question-btn:hover {
|
|
||||||
background-color: #2196F3;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<div class="simulation-panel">
|
|
||||||
<iframe src="deepseek_fulishiyanshi.html"></iframe>
|
|
||||||
</div>
|
|
||||||
<div class="chat-panel">
|
|
||||||
<div class="chat-header">浮力AI助手</div>
|
|
||||||
<div class="chat-messages" id="chatMessages">
|
|
||||||
<div class="message ai-message">
|
|
||||||
<div class="message-content">您好!我是浮力AI助手,可以帮助您理解浮力相关的物理知识。请随时提问,我会尽力为您解答。</div>
|
|
||||||
</div>
|
|
||||||
<div class="message ai-message default-questions">
|
|
||||||
<p style="margin-bottom: 8px; font-weight: bold;">推荐问题:</p>
|
|
||||||
<div class="question-buttons">
|
|
||||||
<button class="default-question-btn">什么是浮力?</button>
|
|
||||||
<button class="default-question-btn">浮力的计算公式是什么?</button>
|
|
||||||
<button class="default-question-btn">物体的浮沉条件是什么?</button>
|
|
||||||
<button class="default-question-btn">阿基米德原理的内容是什么?</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="chat-input">
|
|
||||||
<textarea id="userInput" placeholder="请输入您的问题..."></textarea>
|
|
||||||
<button id="sendBtn">发送</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
const chatMessages = document.getElementById('chatMessages');
|
|
||||||
const userInput = document.getElementById('userInput');
|
|
||||||
const sendBtn = document.getElementById('sendBtn');
|
|
||||||
let isLoading = false;
|
|
||||||
|
|
||||||
// 发送消息
|
|
||||||
function sendMessage() {
|
|
||||||
const message = userInput.value.trim();
|
|
||||||
if (!message || isLoading) return;
|
|
||||||
|
|
||||||
// 添加用户消息
|
|
||||||
addMessage(message, 'user');
|
|
||||||
userInput.value = '';
|
|
||||||
|
|
||||||
// 显示加载中
|
|
||||||
showLoading();
|
|
||||||
|
|
||||||
// 发送POST请求到/api/llm
|
|
||||||
fetch('/api/llm', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ question: message })
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('HTTP error! status: ' + response.status);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理流式响应
|
|
||||||
const reader = response.body.getReader();
|
|
||||||
const decoder = new TextDecoder();
|
|
||||||
let buffer = '';
|
|
||||||
let aiMessageElement = null;
|
|
||||||
let aiMessageContentElement = null;
|
|
||||||
|
|
||||||
function processChunk({ done, value }) {
|
|
||||||
if (done) {
|
|
||||||
// 处理最后一块数据
|
|
||||||
if (buffer) {
|
|
||||||
handleSSEMessage(buffer, aiMessageElement, aiMessageContentElement);
|
|
||||||
}
|
|
||||||
hideLoading();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解码接收到的数据
|
|
||||||
const chunk = decoder.decode(value, { stream: true });
|
|
||||||
buffer += chunk;
|
|
||||||
|
|
||||||
// 按行分割数据
|
|
||||||
const lines = buffer.split('\n');
|
|
||||||
buffer = lines.pop(); // 保存不完整的行
|
|
||||||
|
|
||||||
// 如果还没有创建AI消息元素,则创建
|
|
||||||
if (!aiMessageElement) {
|
|
||||||
aiMessageElement = document.createElement('div');
|
|
||||||
aiMessageElement.className = 'message ai-message';
|
|
||||||
aiMessageContentElement = document.createElement('div');
|
|
||||||
aiMessageContentElement.className = 'message-content';
|
|
||||||
aiMessageElement.appendChild(aiMessageContentElement);
|
|
||||||
chatMessages.appendChild(aiMessageElement);
|
|
||||||
scrollToBottom();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理每一行
|
|
||||||
for (const line of lines) {
|
|
||||||
if (line.trim()) {
|
|
||||||
handleSSEMessage(line, aiMessageElement, aiMessageContentElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 继续读取
|
|
||||||
return reader.read().then(processChunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始读取响应体
|
|
||||||
return reader.read().then(processChunk);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('发送请求失败:', error);
|
|
||||||
hideLoading();
|
|
||||||
addMessage('抱歉,请求失败: ' + error.message, 'ai');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理SSE消息
|
|
||||||
function handleSSEMessage(line, aiMessageElement, aiMessageContentElement) {
|
|
||||||
// 检查是否是SSE格式 (以'data: '开头)
|
|
||||||
if (line.startsWith('data: ')) {
|
|
||||||
const data = line.substring(6).trim();
|
|
||||||
|
|
||||||
// 检查是否是结束信号
|
|
||||||
if (data === 'DONE') {
|
|
||||||
hideLoading();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 解析JSON
|
|
||||||
const jsonData = JSON.parse(data);
|
|
||||||
// 提取content字段
|
|
||||||
if (jsonData.content) {
|
|
||||||
aiMessageContentElement.textContent += jsonData.content;
|
|
||||||
scrollToBottom();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('解析JSON失败:', error, '数据:', data);
|
|
||||||
// 如果解析失败,尝试直接添加文本
|
|
||||||
aiMessageContentElement.textContent += data;
|
|
||||||
scrollToBottom();
|
|
||||||
}
|
|
||||||
} else if (line) {
|
|
||||||
// 如果不是标准SSE格式,尝试直接解析
|
|
||||||
try {
|
|
||||||
const jsonData = JSON.parse(line);
|
|
||||||
if (jsonData.content) {
|
|
||||||
aiMessageContentElement.textContent += jsonData.content;
|
|
||||||
scrollToBottom();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('解析非标准SSE数据失败:', error, '数据:', line);
|
|
||||||
// 如果解析失败,直接添加文本
|
|
||||||
aiMessageContentElement.textContent += line;
|
|
||||||
scrollToBottom();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加消息到聊天框
|
|
||||||
function addMessage(message, sender) {
|
|
||||||
const messageElement = document.createElement('div');
|
|
||||||
messageElement.className = `message ${sender}-message`;
|
|
||||||
|
|
||||||
const contentElement = document.createElement('div');
|
|
||||||
contentElement.className = 'message-content';
|
|
||||||
contentElement.textContent = message;
|
|
||||||
|
|
||||||
messageElement.appendChild(contentElement);
|
|
||||||
chatMessages.appendChild(messageElement);
|
|
||||||
scrollToBottom();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示加载中
|
|
||||||
function showLoading() {
|
|
||||||
if (isLoading) return;
|
|
||||||
isLoading = true;
|
|
||||||
|
|
||||||
const loadingElement = document.createElement('div');
|
|
||||||
loadingElement.className = 'loading-indicator';
|
|
||||||
loadingElement.id = 'loading-indicator';
|
|
||||||
|
|
||||||
for (let i = 0; i < 3; i++) {
|
|
||||||
const dot = document.createElement('div');
|
|
||||||
dot.className = 'loading-dot';
|
|
||||||
loadingElement.appendChild(dot);
|
|
||||||
}
|
|
||||||
|
|
||||||
chatMessages.appendChild(loadingElement);
|
|
||||||
scrollToBottom();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 隐藏加载中
|
|
||||||
function hideLoading() {
|
|
||||||
if (!isLoading) return;
|
|
||||||
isLoading = false;
|
|
||||||
|
|
||||||
const loadingElement = document.getElementById('loading-indicator');
|
|
||||||
if (loadingElement) {
|
|
||||||
loadingElement.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 滚动到底部
|
|
||||||
function scrollToBottom() {
|
|
||||||
chatMessages.scrollTop = chatMessages.scrollHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发送按钮点击事件
|
|
||||||
sendBtn.addEventListener('click', sendMessage);
|
|
||||||
|
|
||||||
// 输入框回车事件
|
|
||||||
userInput.addEventListener('keypress', function(e) {
|
|
||||||
if (e.key === 'Enter' && !e.shiftKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
sendMessage();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 绑定默认问题按钮事件
|
|
||||||
document.querySelectorAll('.default-question-btn').forEach(btn => {
|
|
||||||
btn.addEventListener('click', function() {
|
|
||||||
const question = this.textContent;
|
|
||||||
userInput.value = question;
|
|
||||||
sendMessage();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@@ -1,14 +0,0 @@
|
|||||||
SYSTEM_PROMPT_TEMPLATE="""
|
|
||||||
# 数学解题助手规则(必须严格遵守)
|
|
||||||
|
|
||||||
1. 【核心要求】必须使用初中生知识范围内可以理解的方法解题,绝对禁止使用向量、微积分、复数等高中及以上数学知识。
|
|
||||||
2. 如果是动点问题要注意可能有多个解。
|
|
||||||
3. 使用简单易懂的语言,将复杂问题分解成简单的步骤。
|
|
||||||
4. 引导学生思考,而不是直接给出答案。
|
|
||||||
|
|
||||||
# 角色信息
|
|
||||||
- language: 中文
|
|
||||||
- description: 数学解题助手是一个专门为初中生提供数学问题解答的角色。
|
|
||||||
- expertise: 初中数学解题、数学教育
|
|
||||||
- target_audience: 初中生
|
|
||||||
"""
|
|
Reference in New Issue
Block a user