完成了LLM的适配,DIfy暂时不用
This commit is contained in:
parent
ec4cb87ed7
commit
365b8a488c
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-#
|
||||
# -------------------------------------------------------------------------------
|
||||
# Name: utils.py
|
||||
# Name: api_utils.py
|
||||
# Description:
|
||||
# Author: xaoyaoo
|
||||
# Date: 2023/12/03
|
||||
|
0
pywxdump/api/api_utils/__init__.py
Normal file
0
pywxdump/api/api_utils/__init__.py
Normal file
14
pywxdump/api/api_utils/dify.py
Normal file
14
pywxdump/api/api_utils/dify.py
Normal file
@ -0,0 +1,14 @@
|
||||
# 接入dify工作流,用来制作微信聊天记录可视化
|
||||
|
||||
class Dify(object):
|
||||
def __init__(self):
|
||||
api_key = ""
|
||||
api_base_url = ""
|
||||
|
||||
#TODO: 文件上传
|
||||
def file_upload(self):
|
||||
pass
|
||||
|
||||
#TODO: 运行工作流
|
||||
def run_workflows(self):
|
||||
pass
|
939
pywxdump/api/api_utils/html.py
Normal file
939
pywxdump/api/api_utils/html.py
Normal file
File diff suppressed because one or more lines are too long
1003
pywxdump/api/api_utils/llm.py
Normal file
1003
pywxdump/api/api_utils/llm.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -161,12 +161,12 @@ def export_json_mini_time_limit(wxid, outpath, db_config, my_wxid="我",
|
||||
start_part = start_createtime.replace(" ", "_").replace(":", "-") if start_createtime else "all"
|
||||
end_part = end_createtime.replace(" ", "_").replace(":", "-") if end_createtime else "now"
|
||||
time_suffix = f"_{start_part}_to_{end_part}"
|
||||
|
||||
save_path = os.path.join(outpath, f"{wxid}_mini{time_suffix}.json")
|
||||
filename = f"{wxid}_mini{time_suffix}.json"
|
||||
save_path = os.path.join(outpath, filename)
|
||||
with open(save_path, "w", encoding="utf-8") as f:
|
||||
json.dump(mini_data, f, ensure_ascii=False, indent=indent)
|
||||
|
||||
return True, f"导出成功: {save_path}"
|
||||
return True, f"导出成功: {save_path}", filename
|
||||
|
||||
|
||||
|
||||
|
@ -13,6 +13,7 @@ from collections import Counter
|
||||
from urllib.parse import quote, unquote
|
||||
from typing import List, Optional
|
||||
|
||||
import fastapi.requests
|
||||
from pydantic import BaseModel
|
||||
from fastapi import APIRouter, Response, Body, Query, Request
|
||||
from starlette.responses import StreamingResponse, FileResponse
|
||||
@ -21,12 +22,15 @@ import pywxdump
|
||||
from pywxdump import decrypt_merge, get_core_db
|
||||
from pywxdump.db import DBHandler
|
||||
from pywxdump.db.utils import download_file, dat2img
|
||||
from .api_utils.html import HtmlController
|
||||
|
||||
from .export import export_csv, export_json, export_html
|
||||
from .export.exportJSON import export_json_mini, export_json_mini_time_limit
|
||||
from .rjson import ReJson, RqJson
|
||||
from .utils import error9999, gc, asyncError9999, rs_loger
|
||||
|
||||
|
||||
|
||||
rs_api = APIRouter()
|
||||
|
||||
|
||||
@ -466,13 +470,49 @@ def get_export_json(wxid: str = Body(..., embed=True)):
|
||||
if not os.path.exists(outpath):
|
||||
os.makedirs(outpath)
|
||||
|
||||
code, ret = export_json_mini_time_limit(wxid, outpath, db_config, my_wxid=my_wxid,start_createtime="2025-4-29 00:00:00", end_createtime="2025-4-30 00:00:00")
|
||||
code, ret = export_json(wxid, outpath, db_config, my_wxid=my_wxid)
|
||||
if code:
|
||||
return ReJson(0, ret)
|
||||
else:
|
||||
return ReJson(2001, body=ret)
|
||||
|
||||
|
||||
class ExportJsonMiniRequest(BaseModel):
|
||||
start_createtime: str
|
||||
end_createtime: str
|
||||
|
||||
@rs_api.api_route('/export_json_mini_select_time', methods=["GET", 'POST'])
|
||||
def get_export_json(wxid: str = Body(..., embed=True),time: ExportJsonMiniRequest = Body(..., embed=True)):
|
||||
"""
|
||||
导出json,选择时间,迷你版本
|
||||
:return:
|
||||
"""
|
||||
my_wxid = gc.get_conf(gc.at, "last")
|
||||
if not my_wxid: return ReJson(1001, body="my_wxid is required")
|
||||
db_config = gc.get_conf(my_wxid, "db_config")
|
||||
|
||||
if not wxid:
|
||||
return ReJson(1002, body=f"username is required: {wxid}")
|
||||
|
||||
outpath = os.path.join(gc.work_path, "export", my_wxid, "json", wxid)
|
||||
if not os.path.exists(outpath):
|
||||
os.makedirs(outpath)
|
||||
|
||||
start_createtime = time.start_createtime # 格式为 "2025-05-01 18:06:00"
|
||||
end_createtime = time.end_createtime
|
||||
|
||||
code, ret,filename = export_json_mini_time_limit(wxid, outpath, db_config, my_wxid=my_wxid,start_createtime=start_createtime, end_createtime=end_createtime)
|
||||
if code:
|
||||
# 成功创建,执行生成可视化页面的逻辑
|
||||
# with open(os.path.join(gc.work_path, "export", my_wxid, "html", wxid, filename), "w", encoding="utf-8") as f:
|
||||
# f.write(
|
||||
# #现在是fake
|
||||
# HtmlController().create_html(json_data=None)
|
||||
# )
|
||||
return ReJson(0, ret)
|
||||
|
||||
else:
|
||||
return ReJson(2001, body=ret)
|
||||
|
||||
|
||||
|
||||
@ -671,4 +711,61 @@ def get_readme():
|
||||
else:
|
||||
return ReJson(2001, body="status_code is not 200")
|
||||
|
||||
|
||||
class DifyApiModel(BaseModel):
|
||||
api_key:str
|
||||
base_url:str
|
||||
|
||||
|
||||
@rs_api.api_route('/dify_setting', methods=["GET", 'POST'])
|
||||
@error9999
|
||||
def dify_setting(request: Request = None, dify: DifyApiModel = Body(None, embed=True)):
|
||||
"""
|
||||
dify设置
|
||||
"""
|
||||
|
||||
if request.method == "GET":
|
||||
my_wxid = gc.get_conf(gc.at, "last")
|
||||
if not my_wxid: return ReJson(1001, body="my_wxid is required")
|
||||
gc.get_conf(my_wxid, "dify_setting")
|
||||
|
||||
return ReJson(0, body=gc.get_conf(my_wxid, "dify_setting"))
|
||||
|
||||
elif request.method == "POST":
|
||||
my_wxid = gc.get_conf(gc.at, "last")
|
||||
if not my_wxid: return ReJson(1001, body="my_wxid is required")
|
||||
if not dify.api_key and not dify.base_url:
|
||||
return ReJson(1002, body="dify_setting is required")
|
||||
|
||||
gc.set_conf(my_wxid, "dify_setting", {"API_KEY": dify.api_key, "BASE_URL": dify.base_url})
|
||||
return ReJson(0, body=gc.get_conf(my_wxid, "dify_setting"))
|
||||
return ReJson(2001, body="status_code is not 200")
|
||||
|
||||
class DeepSeekApiModel(BaseModel):
|
||||
api_key:str
|
||||
|
||||
|
||||
@rs_api.api_route('/deepseek_setting', methods=["GET", 'POST'])
|
||||
@error9999
|
||||
def deepseek_setting(request: Request = None, deepseek: DeepSeekApiModel = Body(None, embed=True)):
|
||||
"""
|
||||
deepseek设置
|
||||
"""
|
||||
if request.method == "GET":
|
||||
my_wxid = gc.get_conf(gc.at, "last")
|
||||
if not my_wxid: return ReJson(1001, body="my_wxid is required")
|
||||
gc.get_conf(my_wxid, "deepseek_setting")
|
||||
|
||||
return ReJson(0, body=gc.get_conf(my_wxid, "deepseek_setting"))
|
||||
|
||||
elif request.method == "POST":
|
||||
my_wxid = gc.get_conf(gc.at, "last")
|
||||
if not my_wxid: return ReJson(1001, body="my_wxid is required")
|
||||
if not deepseek or not deepseek.api_key:
|
||||
return ReJson(1002, body="deepseek_setting is required")
|
||||
|
||||
gc.set_conf(my_wxid, "deepseek_setting", {"API_KEY": deepseek.api_key})
|
||||
return ReJson(0, body=gc.get_conf(my_wxid, "deepseek_setting"))
|
||||
return ReJson(2001, body="status_code is not 200")
|
||||
|
||||
# END 关于、帮助、设置 ***************************************************************************************************
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-#
|
||||
# -------------------------------------------------------------------------------
|
||||
# Name: utils.py
|
||||
# Name: api_utils.py
|
||||
# Description:
|
||||
# Author: xaoyaoo
|
||||
# Date: 2024/01/16
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-#
|
||||
# -------------------------------------------------------------------------------
|
||||
# Name: __init__.py.py
|
||||
# Description: db.utils
|
||||
# Description: db.api_utils
|
||||
# Author: xaoyaoo
|
||||
# Date: 2024/07/23
|
||||
# -------------------------------------------------------------------------------
|
||||
|
@ -35,6 +35,20 @@
|
||||
|
||||
--section-gap: 160px;
|
||||
}
|
||||
/* 可视化页面的css*/
|
||||
:root {
|
||||
--bg-ui-s-primary: #0f0e17;
|
||||
--bg-ui-s-secondary: #1a1925;
|
||||
--bg-ui-s-tertiary: #252336;
|
||||
--text-ui-s-primary: #fffffe;
|
||||
--text-ui-s-secondary: #a7a9be;
|
||||
--accent-ui-s-primary: #ff8906;
|
||||
--accent-ui-s-secondary: #f25f4c;
|
||||
--accent-ui-s-tertiary: #e53170;
|
||||
--accent-ui-s-blue: #3da9fc;
|
||||
--accent-ui-s-purple: #7209b7;
|
||||
--accent-ui-s-cyan: #00b4d8;
|
||||
}
|
||||
|
||||
/* @media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
|
@ -11,6 +11,7 @@ import ExportJSON from "@/components/chatBackup/ExportJSON.vue";
|
||||
import ExportHTML from "@/components/chatBackup/ExportHTML.vue";
|
||||
import ExportPDF from "@/components/chatBackup/ExportPDF.vue";
|
||||
import ExportDOCX from "@/components/chatBackup/ExportDOCX.vue";
|
||||
import ExportJSONMini from './ExportJSONMini.vue';
|
||||
|
||||
const props = defineProps({
|
||||
wxid: {
|
||||
@ -44,6 +45,10 @@ const setting = {
|
||||
brief: 'json',
|
||||
detail: "只包含文本,可用于数据分析,情感分析等方面。",
|
||||
},
|
||||
'json-mini': {
|
||||
brief: 'json-mini',
|
||||
detail: "只包含文本,只有最小化的json格式。支持选择时间,注意不要选择太多时间,会导致导出数据过大影响AI分析。",
|
||||
},
|
||||
'html': {
|
||||
brief: 'html-测试中',
|
||||
detail: "主要用于浏览器可视化查看。",
|
||||
@ -91,6 +96,7 @@ const setting = {
|
||||
<ExportDEDB v-if="exportType=='dedb'" :wxid="props.wxid"/>
|
||||
<ExportCSV v-if="exportType=='csv'" :wxid="props.wxid"/>
|
||||
<ExportJSON v-if="exportType=='json'" :wxid="props.wxid"/>
|
||||
<ExportJSONMini v-if="exportType=='json-mini'" :wxid="props.wxid"/>
|
||||
<ExportHTML v-if="exportType=='html'" :wxid="props.wxid"/>
|
||||
<ExportPDF v-if="exportType=='pdf'" :wxid="props.wxid"/>
|
||||
<ExportDOCX v-if="exportType=='docx'" :wxid="props.wxid"/>
|
||||
|
65
pywxdump/ui/src/components/chatBackup/ExportJSONMini.vue
Normal file
65
pywxdump/ui/src/components/chatBackup/ExportJSONMini.vue
Normal file
@ -0,0 +1,65 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {defineProps, ref, watch} from "vue";
|
||||
import http from "@/utils/axios.js";
|
||||
import DateTimeSelect from "@/components/utils/DateTimeSelect.vue";
|
||||
|
||||
const props = defineProps({
|
||||
wxid: {
|
||||
type: String,
|
||||
required: true,
|
||||
}
|
||||
});
|
||||
watch(() => props.wxid, (newVal: string, oldVal: String) => {
|
||||
console.log(newVal);
|
||||
});
|
||||
// 上述代码是监听props.wxid的变化,当props.wxid变化时,会打印新值。
|
||||
|
||||
const datetime = ref([]);
|
||||
const Result = ref("");
|
||||
|
||||
const requestExport = async () => {
|
||||
Result.value = "正在处理中...";
|
||||
try {
|
||||
Result.value = await http.post('/api/rs/export_json_mini_select_time', {
|
||||
'wxid': props.wxid,
|
||||
// 'datetime': datetime.value,
|
||||
"time":{
|
||||
"start_time":datetime.value[0],
|
||||
"end_time":datetime.value[1]
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching data msg_count:', error);
|
||||
Result.value = "请求失败\n" + error;
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// 处理时间选择器的数据
|
||||
const handDatetimeChildData = (val: any) => {
|
||||
datetime.value = val;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<!-- <div>-->
|
||||
<!-- <strong>时间(默认全部):</strong>-->
|
||||
<!-- <DateTimeSelect @datetime="handDatetimeChildData"/>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<div style="position: relative;">
|
||||
<el-button type="primary" @click="requestExport()">导出</el-button>
|
||||
</div>
|
||||
<el-divider/>
|
||||
<!-- 结果显示 -->
|
||||
<el-input type="textarea" :rows="6" readonly placeholder="" v-model="Result"
|
||||
style="width: 100%;"></el-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -23,6 +23,11 @@ const router = createRouter({
|
||||
name: 'chat',
|
||||
component: () => import((`@/views/ChatView.vue`))
|
||||
},
|
||||
{
|
||||
path: '/chat2ui',
|
||||
name: 'chat2ui',
|
||||
component: () => import((`@/views/Chat2UiView.vue`))
|
||||
},
|
||||
{
|
||||
path: '/contacts',
|
||||
name: 'contacts',
|
||||
|
1091
pywxdump/ui/src/views/Chat2UiView.vue
Normal file
1091
pywxdump/ui/src/views/Chat2UiView.vue
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-#
|
||||
# -------------------------------------------------------------------------------
|
||||
# Name: utils.py
|
||||
# Name: api_utils.py
|
||||
# Description:
|
||||
# Author: xaoyaoo
|
||||
# Date: 2023/12/25
|
||||
|
8
setup.py
8
setup.py
@ -45,17 +45,17 @@ setup(
|
||||
license='MIT',
|
||||
|
||||
# packages=find_packages(exclude=[]),
|
||||
packages=['pywxdump', 'pywxdump.ui', 'pywxdump.wx_core', 'pywxdump.wx_core.utils', 'pywxdump.analyzer',
|
||||
'pywxdump.api', 'pywxdump.api.export', 'pywxdump.db', 'pywxdump.db.utils'],
|
||||
packages=['pywxdump', 'pywxdump.ui', 'pywxdump.wx_core', 'pywxdump.wx_core.api_utils', 'pywxdump.analyzer',
|
||||
'pywxdump.api', 'pywxdump.api.export', 'pywxdump.db', 'pywxdump.db.api_utils'],
|
||||
package_dir={'pywxdump': 'pywxdump',
|
||||
'pywxdump.wx_core': 'pywxdump/wx_core',
|
||||
'pywxdump.wx_core.utils': 'pywxdump/wx_core/utils',
|
||||
'pywxdump.wx_core.api_utils': 'pywxdump/wx_core/api_utils',
|
||||
'pywxdump.analyzer': 'pywxdump/analyzer',
|
||||
'pywxdump.ui': 'pywxdump/ui',
|
||||
'pywxdump.api': 'pywxdump/api',
|
||||
'pywxdump.api.export': 'pywxdump/api/export',
|
||||
'pywxdump.db': 'pywxdump/db',
|
||||
'pywxdump.db.utils': 'pywxdump/db/utils'
|
||||
'pywxdump.db.api_utils': 'pywxdump/db/api_utils'
|
||||
},
|
||||
# include_package_data=True,
|
||||
package_data={
|
||||
|
5
temp.md
Normal file
5
temp.md
Normal file
@ -0,0 +1,5 @@
|
||||
- 导出json,可选时间
|
||||
- 单独导航栏 Ai可视化
|
||||
- 可以进行可视化的文件列表
|
||||
- 已经可视化的列表
|
||||
- 查看
|
@ -153,7 +153,7 @@ if package_path:
|
||||
hidden_imports = f.read().splitlines()
|
||||
hidden_imports = [i.replace('-', '_').split("=")[0].split("~")[0] for i in hidden_imports if
|
||||
i and i not in ["setuptools", "wheel"]] # 去掉setuptools、wheel
|
||||
hidden_imports += ["pywxdump", "pywxdump.db", "pywxdump.db.__init__.utils"]
|
||||
hidden_imports += ["pywxdump", "pywxdump.db", "pywxdump.db.__init__.api_utils"]
|
||||
|
||||
# 获取 ui 文件夹下的所有文件 用于打包
|
||||
root_path = os.path.join(package_path, 'pywxdump')
|
||||
|
Loading…
Reference in New Issue
Block a user