llm-token-saver 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- llm_token_saver-0.1.0/LICENSE +21 -0
- llm_token_saver-0.1.0/PKG-INFO +92 -0
- llm_token_saver-0.1.0/README.md +80 -0
- llm_token_saver-0.1.0/llm_token_saver.egg-info/PKG-INFO +92 -0
- llm_token_saver-0.1.0/llm_token_saver.egg-info/SOURCES.txt +15 -0
- llm_token_saver-0.1.0/llm_token_saver.egg-info/dependency_links.txt +1 -0
- llm_token_saver-0.1.0/llm_token_saver.egg-info/requires.txt +1 -0
- llm_token_saver-0.1.0/llm_token_saver.egg-info/top_level.txt +1 -0
- llm_token_saver-0.1.0/pyproject.toml +17 -0
- llm_token_saver-0.1.0/setup.cfg +4 -0
- llm_token_saver-0.1.0/token_saver/__init__.py +4 -0
- llm_token_saver-0.1.0/token_saver/client.py +51 -0
- llm_token_saver-0.1.0/token_saver/optimizers/__init__.py +5 -0
- llm_token_saver-0.1.0/token_saver/optimizers/base.py +10 -0
- llm_token_saver-0.1.0/token_saver/optimizers/context.py +20 -0
- llm_token_saver-0.1.0/token_saver/optimizers/output.py +11 -0
- llm_token_saver-0.1.0/token_saver/optimizers/prefix.py +26 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 李泉
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: llm-token-saver
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A seamless LLM API middleware to maximize context cache hits and reduce token costs.
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/quan0618/token-saver
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: openai>=1.0.0
|
|
11
|
+
Dynamic: license-file
|
|
12
|
+
|
|
13
|
+
```markdown
|
|
14
|
+
# 🛡️ Token-Saver
|
|
15
|
+
[](https://pypi.org/project/token-saver/)
|
|
16
|
+
[](https://opensource.org/licenses/MIT)
|
|
17
|
+
[](https://www.python.org/downloads/)
|
|
18
|
+
|
|
19
|
+
**Token-Saver** 是一个极致轻量、无侵入的 LLM API 中间件。只需一行代码,就能自动优化你的 Prompt 结构,大幅提升上下文缓存(Context Cache)命中率,并自动修剪冗长的对话历史,帮你直接砍掉 50%+ 的 API 账单!
|
|
20
|
+
## ✨ 核心特性
|
|
21
|
+
- **⚡ 零侵入接入**:完全兼容 OpenAI 官方 SDK 格式,无需重写业务逻辑。
|
|
22
|
+
- **🎯 前缀稳定器 (Prefix Stabilizer)**:自动提取 System Prompt 中的动态变量(如时间戳、随机 ID)到末尾,确保请求前缀字节级一致,强制触发缓存命中。
|
|
23
|
+
- **✂️ 上下文瘦身 (Context Pruner)**:自动检测并截断超长对话历史,防止输入 Token 无限膨胀。
|
|
24
|
+
- **🤐 输出防废话 (Output Constraint)**:自动注入隐藏提示词,让大模型直接给结果,减少输出 Token 浪费。
|
|
25
|
+
|
|
26
|
+
## 📦 安装
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install token-saver
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 🚀 极简用法
|
|
33
|
+
|
|
34
|
+
只需要用 `TokenSaver` 包装你现有的官方客户端,其他代码完全不用改:
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from openai import OpenAI
|
|
38
|
+
from token_saver import TokenSaver
|
|
39
|
+
|
|
40
|
+
# 1. 初始化原生客户端
|
|
41
|
+
raw_client = OpenAI(api_key="your-api-key", base_url="https://api.deepseek.com/v1")
|
|
42
|
+
|
|
43
|
+
# 2. 用 TokenSaver 包裹它!
|
|
44
|
+
client = TokenSaver(client=raw_client)
|
|
45
|
+
|
|
46
|
+
# 3. 像平常一样调用 (Token-Saver 会在后台自动优化)
|
|
47
|
+
response = client.chat.completions.create(
|
|
48
|
+
model="deepseek-chat",
|
|
49
|
+
messages=[
|
|
50
|
+
{"role": "system", "content": "你是一个助手。当前时间:2024-05-20 12:00:00"},
|
|
51
|
+
{"role": "user", "content": "给我讲个笑话"}
|
|
52
|
+
]
|
|
53
|
+
)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 🛠️ 高级配置
|
|
57
|
+
|
|
58
|
+
你可以自定义需要保留的上下文轮数:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
# 只保留最近的 5 条历史消息
|
|
62
|
+
client = TokenSaver(client=raw_client, max_history=5)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 🤝 贡献与反馈
|
|
66
|
+
|
|
67
|
+
欢迎提交 Issue 或 Pull Request!如果你觉得这个项目帮你省了钱,请给个 ⭐️ Star 支持一下!
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
### 2. 添加 `pyproject.toml`(安装配置文件)
|
|
73
|
+
|
|
74
|
+
在你的本地仓库根目录,新建一个文件叫 `pyproject.toml`,把下面的代码贴进去。这是目前 Python 打包的标准格式:
|
|
75
|
+
|
|
76
|
+
```toml
|
|
77
|
+
[build-system]
|
|
78
|
+
requires = ["setuptools>=61.0"]
|
|
79
|
+
build-backend = "setuptools.build_meta"
|
|
80
|
+
|
|
81
|
+
[project]
|
|
82
|
+
name = "token-saver"
|
|
83
|
+
version = "0.1.0"
|
|
84
|
+
description = "A seamless LLM API middleware to maximize context cache hits and reduce token costs."
|
|
85
|
+
readme = "README.md"
|
|
86
|
+
requires-python = ">=3.8"
|
|
87
|
+
license = { text = "MIT" }
|
|
88
|
+
dependencies = [
|
|
89
|
+
"openai>=1.0.0",
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
```
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
```markdown
|
|
2
|
+
# 🛡️ Token-Saver
|
|
3
|
+
[](https://pypi.org/project/token-saver/)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
|
|
7
|
+
**Token-Saver** 是一个极致轻量、无侵入的 LLM API 中间件。只需一行代码,就能自动优化你的 Prompt 结构,大幅提升上下文缓存(Context Cache)命中率,并自动修剪冗长的对话历史,帮你直接砍掉 50%+ 的 API 账单!
|
|
8
|
+
## ✨ 核心特性
|
|
9
|
+
- **⚡ 零侵入接入**:完全兼容 OpenAI 官方 SDK 格式,无需重写业务逻辑。
|
|
10
|
+
- **🎯 前缀稳定器 (Prefix Stabilizer)**:自动提取 System Prompt 中的动态变量(如时间戳、随机 ID)到末尾,确保请求前缀字节级一致,强制触发缓存命中。
|
|
11
|
+
- **✂️ 上下文瘦身 (Context Pruner)**:自动检测并截断超长对话历史,防止输入 Token 无限膨胀。
|
|
12
|
+
- **🤐 输出防废话 (Output Constraint)**:自动注入隐藏提示词,让大模型直接给结果,减少输出 Token 浪费。
|
|
13
|
+
|
|
14
|
+
## 📦 安装
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install token-saver
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 🚀 极简用法
|
|
21
|
+
|
|
22
|
+
只需要用 `TokenSaver` 包装你现有的官方客户端,其他代码完全不用改:
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from openai import OpenAI
|
|
26
|
+
from token_saver import TokenSaver
|
|
27
|
+
|
|
28
|
+
# 1. 初始化原生客户端
|
|
29
|
+
raw_client = OpenAI(api_key="your-api-key", base_url="https://api.deepseek.com/v1")
|
|
30
|
+
|
|
31
|
+
# 2. 用 TokenSaver 包裹它!
|
|
32
|
+
client = TokenSaver(client=raw_client)
|
|
33
|
+
|
|
34
|
+
# 3. 像平常一样调用 (Token-Saver 会在后台自动优化)
|
|
35
|
+
response = client.chat.completions.create(
|
|
36
|
+
model="deepseek-chat",
|
|
37
|
+
messages=[
|
|
38
|
+
{"role": "system", "content": "你是一个助手。当前时间:2024-05-20 12:00:00"},
|
|
39
|
+
{"role": "user", "content": "给我讲个笑话"}
|
|
40
|
+
]
|
|
41
|
+
)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 🛠️ 高级配置
|
|
45
|
+
|
|
46
|
+
你可以自定义需要保留的上下文轮数:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
# 只保留最近的 5 条历史消息
|
|
50
|
+
client = TokenSaver(client=raw_client, max_history=5)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 🤝 贡献与反馈
|
|
54
|
+
|
|
55
|
+
欢迎提交 Issue 或 Pull Request!如果你觉得这个项目帮你省了钱,请给个 ⭐️ Star 支持一下!
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### 2. 添加 `pyproject.toml`(安装配置文件)
|
|
61
|
+
|
|
62
|
+
在你的本地仓库根目录,新建一个文件叫 `pyproject.toml`,把下面的代码贴进去。这是目前 Python 打包的标准格式:
|
|
63
|
+
|
|
64
|
+
```toml
|
|
65
|
+
[build-system]
|
|
66
|
+
requires = ["setuptools>=61.0"]
|
|
67
|
+
build-backend = "setuptools.build_meta"
|
|
68
|
+
|
|
69
|
+
[project]
|
|
70
|
+
name = "token-saver"
|
|
71
|
+
version = "0.1.0"
|
|
72
|
+
description = "A seamless LLM API middleware to maximize context cache hits and reduce token costs."
|
|
73
|
+
readme = "README.md"
|
|
74
|
+
requires-python = ">=3.8"
|
|
75
|
+
license = { text = "MIT" }
|
|
76
|
+
dependencies = [
|
|
77
|
+
"openai>=1.0.0",
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
```
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: llm-token-saver
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A seamless LLM API middleware to maximize context cache hits and reduce token costs.
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/quan0618/token-saver
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: openai>=1.0.0
|
|
11
|
+
Dynamic: license-file
|
|
12
|
+
|
|
13
|
+
```markdown
|
|
14
|
+
# 🛡️ Token-Saver
|
|
15
|
+
[](https://pypi.org/project/token-saver/)
|
|
16
|
+
[](https://opensource.org/licenses/MIT)
|
|
17
|
+
[](https://www.python.org/downloads/)
|
|
18
|
+
|
|
19
|
+
**Token-Saver** 是一个极致轻量、无侵入的 LLM API 中间件。只需一行代码,就能自动优化你的 Prompt 结构,大幅提升上下文缓存(Context Cache)命中率,并自动修剪冗长的对话历史,帮你直接砍掉 50%+ 的 API 账单!
|
|
20
|
+
## ✨ 核心特性
|
|
21
|
+
- **⚡ 零侵入接入**:完全兼容 OpenAI 官方 SDK 格式,无需重写业务逻辑。
|
|
22
|
+
- **🎯 前缀稳定器 (Prefix Stabilizer)**:自动提取 System Prompt 中的动态变量(如时间戳、随机 ID)到末尾,确保请求前缀字节级一致,强制触发缓存命中。
|
|
23
|
+
- **✂️ 上下文瘦身 (Context Pruner)**:自动检测并截断超长对话历史,防止输入 Token 无限膨胀。
|
|
24
|
+
- **🤐 输出防废话 (Output Constraint)**:自动注入隐藏提示词,让大模型直接给结果,减少输出 Token 浪费。
|
|
25
|
+
|
|
26
|
+
## 📦 安装
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install token-saver
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 🚀 极简用法
|
|
33
|
+
|
|
34
|
+
只需要用 `TokenSaver` 包装你现有的官方客户端,其他代码完全不用改:
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from openai import OpenAI
|
|
38
|
+
from token_saver import TokenSaver
|
|
39
|
+
|
|
40
|
+
# 1. 初始化原生客户端
|
|
41
|
+
raw_client = OpenAI(api_key="your-api-key", base_url="https://api.deepseek.com/v1")
|
|
42
|
+
|
|
43
|
+
# 2. 用 TokenSaver 包裹它!
|
|
44
|
+
client = TokenSaver(client=raw_client)
|
|
45
|
+
|
|
46
|
+
# 3. 像平常一样调用 (Token-Saver 会在后台自动优化)
|
|
47
|
+
response = client.chat.completions.create(
|
|
48
|
+
model="deepseek-chat",
|
|
49
|
+
messages=[
|
|
50
|
+
{"role": "system", "content": "你是一个助手。当前时间:2024-05-20 12:00:00"},
|
|
51
|
+
{"role": "user", "content": "给我讲个笑话"}
|
|
52
|
+
]
|
|
53
|
+
)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 🛠️ 高级配置
|
|
57
|
+
|
|
58
|
+
你可以自定义需要保留的上下文轮数:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
# 只保留最近的 5 条历史消息
|
|
62
|
+
client = TokenSaver(client=raw_client, max_history=5)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 🤝 贡献与反馈
|
|
66
|
+
|
|
67
|
+
欢迎提交 Issue 或 Pull Request!如果你觉得这个项目帮你省了钱,请给个 ⭐️ Star 支持一下!
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
### 2. 添加 `pyproject.toml`(安装配置文件)
|
|
73
|
+
|
|
74
|
+
在你的本地仓库根目录,新建一个文件叫 `pyproject.toml`,把下面的代码贴进去。这是目前 Python 打包的标准格式:
|
|
75
|
+
|
|
76
|
+
```toml
|
|
77
|
+
[build-system]
|
|
78
|
+
requires = ["setuptools>=61.0"]
|
|
79
|
+
build-backend = "setuptools.build_meta"
|
|
80
|
+
|
|
81
|
+
[project]
|
|
82
|
+
name = "token-saver"
|
|
83
|
+
version = "0.1.0"
|
|
84
|
+
description = "A seamless LLM API middleware to maximize context cache hits and reduce token costs."
|
|
85
|
+
readme = "README.md"
|
|
86
|
+
requires-python = ">=3.8"
|
|
87
|
+
license = { text = "MIT" }
|
|
88
|
+
dependencies = [
|
|
89
|
+
"openai>=1.0.0",
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
llm_token_saver.egg-info/PKG-INFO
|
|
5
|
+
llm_token_saver.egg-info/SOURCES.txt
|
|
6
|
+
llm_token_saver.egg-info/dependency_links.txt
|
|
7
|
+
llm_token_saver.egg-info/requires.txt
|
|
8
|
+
llm_token_saver.egg-info/top_level.txt
|
|
9
|
+
token_saver/__init__.py
|
|
10
|
+
token_saver/client.py
|
|
11
|
+
token_saver/optimizers/__init__.py
|
|
12
|
+
token_saver/optimizers/base.py
|
|
13
|
+
token_saver/optimizers/context.py
|
|
14
|
+
token_saver/optimizers/output.py
|
|
15
|
+
token_saver/optimizers/prefix.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
openai>=1.0.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
token_saver
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "llm-token-saver"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A seamless LLM API middleware to maximize context cache hits and reduce token costs."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
dependencies = [
|
|
13
|
+
"openai>=1.0.0",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[project.urls]
|
|
17
|
+
Homepage = "https://github.com/quan0618/token-saver"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
from .optimizers import PrefixStabilizer, ContextPruner, OutputConstraint
|
|
3
|
+
|
|
4
|
+
class TokenSaver:
|
|
5
|
+
"""包装官方的 OpenAI 客户端,实现无缝 Token 优化。"""
|
|
6
|
+
|
|
7
|
+
def __init__(self, client: Any, max_history: int = 10):
|
|
8
|
+
self._client = client
|
|
9
|
+
|
|
10
|
+
# 装配优化器链
|
|
11
|
+
self.optimizers = [
|
|
12
|
+
PrefixStabilizer(),
|
|
13
|
+
ContextPruner(max_messages=max_history),
|
|
14
|
+
OutputConstraint()
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
# 注意这里:直接用 _ChatProxy 类名,不要加 self.
|
|
18
|
+
self.chat = _ChatProxy(self._client.chat, self.optimizers)
|
|
19
|
+
|
|
20
|
+
def __getattr__(self, name):
|
|
21
|
+
# 将其他未修改的属性(如 models)原样返回给官方客户端
|
|
22
|
+
return getattr(self._client, name)
|
|
23
|
+
|
|
24
|
+
class _ChatProxy:
|
|
25
|
+
def __init__(self, original_chat, optimizers):
|
|
26
|
+
self._original_chat = original_chat
|
|
27
|
+
self._optimizers = optimizers
|
|
28
|
+
|
|
29
|
+
# 注意这里:直接用 _CompletionsProxy 类名
|
|
30
|
+
self.completions = _CompletionsProxy(original_chat.completions, optimizers)
|
|
31
|
+
|
|
32
|
+
def __getattr__(self, name):
|
|
33
|
+
return getattr(self._original_chat, name)
|
|
34
|
+
|
|
35
|
+
class _CompletionsProxy:
|
|
36
|
+
def __init__(self, original_completions, optimizers):
|
|
37
|
+
self._original_completions = original_completions
|
|
38
|
+
self._optimizers = optimizers
|
|
39
|
+
|
|
40
|
+
def create(self, *args, **kwargs):
|
|
41
|
+
# 1. 拦截参数中的 messages
|
|
42
|
+
if "messages" in kwargs:
|
|
43
|
+
messages = kwargs["messages"]
|
|
44
|
+
# 2. 依次通过优化器链
|
|
45
|
+
for opt in self._optimizers:
|
|
46
|
+
messages = opt.optimize(messages)
|
|
47
|
+
# 3. 替换为优化后的 messages
|
|
48
|
+
kwargs["messages"] = messages
|
|
49
|
+
|
|
50
|
+
# 4. 放行请求给官方客户端
|
|
51
|
+
return self._original_completions.create(*args, **kwargs)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from typing import List, Dict
|
|
2
|
+
from .base import BaseOptimizer
|
|
3
|
+
|
|
4
|
+
class ContextPruner(BaseOptimizer):
|
|
5
|
+
def __init__(self, max_messages: int = 10):
|
|
6
|
+
self.max_messages = max_messages
|
|
7
|
+
|
|
8
|
+
def optimize(self, messages: List[Dict[str, str]]) -> List[Dict[str, str]]:
|
|
9
|
+
if len(messages) <= self.max_messages:
|
|
10
|
+
return messages
|
|
11
|
+
|
|
12
|
+
# 必须保留 system 开头的消息,裁剪后面的
|
|
13
|
+
system_msgs = [m for m in messages if m.get("role") == "system"]
|
|
14
|
+
other_msgs = [m for m in messages if m.get("role") != "system"]
|
|
15
|
+
|
|
16
|
+
# 只保留最近的 N 条对话
|
|
17
|
+
keep_count = self.max_messages - len(system_msgs)
|
|
18
|
+
pruned_others = other_msgs[-keep_count:] if keep_count > 0 else []
|
|
19
|
+
|
|
20
|
+
return system_msgs + pruned_others
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from typing import List, Dict
|
|
2
|
+
from .base import BaseOptimizer
|
|
3
|
+
|
|
4
|
+
class OutputConstraint(BaseOptimizer):
|
|
5
|
+
def optimize(self, messages: List[Dict[str, str]]) -> List[Dict[str, str]]:
|
|
6
|
+
# 找到最后一条 user 消息,追加约束
|
|
7
|
+
for msg in reversed(messages):
|
|
8
|
+
if msg.get("role") == "user" and isinstance(msg.get("content"), str):
|
|
9
|
+
msg["content"] += "\n\n(注意:请直接给出答案,不要输出客套话或废话。)"
|
|
10
|
+
break
|
|
11
|
+
return messages
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import List, Dict
|
|
3
|
+
from .base import BaseOptimizer
|
|
4
|
+
|
|
5
|
+
class PrefixStabilizer(BaseOptimizer):
|
|
6
|
+
def __init__(self):
|
|
7
|
+
# 匹配常见的日期时间格式,如 "当前时间:2024-05-20 12:00:00"
|
|
8
|
+
self.time_pattern = r'(当前时间[::]\s*[\d\-\/:年月日时分秒\s]+)'
|
|
9
|
+
|
|
10
|
+
def optimize(self, messages: List[Dict[str, str]]) -> List[Dict[str, str]]:
|
|
11
|
+
if not messages:
|
|
12
|
+
return messages
|
|
13
|
+
|
|
14
|
+
for msg in messages:
|
|
15
|
+
if msg.get("role") == "system" and isinstance(msg.get("content"), str):
|
|
16
|
+
content = msg["content"]
|
|
17
|
+
match = re.search(self.time_pattern, content)
|
|
18
|
+
|
|
19
|
+
if match:
|
|
20
|
+
dynamic_part = match.group(1)
|
|
21
|
+
# 剥离动态部分
|
|
22
|
+
static_content = content.replace(dynamic_part, "").strip()
|
|
23
|
+
# 拼接回末尾
|
|
24
|
+
msg["content"] = f"{static_content}\n\n[系统动态信息]: {dynamic_part}"
|
|
25
|
+
|
|
26
|
+
return messages
|