mem1 0.0.6__py3-none-any.whl → 0.0.8__py3-none-any.whl
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.
- mem1/__init__.py +5 -4
- mem1/config.py +14 -5
- mem1/llm.py +54 -5
- mem1/{memory_es.py → memory.py} +225 -382
- mem1/prompts.py +22 -0
- mem1/storage.py +399 -0
- mem1-0.0.8.dist-info/METADATA +290 -0
- mem1-0.0.8.dist-info/RECORD +12 -0
- mem1-0.0.6.dist-info/METADATA +0 -191
- mem1-0.0.6.dist-info/RECORD +0 -11
- {mem1-0.0.6.dist-info → mem1-0.0.8.dist-info}/WHEEL +0 -0
mem1/__init__.py
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Mem1 -
|
|
2
|
+
Mem1 - 用户记忆系统(支持可插拔存储后端)
|
|
3
3
|
"""
|
|
4
4
|
import logging
|
|
5
5
|
|
|
6
|
-
__version__ = "0.0.
|
|
6
|
+
__version__ = "0.0.7"
|
|
7
7
|
|
|
8
8
|
# 屏蔽第三方库的详细日志(必须在导入前设置)
|
|
9
9
|
logging.getLogger("elastic_transport").setLevel(logging.WARNING)
|
|
10
10
|
logging.getLogger("elastic_transport.transport").setLevel(logging.WARNING)
|
|
11
11
|
logging.getLogger("httpx").setLevel(logging.WARNING)
|
|
12
12
|
|
|
13
|
-
from mem1.
|
|
13
|
+
from mem1.memory import Mem1Memory
|
|
14
14
|
from mem1.config import Mem1Config, LLMConfig
|
|
15
|
+
from mem1.storage import StorageBackend, ESStorage
|
|
15
16
|
|
|
16
|
-
__all__ = ["Mem1Memory", "Mem1Config", "LLMConfig"]
|
|
17
|
+
__all__ = ["Mem1Memory", "Mem1Config", "LLMConfig", "StorageBackend", "ESStorage"]
|
mem1/config.py
CHANGED
|
@@ -13,14 +13,21 @@ class LLMConfig(BaseModel):
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class VLConfig(BaseModel):
|
|
16
|
-
"""视觉语言模型配置(可选,配置了
|
|
16
|
+
"""视觉语言模型配置(可选,配置了 provider 即启用)
|
|
17
|
+
|
|
18
|
+
支持的 provider:
|
|
19
|
+
- qwen: 使用 dashscope SDK 调用 Qwen-VL
|
|
20
|
+
- doubao: 使用 OpenAI 兼容接口调用豆包视觉模型
|
|
21
|
+
"""
|
|
22
|
+
provider: str = "" # qwen / doubao
|
|
17
23
|
model: str = ""
|
|
18
24
|
api_key: str = ""
|
|
25
|
+
base_url: str = "" # doubao 需要
|
|
19
26
|
|
|
20
27
|
@property
|
|
21
28
|
def enabled(self) -> bool:
|
|
22
|
-
"""
|
|
23
|
-
return bool(self.
|
|
29
|
+
"""配置了 provider 就启用"""
|
|
30
|
+
return bool(self.provider)
|
|
24
31
|
|
|
25
32
|
|
|
26
33
|
class MemoryConfig(BaseModel):
|
|
@@ -101,10 +108,12 @@ class Mem1Config(BaseModel):
|
|
|
101
108
|
memory_dir = required_vars["MEM1_MEMORY_DIR"]
|
|
102
109
|
images_dir = f"{memory_dir}/images"
|
|
103
110
|
|
|
104
|
-
# VL 模型配置(可选,配置了
|
|
111
|
+
# VL 模型配置(可选,配置了 provider 即启用)
|
|
105
112
|
vl_config = VLConfig(
|
|
113
|
+
provider=os.getenv("MEM1_VL_PROVIDER", ""),
|
|
106
114
|
model=os.getenv("MEM1_VL_MODEL", ""),
|
|
107
|
-
api_key=os.getenv("MEM1_VL_API_KEY", "")
|
|
115
|
+
api_key=os.getenv("MEM1_VL_API_KEY", ""),
|
|
116
|
+
base_url=os.getenv("MEM1_VL_BASE_URL", "")
|
|
108
117
|
)
|
|
109
118
|
|
|
110
119
|
return cls(
|
mem1/llm.py
CHANGED
|
@@ -44,12 +44,20 @@ class LLMClient:
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
class VLClient:
|
|
47
|
-
"""
|
|
47
|
+
"""视觉语言模型客户端(支持 qwen/doubao)"""
|
|
48
48
|
|
|
49
49
|
def __init__(self, config: VLConfig):
|
|
50
50
|
self.config = config
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
self.provider = config.provider.lower()
|
|
52
|
+
|
|
53
|
+
if self.provider == "qwen":
|
|
54
|
+
import dashscope
|
|
55
|
+
dashscope.api_key = config.api_key
|
|
56
|
+
elif self.provider == "doubao":
|
|
57
|
+
self.client = OpenAI(
|
|
58
|
+
api_key=config.api_key,
|
|
59
|
+
base_url=config.base_url
|
|
60
|
+
)
|
|
53
61
|
|
|
54
62
|
def understand_image(
|
|
55
63
|
self,
|
|
@@ -65,13 +73,22 @@ class VLClient:
|
|
|
65
73
|
Returns:
|
|
66
74
|
图片理解结果(包含 OCR 文字和内容描述)
|
|
67
75
|
"""
|
|
68
|
-
import dashscope
|
|
69
|
-
|
|
70
76
|
prompt = "请分析这张图片,完成以下任务:\n1. OCR识别:提取图片中的所有文字\n2. 内容理解:描述图片的主要内容和关键信息\n\n请用简洁的中文回答,格式如下:\n【文字内容】...\n【图片描述】..."
|
|
71
77
|
|
|
72
78
|
if user_description:
|
|
73
79
|
prompt += f"\n\n用户补充说明:{user_description}"
|
|
74
80
|
|
|
81
|
+
if self.provider == "qwen":
|
|
82
|
+
return self._call_qwen(image_path, prompt)
|
|
83
|
+
elif self.provider == "doubao":
|
|
84
|
+
return self._call_doubao(image_path, prompt)
|
|
85
|
+
else:
|
|
86
|
+
raise ValueError(f"不支持的 VL provider: {self.provider}")
|
|
87
|
+
|
|
88
|
+
def _call_qwen(self, image_path: str, prompt: str) -> str:
|
|
89
|
+
"""调用 Qwen-VL(dashscope SDK)"""
|
|
90
|
+
import dashscope
|
|
91
|
+
|
|
75
92
|
messages = [
|
|
76
93
|
{
|
|
77
94
|
"role": "user",
|
|
@@ -88,3 +105,35 @@ class VLClient:
|
|
|
88
105
|
)
|
|
89
106
|
|
|
90
107
|
return response.output.choices[0].message.content[0]["text"]
|
|
108
|
+
|
|
109
|
+
def _call_doubao(self, image_path: str, prompt: str) -> str:
|
|
110
|
+
"""调用豆包视觉模型(OpenAI 兼容接口)"""
|
|
111
|
+
import base64
|
|
112
|
+
|
|
113
|
+
# 读取图片并转为 base64
|
|
114
|
+
with open(image_path, "rb") as f:
|
|
115
|
+
image_data = base64.b64encode(f.read()).decode("utf-8")
|
|
116
|
+
|
|
117
|
+
# 获取图片格式
|
|
118
|
+
ext = image_path.lower().split(".")[-1]
|
|
119
|
+
mime_type = {"png": "image/png", "jpg": "image/jpeg", "jpeg": "image/jpeg", "gif": "image/gif", "webp": "image/webp"}.get(ext, "image/png")
|
|
120
|
+
|
|
121
|
+
messages = [
|
|
122
|
+
{
|
|
123
|
+
"role": "user",
|
|
124
|
+
"content": [
|
|
125
|
+
{
|
|
126
|
+
"type": "image_url",
|
|
127
|
+
"image_url": {"url": f"data:{mime_type};base64,{image_data}"}
|
|
128
|
+
},
|
|
129
|
+
{"type": "text", "text": prompt}
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
|
|
134
|
+
response = self.client.chat.completions.create(
|
|
135
|
+
model=self.config.model,
|
|
136
|
+
messages=messages
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
return response.choices[0].message.content
|