Error in user YAML: (<unknown>): found a tab character that violate indentation while scanning a plain scalar at line 3 column 3
---
- oeasy Python 0782
- 这是 oeasy 系统化 Python 教程,从基础一步步讲,扎实、完整、不跳步。愿意花时间学,就能真正学会。
- 本教程同步发布在:
- 个人网站: `https://oeasy.org`
- 蓝桥云课: `https://www.lanqiao.cn/courses/3584`
- GitHub: `https://github.com/overmind1980/oeasy-python-tutorial`
- Gitee: `https://gitee.com/overmind1980/oeasypython`
----
上次 可以把代码整合成一个py文件
- 把index.html嵌入到app.py中
-
也可以 使用restful的方式直接向大模型提交请求
- 使用 纯html的方式
-
Flask 两种结构对比(极简表格版)
| 维度 | 纯 app.py | app.py + index.html |
|---|---|---|
| 核心特点 | 代码里“藏”页面,一锅炖 | 逻辑、页面分开,各管各 |
| 开发快慢 | 小需求快(不用切文件) | 大需求快(改界面不碰逻辑) |
| 好不好改 | 改界面=动代码,容易乱 | 改界面只动 HTML,很安全 |
| 适合场景 | 临时测、小工具(1-2个功能) | 正经 app、要加页面的项目 |
| 一句话总结 | 快但“乱”,适合临时用 | 清且“稳”,适合长期做 |
- 怎么让大模型返回的数据看起来更好看呢?🤔
- 在最开始的状态下
- md文档无法在网页中有相应的格式
大模型当前返回的是 Markdown (MD) 格式文档,其中包含多种 Markdown 语法元素,如使用 #、##、### 等符号表示的不同级别标题、表格结构以及加粗等文本样式。这些 Markdown 格式内容在 HTML 页面中无法直接正常渲染显示,目前仅能以 Markdown 源文件的原始文本形式呈现。请帮我修改相关代码或实现相应功能,将 Markdown 格式的内容正确转换并渲染为美观的 HTML 格式,确保所有 Markdown 语法元素(包括但不限于标题、表格、加粗文本等)都能在 HTML 页面中正常显示。
- 这次引入了一个marked.js
- 用于在前端渲染markdown 文本
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>对话</title>
<!-- 引入marked.js用于Markdown渲染 -->
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<style>
body { margin: 0; padding: 20px; font-family: Arial; }
#messages { height: 400px; overflow-y: auto; border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; }
.user, .assistant { margin: 5px 0; padding: 8px; border-radius: 5px; }
.user { text-align: right; background: #e3f2fd; }
.assistant { background: #f5f5f5; }
input { width: 75%; padding: 10px; border: 1px solid #ccc; }
button { padding: 10px 15px; background: #333; color: white; border: none; cursor: pointer; }
/* Markdown样式 */
.markdown-content h1, .markdown-content h2, .markdown-content h3 {
margin: 10px 0;
font-weight: bold;
}
.markdown-content h1 { font-size: 24px; border-bottom: 1px solid #ddd; padding-bottom: 5px; }
.markdown-content h2 { font-size: 20px; }
.markdown-content h3 { font-size: 18px; }
.markdown-content p { margin: 10px 0; }
.markdown-content ul, .markdown-content ol { margin: 10px 0; padding-left: 20px; }
.markdown-content li { margin: 5px 0; }
.markdown-content blockquote {
border-left: 4px solid #ddd;
padding-left: 10px;
color: #666;
margin: 10px 0;
}
.markdown-content code {
background: #f4f4f4;
padding: 2px 4px;
border-radius: 3px;
font-family: monospace;
}
.markdown-content pre {
background: #f4f4f4;
padding: 10px;
border-radius: 5px;
overflow-x: auto;
margin: 10px 0;
}
.markdown-content table {
border-collapse: collapse;
width: 100%;
margin: 10px 0;
}
.markdown-content th, .markdown-content td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
.markdown-content th { background-color: #f2f2f2; }
.markdown-content tr:nth-child(even) { background-color: #f9f9f9; }
.markdown-content a { color: #1a73e8; text-decoration: none; }
.markdown-content a:hover { text-decoration: underline; }
</style>
</head>
<body>
<div id="messages"></div>
<input type="text" id="input" placeholder="输入消息...">
<button onclick="send()">发送</button>
<script>
async function send() {
const input = document.getElementById('input');
const button = document.querySelector('button');
const msg = input.value.trim();
if (!msg) return;
button.disabled = true;
button.textContent = '发送中...';
add(msg, 'user');
input.value = '';
try {
const response = await fetch('/api/chat', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({message: msg})
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
let content = '', assistantDiv;
while (true) {
const { done, value } = await reader.read();
if (done) break;
const lines = decoder.decode(value, { stream: true }).split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
try {
const data = JSON.parse(line.substring(6));
if (data.content) {
content += data.content;
if (!assistantDiv) {
assistantDiv = document.createElement('div');
assistantDiv.className = 'assistant';
document.getElementById('messages').appendChild(assistantDiv);
}
// 使用marked将Markdown转换为HTML
const htmlContent = marked.parse(content);
assistantDiv.innerHTML = '<div class="markdown-content">' + htmlContent + '</div>';
document.getElementById('messages').scrollTop = 999999;
} else if (data.error) {
if (!assistantDiv) {
assistantDiv = document.createElement('div');
assistantDiv.className = 'assistant';
document.getElementById('messages').appendChild(assistantDiv);
}
assistantDiv.textContent = '错误: ' + data.error;
}
} catch (e) {}
}
}
}
} catch (error) {
add('错误: ' + (error.message || '未知错误'), 'assistant');
} finally {
button.disabled = false;
button.textContent = '发送';
input.focus();
}
}
function add(content, type) {
const div = document.createElement('div');
div.className = type;
if (type === 'assistant') {
// 对于助手消息,应用Markdown渲染
const htmlContent = marked.parse(content);
div.innerHTML = '<div class="markdown-content">' + htmlContent + '</div>';
} else {
// 用户消息保持原样
div.textContent = content;
}
document.getElementById('messages').appendChild(div);
document.getElementById('messages').scrollTop = 999999;
}
</script>
</body>
</html>
- md表格渲染成功
- 大纲级别渲染成功
- 可以在终端
- 输出大模型的回复吗?
目前已成功实现在网页中显示Markdown格式内容,但需要进一步实现Markdown格式内容在终端和日志中的格式化输出功能。请确保大模型返回的Markdown格式内容能够在终端环境中保持适当的格式展示,同时在日志文件中正确记录格式化后的内容。需要兼顾终端显示的可读性和日志记录的完整性,确保在不同输出环境下都能清晰呈现Markdown的结构和格式特征。
from flask import Flask, request, send_file, Response
from flask_cors import CORS
from openai import OpenAI
import json
app = Flask(__name__)
CORS(app)
client = OpenAI(
base_url='https://api-inference.modelscope.cn/v1',
api_key = 'ms-81c1f87a-fa0a-4edc-a4a5-4bc7ba3cbbba'
)
@app.route('/')
def index():
return send_file('index.html')
@app.route('/api/chat', methods=['POST'])
def chat():
data = request.get_json()
user_message = data.get('message', '')
def generate():
try:
response = client.chat.completions.create(
model='Qwen/Qwen3-Next-80B-A3B-Instruct',
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": user_message}
],
stream=True
)
for chunk in response:
if chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
# 将大模型回复输出到终端
print(f"{content}",end="")
yield f"data: {json.dumps({'content': content})}\n\n"
yield f"data: {json.dumps({'done': True})}\n\n"
except Exception as e:
# 输出错误信息到控制台,方便调试
print(f"OpenAI API Error: {str(e)}")
yield f"data: {json.dumps({'error': str(e)})}\n\n"
return Response(generate(), mimetype='text/plain')
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=8081)- 我想要终端也能对于markdown文件
- 解析、转化、渲染
可以在终端里面也对md进行解析、转化、渲染吗?
- 使用了 rich这类库
- 在终端使用富文本
from flask import Flask, request, send_file, Response
from flask_cors import CORS
from openai import OpenAI
import json
# 导入rich库用于终端中渲染Markdown
try:
from rich.console import Console
from rich.markdown import Markdown
has_rich = True
console = Console()
except ImportError:
has_rich = False
print("警告: rich库未安装,终端将以原始文本形式显示Markdown内容")
app = Flask(__name__)
CORS(app)
client = OpenAI(
base_url='https://api-inference.modelscope.cn/v1',
api_key = 'ms-81c1f87a-fa0a-4edc-a4a5-4bc7ba3cbbba'
)
@app.route('/')
def index():
return send_file('index.html')
@app.route('/api/chat', methods=['POST'])
def chat():
data = request.get_json()
user_message = data.get('message', '')
def generate():
try:
response = client.chat.completions.create(
model='Qwen/Qwen3-Next-80B-A3B-Instruct',
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": user_message}
],
stream=True
)
# 用于存储完整的Markdown内容
full_content = ""
for chunk in response:
if chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
full_content += content
# 将大模型回复输出到终端
print(f"{content}", end="")
yield f"data: {json.dumps({'content': content})}\n\n"
# 当接收到完整内容后,在终端中渲染Markdown格式
if has_rich and full_content:
print("\n\n--- 终端Markdown渲染预览 ---")
console.print(Markdown(full_content))
print("--------------------------\n")
yield f"data: {json.dumps({'done': True})}\n\n"
except Exception as e:
# 输出错误信息到控制台,方便调试
print(f"OpenAI API Error: {str(e)}")
yield f"data: {json.dumps({'error': str(e)})}\n\n"
return Response(generate(), mimetype='text/plain')
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=8081)
- 大纲级别、加粗
- 如果我 恰好需要返回的是 md源文件
- 而不是 渲染好的 html代码
- 怎么办呢?
- 这次我们研究了渲染的问题
- 无论是 浏览器 还是 终端
- 都可以 按照md的文档格式 进行渲染
- 还有什么 可以玩吗?🤔
- 下次再说👋
- 本文来自 oeasy Python 系统教程。
- 想完整、扎实学 Python,
- 搜索 oeasy 即可。







