mirror of
https://github.com/idootop/mi-gpt.git
synced 2025-04-21 01:22:24 +00:00
feat: add Logger
This commit is contained in:
parent
7ad50322fe
commit
2dc65da0fe
3
TODO.md
3
TODO.md
|
@ -2,3 +2,6 @@
|
||||||
- ✅ Stream response
|
- ✅ Stream response
|
||||||
- ✅ Deactivate Xiaoai
|
- ✅ Deactivate Xiaoai
|
||||||
- ✅ Update long/short memories
|
- ✅ Update long/short memories
|
||||||
|
- ✅ Logger
|
||||||
|
- Docker
|
||||||
|
- Npm export
|
|
@ -4,6 +4,7 @@ import { readJSON, writeJSON } from "../../utils/io";
|
||||||
import { DeepPartial } from "../../utils/type";
|
import { DeepPartial } from "../../utils/type";
|
||||||
import { RoomCRUD, getRoomID } from "../db/room";
|
import { RoomCRUD, getRoomID } from "../db/room";
|
||||||
import { UserCRUD } from "../db/user";
|
import { UserCRUD } from "../db/user";
|
||||||
|
import { Logger } from "../../utils/log";
|
||||||
|
|
||||||
const kDefaultMaster = {
|
const kDefaultMaster = {
|
||||||
name: "用户",
|
name: "用户",
|
||||||
|
@ -27,6 +28,7 @@ export interface IBotConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BotConfig {
|
class _BotConfig {
|
||||||
|
private _logger = Logger.create({ tag: "BotConfig" });
|
||||||
private botIndex?: IBotIndex;
|
private botIndex?: IBotIndex;
|
||||||
|
|
||||||
private _index_path = ".bot.json";
|
private _index_path = ".bot.json";
|
||||||
|
@ -44,12 +46,12 @@ class _BotConfig {
|
||||||
// create db records
|
// create db records
|
||||||
const bot = await UserCRUD.addOrUpdate(kDefaultBot);
|
const bot = await UserCRUD.addOrUpdate(kDefaultBot);
|
||||||
if (!bot) {
|
if (!bot) {
|
||||||
console.error("❌ create bot failed");
|
this._logger.error("create bot failed");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const master = await UserCRUD.addOrUpdate(kDefaultMaster);
|
const master = await UserCRUD.addOrUpdate(kDefaultMaster);
|
||||||
if (!master) {
|
if (!master) {
|
||||||
console.error("❌ create master failed");
|
this._logger.error("create master failed");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const defaultRoomName = `${master.name}和${bot.name}的私聊`;
|
const defaultRoomName = `${master.name}和${bot.name}的私聊`;
|
||||||
|
@ -59,7 +61,7 @@ class _BotConfig {
|
||||||
description: defaultRoomName,
|
description: defaultRoomName,
|
||||||
});
|
});
|
||||||
if (!room) {
|
if (!room) {
|
||||||
console.error("❌ create room failed");
|
this._logger.error("create room failed");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
this.botIndex = {
|
this.botIndex = {
|
||||||
|
@ -70,17 +72,17 @@ class _BotConfig {
|
||||||
}
|
}
|
||||||
const bot = await UserCRUD.get(this.botIndex!.botId);
|
const bot = await UserCRUD.get(this.botIndex!.botId);
|
||||||
if (!bot) {
|
if (!bot) {
|
||||||
console.error("❌ find bot failed");
|
this._logger.error("find bot failed");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const master = await UserCRUD.get(this.botIndex!.masterId);
|
const master = await UserCRUD.get(this.botIndex!.masterId);
|
||||||
if (!master) {
|
if (!master) {
|
||||||
console.error("❌ find master failed");
|
this._logger.error("find master failed");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const room = await RoomCRUD.get(getRoomID([bot, master]));
|
const room = await RoomCRUD.get(getRoomID([bot, master]));
|
||||||
if (!room) {
|
if (!room) {
|
||||||
console.error("❌ find room failed");
|
this._logger.error("find room failed");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return { bot, master, room };
|
return { bot, master, room };
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
import { PrismaClient } from "@prisma/client";
|
import { PrismaClient } from "@prisma/client";
|
||||||
|
import { Logger } from "../../utils/log";
|
||||||
|
|
||||||
export const k404 = -404;
|
export const k404 = -404;
|
||||||
|
|
||||||
export const kPrisma = new PrismaClient();
|
export const kPrisma = new PrismaClient();
|
||||||
|
|
||||||
|
export const kDBLogger = Logger.create({ tag: "DB" });
|
||||||
export function runWithDB(main: () => Promise<void>) {
|
export function runWithDB(main: () => Promise<void>) {
|
||||||
main()
|
main()
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
await kPrisma.$disconnect();
|
await kPrisma.$disconnect();
|
||||||
})
|
})
|
||||||
.catch(async (e) => {
|
.catch(async (e) => {
|
||||||
console.error(e);
|
kDBLogger.error(e);
|
||||||
await kPrisma.$disconnect();
|
await kPrisma.$disconnect();
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { LongTermMemory, Room, User } from "@prisma/client";
|
import { LongTermMemory, Room, User } from "@prisma/client";
|
||||||
import { removeEmpty } from "../../utils/base";
|
import { removeEmpty } from "../../utils/base";
|
||||||
import { getSkipWithCursor, k404, kPrisma } from "./index";
|
import { getSkipWithCursor, k404, kDBLogger, kPrisma } from "./index";
|
||||||
|
|
||||||
class _LongTermMemoryCRUD {
|
class _LongTermMemoryCRUD {
|
||||||
async count(options?: { cursorId?: number; room?: Room; owner?: User }) {
|
async count(options?: { cursorId?: number; room?: Room; owner?: User }) {
|
||||||
|
@ -14,14 +14,14 @@ class _LongTermMemoryCRUD {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ get longTermMemory count failed", e);
|
kDBLogger.error("get longTermMemory count failed", e);
|
||||||
return -1;
|
return -1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(id: number) {
|
async get(id: number) {
|
||||||
return kPrisma.longTermMemory.findFirst({ where: { id } }).catch((e) => {
|
return kPrisma.longTermMemory.findFirst({ where: { id } }).catch((e) => {
|
||||||
console.error("❌ get long term memory failed", id, e);
|
kDBLogger.error("get long term memory failed", id, e);
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ class _LongTermMemoryCRUD {
|
||||||
...getSkipWithCursor(skip, cursorId),
|
...getSkipWithCursor(skip, cursorId),
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ get long term memories failed", options, e);
|
kDBLogger.error("get long term memories failed", options, e);
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
return order === "desc" ? memories.reverse() : memories;
|
return order === "desc" ? memories.reverse() : memories;
|
||||||
|
@ -82,7 +82,7 @@ class _LongTermMemoryCRUD {
|
||||||
update: data,
|
update: data,
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ add longTermMemory to db failed", longTermMemory, e);
|
kDBLogger.error("add longTermMemory to db failed", longTermMemory, e);
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Room, ShortTermMemory, User } from "@prisma/client";
|
import { Room, ShortTermMemory, User } from "@prisma/client";
|
||||||
import { removeEmpty } from "../../utils/base";
|
import { removeEmpty } from "../../utils/base";
|
||||||
import { getSkipWithCursor, k404, kPrisma } from "./index";
|
import { getSkipWithCursor, k404, kDBLogger, kPrisma } from "./index";
|
||||||
|
|
||||||
class _ShortTermMemoryCRUD {
|
class _ShortTermMemoryCRUD {
|
||||||
async count(options?: { cursorId?: number; room?: Room; owner?: User }) {
|
async count(options?: { cursorId?: number; room?: Room; owner?: User }) {
|
||||||
|
@ -14,14 +14,14 @@ class _ShortTermMemoryCRUD {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ get shortTermMemory count failed", e);
|
kDBLogger.error("get shortTermMemory count failed", e);
|
||||||
return -1;
|
return -1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(id: number) {
|
async get(id: number) {
|
||||||
return kPrisma.shortTermMemory.findFirst({ where: { id } }).catch((e) => {
|
return kPrisma.shortTermMemory.findFirst({ where: { id } }).catch((e) => {
|
||||||
console.error("❌ get short term memory failed", id, e);
|
kDBLogger.error("get short term memory failed", id, e);
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ class _ShortTermMemoryCRUD {
|
||||||
...getSkipWithCursor(skip, cursorId),
|
...getSkipWithCursor(skip, cursorId),
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ get short term memories failed", options, e);
|
kDBLogger.error("get short term memories failed", options, e);
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
return order === "desc" ? memories.reverse() : memories;
|
return order === "desc" ? memories.reverse() : memories;
|
||||||
|
@ -82,11 +82,7 @@ class _ShortTermMemoryCRUD {
|
||||||
update: data,
|
update: data,
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error(
|
kDBLogger.error("add shortTermMemory to db failed", shortTermMemory, e);
|
||||||
"❌ add shortTermMemory to db failed",
|
|
||||||
shortTermMemory,
|
|
||||||
e
|
|
||||||
);
|
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Memory, Prisma, Room, User } from "@prisma/client";
|
import { Memory, Prisma, Room, User } from "@prisma/client";
|
||||||
import { getSkipWithCursor, k404, kPrisma } from "./index";
|
|
||||||
import { removeEmpty } from "../../utils/base";
|
import { removeEmpty } from "../../utils/base";
|
||||||
|
import { getSkipWithCursor, k404, kDBLogger, kPrisma } from "./index";
|
||||||
|
|
||||||
class _MemoryCRUD {
|
class _MemoryCRUD {
|
||||||
async count(options?: { cursorId?: number; room?: Room; owner?: User }) {
|
async count(options?: { cursorId?: number; room?: Room; owner?: User }) {
|
||||||
|
@ -14,7 +14,7 @@ class _MemoryCRUD {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ get memory count failed", e);
|
kDBLogger.error("get memory count failed", e);
|
||||||
return -1;
|
return -1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ class _MemoryCRUD {
|
||||||
},
|
},
|
||||||
} = options ?? {};
|
} = options ?? {};
|
||||||
return kPrisma.memory.findFirst({ where: { id }, include }).catch((e) => {
|
return kPrisma.memory.findFirst({ where: { id }, include }).catch((e) => {
|
||||||
console.error("❌ get memory failed", id, e);
|
kDBLogger.error("get memory failed", id, e);
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ class _MemoryCRUD {
|
||||||
...getSkipWithCursor(skip, cursorId),
|
...getSkipWithCursor(skip, cursorId),
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ get memories failed", options, e);
|
kDBLogger.error("get memories failed", options, e);
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
return order === "desc" ? memories.reverse() : memories;
|
return order === "desc" ? memories.reverse() : memories;
|
||||||
|
@ -98,7 +98,7 @@ class _MemoryCRUD {
|
||||||
update: data,
|
update: data,
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ add memory to db failed", memory, e);
|
kDBLogger.error("add memory to db failed", memory, e);
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Message, Prisma, Room, User } from "@prisma/client";
|
import { Message, Prisma, Room, User } from "@prisma/client";
|
||||||
import { removeEmpty } from "../../utils/base";
|
import { removeEmpty } from "../../utils/base";
|
||||||
import { getSkipWithCursor, k404, kPrisma } from "./index";
|
import { getSkipWithCursor, k404, kDBLogger, kPrisma } from "./index";
|
||||||
|
|
||||||
class _MessageCRUD {
|
class _MessageCRUD {
|
||||||
async count(options?: { cursorId?: number; room?: Room; sender?: User }) {
|
async count(options?: { cursorId?: number; room?: Room; sender?: User }) {
|
||||||
|
@ -14,7 +14,7 @@ class _MessageCRUD {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ get message count failed", e);
|
kDBLogger.error("get message count failed", e);
|
||||||
return -1;
|
return -1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ class _MessageCRUD {
|
||||||
) {
|
) {
|
||||||
const { include = { sender: true } } = options ?? {};
|
const { include = { sender: true } } = options ?? {};
|
||||||
return kPrisma.message.findFirst({ where: { id }, include }).catch((e) => {
|
return kPrisma.message.findFirst({ where: { id }, include }).catch((e) => {
|
||||||
console.error("❌ get message failed", id, e);
|
kDBLogger.error("get message failed", id, e);
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ class _MessageCRUD {
|
||||||
...getSkipWithCursor(skip, cursorId),
|
...getSkipWithCursor(skip, cursorId),
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ get messages failed", options, e);
|
kDBLogger.error("get messages failed", options, e);
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
return order === "desc" ? messages.reverse() : messages;
|
return order === "desc" ? messages.reverse() : messages;
|
||||||
|
@ -89,7 +89,7 @@ class _MessageCRUD {
|
||||||
update: data,
|
update: data,
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ add message to db failed", message, e);
|
kDBLogger.error("add message to db failed", message, e);
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Prisma, Room, User } from "@prisma/client";
|
import { Prisma, Room, User } from "@prisma/client";
|
||||||
import { k404, kPrisma, getSkipWithCursor } from "./index";
|
import { k404, kPrisma, getSkipWithCursor, kDBLogger } from "./index";
|
||||||
|
|
||||||
export function getRoomID(users: User[]) {
|
export function getRoomID(users: User[]) {
|
||||||
return users
|
return users
|
||||||
|
@ -22,7 +22,7 @@ class _RoomCRUD {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ get room count failed", e);
|
kDBLogger.error("get room count failed", e);
|
||||||
return -1;
|
return -1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ class _RoomCRUD {
|
||||||
) {
|
) {
|
||||||
const { include = { members: true } } = options ?? {};
|
const { include = { members: true } } = options ?? {};
|
||||||
return kPrisma.room.findFirst({ where: { id } }).catch((e) => {
|
return kPrisma.room.findFirst({ where: { id } }).catch((e) => {
|
||||||
console.error("❌ get room failed", id, e);
|
kDBLogger.error("get room failed", id, e);
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ class _RoomCRUD {
|
||||||
...getSkipWithCursor(skip, cursorId),
|
...getSkipWithCursor(skip, cursorId),
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ get rooms failed", options, e);
|
kDBLogger.error("get rooms failed", options, e);
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
return order === "desc" ? rooms.reverse() : rooms;
|
return order === "desc" ? rooms.reverse() : rooms;
|
||||||
|
@ -89,7 +89,7 @@ class _RoomCRUD {
|
||||||
update: room,
|
update: room,
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ add room to db failed", room, e);
|
kDBLogger.error("add room to db failed", room, e);
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Prisma, User } from "@prisma/client";
|
import { Prisma, User } from "@prisma/client";
|
||||||
import { getSkipWithCursor, k404, kPrisma } from "./index";
|
import { getSkipWithCursor, k404, kDBLogger, kPrisma } from "./index";
|
||||||
|
|
||||||
class _UserCRUD {
|
class _UserCRUD {
|
||||||
async count() {
|
async count() {
|
||||||
return kPrisma.user.count().catch((e) => {
|
return kPrisma.user.count().catch((e) => {
|
||||||
console.error("❌ get user count failed", e);
|
kDBLogger.error("get user count failed", e);
|
||||||
return -1;
|
return -1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ class _UserCRUD {
|
||||||
) {
|
) {
|
||||||
const { include = { rooms: false } } = options ?? {};
|
const { include = { rooms: false } } = options ?? {};
|
||||||
return kPrisma.user.findFirst({ where: { id }, include }).catch((e) => {
|
return kPrisma.user.findFirst({ where: { id }, include }).catch((e) => {
|
||||||
console.error("❌ get user failed", id, e);
|
kDBLogger.error("get user failed", id, e);
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ class _UserCRUD {
|
||||||
...getSkipWithCursor(skip, cursorId),
|
...getSkipWithCursor(skip, cursorId),
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ get users failed", options, e);
|
kDBLogger.error("get users failed", options, e);
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
return order === "desc" ? users.reverse() : users;
|
return order === "desc" ? users.reverse() : users;
|
||||||
|
@ -68,7 +68,7 @@ class _UserCRUD {
|
||||||
update: user,
|
update: user,
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ add user to db failed", user, e);
|
kDBLogger.error("add user to db failed", user, e);
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import axios, { AxiosRequestConfig, CreateAxiosDefaults } from "axios";
|
import axios, { AxiosRequestConfig, CreateAxiosDefaults } from "axios";
|
||||||
import { HttpsProxyAgent } from "https-proxy-agent";
|
import { HttpsProxyAgent } from "https-proxy-agent";
|
||||||
import { isNotEmpty } from "../utils/is";
|
import { isNotEmpty } from "../utils/is";
|
||||||
|
import { Logger } from "../utils/log";
|
||||||
|
|
||||||
export const kProxyAgent = new HttpsProxyAgent(
|
export const kProxyAgent = new HttpsProxyAgent(
|
||||||
process.env.HTTP_PROXY ?? "http://127.0.0.1:7890"
|
process.env.HTTP_PROXY ?? "http://127.0.0.1:7890"
|
||||||
|
@ -29,6 +30,7 @@ type RequestConfig = AxiosRequestConfig<any> & {
|
||||||
cookies?: Record<string, string | number | boolean | undefined>;
|
cookies?: Record<string, string | number | boolean | undefined>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const _logger = Logger.create({ tag: "Http" });
|
||||||
_http.interceptors.response.use(
|
_http.interceptors.response.use(
|
||||||
(res) => {
|
(res) => {
|
||||||
const config: any = res.config;
|
const config: any = res.config;
|
||||||
|
@ -45,8 +47,8 @@ _http.interceptors.response.use(
|
||||||
code: error.code ?? "UNKNOWN CODE",
|
code: error.code ?? "UNKNOWN CODE",
|
||||||
message: error.message ?? "UNKNOWN ERROR",
|
message: error.message ?? "UNKNOWN ERROR",
|
||||||
};
|
};
|
||||||
console.error(
|
_logger.error(
|
||||||
"❌ Network request failed:",
|
"Network request failed:",
|
||||||
apiError.code,
|
apiError.code,
|
||||||
apiError.message,
|
apiError.message,
|
||||||
error
|
error
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { kEnvs } from "../utils/env";
|
||||||
import { kProxyAgent } from "./http";
|
import { kProxyAgent } from "./http";
|
||||||
import { withDefault } from "../utils/base";
|
import { withDefault } from "../utils/base";
|
||||||
import { ChatCompletionCreateParamsBase } from "openai/resources/chat/completions";
|
import { ChatCompletionCreateParamsBase } from "openai/resources/chat/completions";
|
||||||
|
import { Logger } from "../utils/log";
|
||||||
|
|
||||||
export interface ChatOptions {
|
export interface ChatOptions {
|
||||||
user: string;
|
user: string;
|
||||||
|
@ -19,6 +20,7 @@ export interface ChatOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
class OpenAIClient {
|
class OpenAIClient {
|
||||||
|
private _logger = Logger.create({ tag: "OpenAI" });
|
||||||
private _client = new OpenAI({
|
private _client = new OpenAI({
|
||||||
httpAgent: kProxyAgent,
|
httpAgent: kProxyAgent,
|
||||||
apiKey: kEnvs.OPENAI_API_KEY!,
|
apiKey: kEnvs.OPENAI_API_KEY!,
|
||||||
|
@ -44,9 +46,8 @@ class OpenAIClient {
|
||||||
requestId,
|
requestId,
|
||||||
model = kEnvs.OPENAI_MODEL ?? "gpt-3.5-turbo-0125",
|
model = kEnvs.OPENAI_MODEL ?? "gpt-3.5-turbo-0125",
|
||||||
} = options;
|
} = options;
|
||||||
console.log(
|
this._logger.log(
|
||||||
`
|
`🔥 onAskAI
|
||||||
🔥🔥🔥 onAskAI start
|
|
||||||
🤖️ System: ${system ?? "None"}
|
🤖️ System: ${system ?? "None"}
|
||||||
😊 User: ${user}
|
😊 User: ${user}
|
||||||
`.trim()
|
`.trim()
|
||||||
|
@ -71,16 +72,11 @@ class OpenAIClient {
|
||||||
{ signal }
|
{ signal }
|
||||||
)
|
)
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ openai chat failed", e);
|
this._logger.error("openai chat failed", e);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
const message = chatCompletion?.choices?.[0]?.message;
|
const message = chatCompletion?.choices?.[0]?.message;
|
||||||
console.log(
|
this._logger.success(`🤖️ Answer: ${message?.content ?? "None"}`.trim());
|
||||||
`
|
|
||||||
✅✅✅ onAskAI end
|
|
||||||
🤖️ Answer: ${message?.content ?? "None"}
|
|
||||||
`.trim()
|
|
||||||
);
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,9 +94,8 @@ class OpenAIClient {
|
||||||
onStream,
|
onStream,
|
||||||
model = kEnvs.OPENAI_MODEL ?? "gpt-3.5-turbo-0125",
|
model = kEnvs.OPENAI_MODEL ?? "gpt-3.5-turbo-0125",
|
||||||
} = options;
|
} = options;
|
||||||
console.log(
|
this._logger.log(
|
||||||
`
|
`🔥 onAskAI
|
||||||
🔥🔥🔥 onAskAI start
|
|
||||||
🤖️ System: ${system ?? "None"}
|
🤖️ System: ${system ?? "None"}
|
||||||
😊 User: ${user}
|
😊 User: ${user}
|
||||||
`.trim()
|
`.trim()
|
||||||
|
@ -117,7 +112,7 @@ class OpenAIClient {
|
||||||
response_format: jsonMode ? { type: "json_object" } : undefined,
|
response_format: jsonMode ? { type: "json_object" } : undefined,
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("❌ openai chat failed", e);
|
this._logger.error("❌ openai chat failed", e);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
|
@ -140,12 +135,7 @@ class OpenAIClient {
|
||||||
content += text;
|
content += text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(
|
this._logger.success(`🤖️ Answer: ${content ?? "None"}`.trim());
|
||||||
`
|
|
||||||
✅✅✅ onAskAI end
|
|
||||||
🤖️ Answer: ${content ?? "None"}
|
|
||||||
`.trim()
|
|
||||||
);
|
|
||||||
return withDefault(content, undefined);
|
return withDefault(content, undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { assert } from "console";
|
|
||||||
import {
|
import {
|
||||||
|
MiIOT,
|
||||||
|
MiNA,
|
||||||
MiServiceConfig,
|
MiServiceConfig,
|
||||||
getMiIOT,
|
getMiIOT,
|
||||||
getMiNA,
|
getMiNA,
|
||||||
MiNA,
|
|
||||||
MiIOT,
|
|
||||||
} from "mi-service-lite";
|
} from "mi-service-lite";
|
||||||
import { sleep } from "../../utils/base";
|
import { sleep } from "../../utils/base";
|
||||||
|
import { Logger } from "../../utils/log";
|
||||||
import { Http } from "../http";
|
import { Http } from "../http";
|
||||||
import { StreamResponse } from "./stream";
|
import { StreamResponse } from "./stream";
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ export type BaseSpeakerConfig = MiServiceConfig & {
|
||||||
};
|
};
|
||||||
|
|
||||||
export class BaseSpeaker {
|
export class BaseSpeaker {
|
||||||
|
logger = Logger.create({ tag: "Speaker" });
|
||||||
MiNA?: MiNA;
|
MiNA?: MiNA;
|
||||||
MiIOT?: MiIOT;
|
MiIOT?: MiIOT;
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ export class BaseSpeaker {
|
||||||
async initMiServices() {
|
async initMiServices() {
|
||||||
this.MiNA = await getMiNA(this.config);
|
this.MiNA = await getMiNA(this.config);
|
||||||
this.MiIOT = await getMiIOT(this.config);
|
this.MiIOT = await getMiIOT(this.config);
|
||||||
assert(!!this.MiNA && !!this.MiIOT, "❌ init Mi Services failed");
|
this.logger.assert(!!this.MiNA && !!this.MiIOT, "init Mi Services failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
wakeUp() {
|
wakeUp() {
|
||||||
|
@ -169,7 +170,7 @@ export class BaseSpeaker {
|
||||||
await this.unWakeUp();
|
await this.unWakeUp();
|
||||||
}
|
}
|
||||||
await this.MiNA!.play(args);
|
await this.MiNA!.play(args);
|
||||||
console.log("✅ " + ttsText ?? audio);
|
this.logger.success(ttsText ?? audio);
|
||||||
// 等待回答播放完毕
|
// 等待回答播放完毕
|
||||||
while (true) {
|
while (true) {
|
||||||
const res = await this.MiNA!.getStatus();
|
const res = await this.MiNA!.getStatus();
|
||||||
|
|
|
@ -64,13 +64,13 @@ export class Speaker extends BaseSpeaker {
|
||||||
if (!this.MiNA) {
|
if (!this.MiNA) {
|
||||||
this.stop();
|
this.stop();
|
||||||
}
|
}
|
||||||
console.log("✅ 服务已启动...");
|
this.logger.success("服务已启动...");
|
||||||
this.activeKeepAliveMode();
|
this.activeKeepAliveMode();
|
||||||
while (this.status === "running") {
|
while (this.status === "running") {
|
||||||
const nextMsg = await this.fetchNextMessage();
|
const nextMsg = await this.fetchNextMessage();
|
||||||
if (nextMsg) {
|
if (nextMsg) {
|
||||||
this.responding = false;
|
this.responding = false;
|
||||||
console.log("🔥 " + nextMsg.text);
|
this.logger.log("🔥 " + nextMsg.text);
|
||||||
// 异步处理消息,不阻塞正常消息拉取
|
// 异步处理消息,不阻塞正常消息拉取
|
||||||
this.onMessage(nextMsg);
|
this.onMessage(nextMsg);
|
||||||
}
|
}
|
||||||
|
|
110
src/utils/log.ts
Normal file
110
src/utils/log.ts
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
import { toSet } from "./base";
|
||||||
|
import { isString } from "./is";
|
||||||
|
import { formatDateTime } from "./string";
|
||||||
|
|
||||||
|
class _LoggerManager {
|
||||||
|
disable = false;
|
||||||
|
_excludes: string[] = [];
|
||||||
|
|
||||||
|
excludes(tags: string[]) {
|
||||||
|
this._excludes = toSet(this._excludes.concat(tags));
|
||||||
|
}
|
||||||
|
|
||||||
|
includes(tags: string[]) {
|
||||||
|
for (const tag of tags) {
|
||||||
|
const idx = this._excludes.indexOf(tag);
|
||||||
|
if (idx > -1) {
|
||||||
|
this._excludes.splice(idx, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getLogs(tag: string, ...args: any[]) {
|
||||||
|
if (this.disable || this._excludes.includes(tag)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const date = formatDateTime(new Date());
|
||||||
|
let prefix = `${date} ${tag} `;
|
||||||
|
if (args.length < 1) {
|
||||||
|
args = [undefined];
|
||||||
|
}
|
||||||
|
if (isString(args[0])) {
|
||||||
|
prefix += args[0];
|
||||||
|
args = args.slice(1);
|
||||||
|
}
|
||||||
|
return [prefix, ...args];
|
||||||
|
}
|
||||||
|
|
||||||
|
log(tag: string, args: any[] = []) {
|
||||||
|
const logs = this._getLogs(tag, ...args);
|
||||||
|
if (logs.length > 0) {
|
||||||
|
console.log(...logs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
success(tag: string, args: any[]) {
|
||||||
|
const logs = this._getLogs(tag + " ✅", ...args);
|
||||||
|
if (logs.length > 0) {
|
||||||
|
console.log(...logs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error(tag: string, args: any[]) {
|
||||||
|
const logs = this._getLogs(tag + " ❌", ...args);
|
||||||
|
if (logs.length > 0) {
|
||||||
|
console.error(...logs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(tag: string, value: any, args: any[]) {
|
||||||
|
const logs = this._getLogs(tag + " ❌", ...args);
|
||||||
|
if (!value) {
|
||||||
|
console.error(...logs);
|
||||||
|
throw Error("❌ Assertion failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LoggerManager = new _LoggerManager();
|
||||||
|
|
||||||
|
export interface LoggerConfig {
|
||||||
|
tag?: string;
|
||||||
|
disable?: boolean;
|
||||||
|
}
|
||||||
|
class _Logger {
|
||||||
|
tag: string;
|
||||||
|
disable: boolean;
|
||||||
|
constructor(config?: LoggerConfig) {
|
||||||
|
const { tag = "default", disable = false } = config ?? {};
|
||||||
|
this.tag = tag;
|
||||||
|
this.disable = disable;
|
||||||
|
}
|
||||||
|
|
||||||
|
create(config?: LoggerConfig) {
|
||||||
|
return new _Logger(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
log(...args: any[]) {
|
||||||
|
if (!this.disable) {
|
||||||
|
LoggerManager.log(this.tag, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
success(...args: any[]) {
|
||||||
|
if (!this.disable) {
|
||||||
|
LoggerManager.success(this.tag, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error(...args: any[]) {
|
||||||
|
if (!this.disable) {
|
||||||
|
LoggerManager.error(this.tag, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(value: any, ...args: any[]) {
|
||||||
|
LoggerManager.assert(this.tag, value, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Logger = new _Logger();
|
|
@ -52,3 +52,14 @@ export function formatMsg(msg: {
|
||||||
const { name, text, timestamp } = msg;
|
const { name, text, timestamp } = msg;
|
||||||
return `${toUTC8Time(new Date(timestamp))} ${name}: ${text}`;
|
return `${toUTC8Time(new Date(timestamp))} ${name}: ${text}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatDateTime(date: Date) {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||||
|
const day = String(date.getDate()).padStart(2, "0");
|
||||||
|
const hours = String(date.getHours()).padStart(2, "0");
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, "0");
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, "0");
|
||||||
|
|
||||||
|
return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { testDB } from "./db";
|
||||||
import { testSpeaker } from "./speaker";
|
import { testSpeaker } from "./speaker";
|
||||||
import { testOpenAI } from "./openai";
|
import { testOpenAI } from "./openai";
|
||||||
import { testMyBot } from "./bot";
|
import { testMyBot } from "./bot";
|
||||||
|
import { testLog } from "./log";
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
|
@ -14,7 +15,8 @@ async function main() {
|
||||||
// testDB();
|
// testDB();
|
||||||
// testSpeaker();
|
// testSpeaker();
|
||||||
// testOpenAI();
|
// testOpenAI();
|
||||||
testMyBot();
|
// testMyBot();
|
||||||
|
testLog();
|
||||||
}
|
}
|
||||||
|
|
||||||
runWithDB(main);
|
runWithDB(main);
|
||||||
|
|
9
tests/log.ts
Normal file
9
tests/log.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { Logger } from "../src/utils/log";
|
||||||
|
|
||||||
|
export function testLog() {
|
||||||
|
Logger.log("你好", ["世界"], { hello: "world!" });
|
||||||
|
Logger.success("你好", ["世界"], { hello: "world!" });
|
||||||
|
Logger.error("你好", ["世界"], { hello: "world!" });
|
||||||
|
Logger.assert(true, "你好 111", ["世界"], { hello: "world!" });
|
||||||
|
Logger.assert(false, "你好 222", ["世界"], { hello: "world!" });
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user