Skip to content

Commit

Permalink
mindmap update
Browse files Browse the repository at this point in the history
  • Loading branch information
jamiesun committed Nov 23, 2023
1 parent 45c820d commit e50420b
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 14 deletions.
66 changes: 55 additions & 11 deletions common.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,52 @@ def optimize_text_by_openai(content):
return response.choices[0].message.content


def create_mindma_data_by_openai(content):
"""通过LLM 修正优化文本"""
sysmsg = """
You are a mind mapping expert who analyzes user input, organizes the responses into a mind map structure, and replies in json format.
- You need to analyze the user's question and break it down into sub-questions.
- You need to organize the answers to the questions into a mind map structure with no more than 4 levels of nodes.
- The first three levels of the mind map should be accompanied by an emoji that matches the semantics of the node, make sure the emoji are encoded in UTF-8 format.
- The language of the mind map's nodes is determined by the user's input, e.g. Chinese if the user inputs Chinese, English if the user inputs English, or whichever language is explicitly requested by the user.- You need to reply to the user with the structure of the mind map in json format.
- The total number of nodes to be generated should not exceed 60, so please strictly enforce this rule.
The json format template:
{
"title": "root node",
"structure": {
"root node": ["node1", "node2"],
"node1": ["node1-1", "node1-2"],
"node2": ["node2-1", "node2-2"],
}
}
"""
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4-1106-preview",
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": sysmsg},
{"role": "user", "content": content},
]
)
return response.choices[0].message.content


def generate_light_color(pcolor: str):
"""生成比给定颜色浅一半的颜色"""
"""生成比给定颜色更浅的颜色"""
r, g, b = int(pcolor[1:3], 16), int(pcolor[3:5], 16), int(pcolor[5:7], 16)
r = int(r + (255 - r) / 2)
g = int(g + (255 - g) / 2)
b = int(b + (255 - b) / 2)

# 增加每个颜色分量,使之更接近255
# 比如,可以使用原始值与255之间的75%点而不是50%
r = int(r + 0.65 * (255 - r))
g = int(g + 0.65 * (255 - g))
b = int(b + 0.65 * (255 - b))

return '#%02x%02x%02x' % (r, g, b)


Expand All @@ -92,22 +132,26 @@ def build_mind_map(graph, node, parent, structure, level=0, parent_color=None):
# 根据层级设置样式
if level == 0: # 根节点
node_color = generate_random_dark_color()
graph.node(node, style='filled', color=node_color, fontsize="21", fontname='WenQuanYi Micro Hei', fontcolor='white',
shape='tripleoctagon',peripheries="2", label=node)
graph.node(node, style='filled', color=node_color, fontsize="21", fontname='WenQuanYi Micro Hei',
fontcolor='white',
shape='tripleoctagon', peripheries="2", label=node)
elif level == 1: # 第二层节点
node_color = generate_random_dark_color()
graph.node(node, style='filled', color=node_color, fontsize="18", fontname='WenQuanYi Micro Hei', fontcolor='white',
shape='hexagon',peripheries="2", label=node)
graph.node(node, style='filled', color=node_color, fontsize="18", fontname='WenQuanYi Micro Hei',
fontcolor='white',
shape='hexagon', peripheries="2", label=node)
elif level == 2: # 第三层节点
node_color = generate_light_color(parent_color)
graph.node(node, style='filled', color=node_color, fontsize="16", shape='note', fontname='WenQuanYi Micro Hei', label=node)
graph.node(node, style='filled', color=node_color, fontsize="16", shape='note', fontname='WenQuanYi Micro Hei',
label=node)
else: # 其他层级
node_color = generate_light_color(parent_color)
graph.node(node, style='solid', color=node_color,fontsize="14", shape='egg', fontname='WenQuanYi Micro Hei', label=node)
graph.node(node, style='solid', color=node_color, fontsize="14", shape='egg', fontname='WenQuanYi Micro Hei',
label=node)

# 连接节点
if parent:
graph.edge(parent, node, penwidth='2.0', color=parent_color if level == 1 else node_color)
graph.edge(parent, node, penwidth='2.0', color=parent_color if level == 1 else node_color)

# 递归构建子节点
for child in structure.get(node, []):
Expand Down
35 changes: 32 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import re
import uuid
from typing import Dict, List
Expand All @@ -6,7 +7,7 @@
import logging
import os
import shutil
from fastapi import FastAPI, Depends, HTTPException
from fastapi import FastAPI, Depends, HTTPException, Query
from fastapi.responses import FileResponse
from fastapi.responses import HTMLResponse
from fastapi.security import APIKeyHeader
Expand All @@ -29,6 +30,7 @@
validate_api_key,
preprocess_image,
build_mind_map,
create_mindma_data_by_openai,
optimize_text_by_openai)
from qdrant_index import qdrant

Expand Down Expand Up @@ -161,6 +163,7 @@ async def download_file(filename: str):
# 返回文件响应
return FileResponse(file_path)


@app.get("/privacy", response_class=HTMLResponse)
async def root():
return """
Expand Down Expand Up @@ -270,13 +273,13 @@ async def create_image_ocr(file: UploadFile = File(...), td: TokenData = Depends


@app.post("/knowledge/mindmap/create", summary="Create a knowledge base mindmap from params",
description="Generating mind maps from given structured data")
description="Generating mind maps from given structured data", include_in_schema=False)
async def create_mindmap(item: MindmapItem, td: bool = Depends(verify_api_key)):
try:
log.info(f"create_mindmap: {item}")
# 创建并构建思维导图
graph = Digraph(comment=item.title, engine="sfdp")
graph.attr(splines='curved')
graph.attr(splines='curved', overlap='false', margin='0.4') # 设置图的大小为A4纸尺寸
build_mind_map(graph, item.title, None, structure=item.structure)
fileuuid = str(uuid.uuid4())
graph.render(os.path.join(DATA_DIR, fileuuid), format='png', cleanup=True)
Expand All @@ -289,6 +292,32 @@ async def create_mindmap(item: MindmapItem, td: bool = Depends(verify_api_key)):
raise HTTPException(status_code=500, detail=str(e))


@app.get("/knowledge/mindmap/generate", summary="Create a knowledge base mindmap from query content",
description="Generating mind maps from given content")
async def generate_mindmap(content: str = Query(...), td: bool = Depends(verify_api_key)):
try:
log.info(f"generate_mindmap params: {content}")
airesp = create_mindma_data_by_openai(content)
log.info(f"generate_mindmap result: {airesp}")
# 创建并构建思维导图
# 将 JSON 字符串转换为 Python 字典
data = json.loads(airesp)
# 使用 model_validate 方法创建 MindmapItem 实例
item = MindmapItem.model_validate(data)
graph = Digraph(comment=item.title, engine="sfdp")
graph.attr(splines='curved')
build_mind_map(graph, item.title, None, structure=item.structure)
fileuuid = str(uuid.uuid4())
graph.render(os.path.join(DATA_DIR, fileuuid), format='png', cleanup=True)
server_url = os.environ.get("GPTS_API_SERVER")
if server_url.endswith("/"):
server_url = server_url[:-1]
return RestResult(code=0, msg="success", result=dict(data=f"{server_url}/assets/{fileuuid}.png"))
except Exception as e:
log.error(f"generate_mindmap error: {e}")
raise HTTPException(status_code=500, detail=str(e))


if __name__ == "__main__":
import uvicorn

Expand Down
5 changes: 5 additions & 0 deletions tests/test.http
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,12 @@ Authorization: Bearer a99e05501a0405531caf783eef419b56a5a32f57b64ae3b89587b3a0d5
}
}

###

GET http://127.0.0.1:8700/knowledge/mindmap/generate?content=根据Python知识创建一个思维导图,最多60节点
Accept: application/json
Content-Type: application/json
Authorization: Bearer a99e05501a0405531caf783eef419b56a5a32f57b64ae3b89587b3a0d5202ee167d80d727a1b8181


###
Expand Down
61 changes: 61 additions & 0 deletions tools/generate_mindmap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import json
import os
import uuid
from graphviz import Digraph
from common import create_mindma_data_by_openai, build_mind_map
from main import MindmapItem


def generate_mindmap():
try:
airesp = create_mindma_data_by_openai("根据微积分基础整理一个学习计划思维导图")
# 创建并构建思维导图
data = json.loads(airesp)
item = MindmapItem.model_validate(data)

graph = Digraph(comment=item.title, engine="Sfdp")
graph.attr(splines='curved', overlap='false', sep='2',mode="major", margin='0.4') # 设置图的大小为A4纸尺寸

build_mind_map(graph, item.title, None, structure=item.structure)

fileuuid = str(uuid.uuid4())
output_path = os.path.join("/tmp", fileuuid)
graph.render(output_path, format='png', cleanup=True)
graph.view()

except Exception as e:
import traceback
traceback.print_exc()


if __name__ == '__main__':
content = """{
"title": "对数基础知识",
"structure": {
"对数基础知识": ["📚 定义", "🔍 属性", "🔢 计算规则", "📈 应用"],
"📚 定义": ["🎯 对数的概念", "🔑 对数的底数", "✅ 对数函数"],
"🔍 属性": ["🌀 唯一性", "☀️ 正值性", "🌐 定义域和值域"],
"🔢 计算规则": ["➕ 乘法的对数法则", "➖ 除法的对数法则", "✖️ 幂的对数法则", "➗ 根的对数法则", "🔄 底数变换法则"],
"📈 应用": ["📉 指数方程", "💹 指数衰减与增长", "🌏 科学计数法", "📊 数据分析"],
"🎯 对数的概念": [],
"🔑 对数的底数": [],
"✅ 对数函数": [],
"🌀 唯一性": [],
"☀️ 正值性": [],
"🌐 定义域和值域": [],
"➕ 乘法的对数法则": [],
"➖ 除法的对数法则": [],
"✖️ 幂的对数法则": [],
"➗ 根的对数法则": [],
"🔄 底数变换法则": [],
"📉 指数方程": [],
"💹 指数衰减与增长": [],
"🌏 科学计数法": [],
"📊 数据分析": []
}
}"""
generate_mindmap()

0 comments on commit e50420b

Please sign in to comment.