sycommon-python-lib 0.1.56b12__py3-none-any.whl → 0.1.56b14__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.
sycommon/config/Config.py CHANGED
@@ -21,6 +21,7 @@ class Config(metaclass=SingletonMeta):
21
21
  self.embedding_configs = []
22
22
  self.reranker_configs = []
23
23
  self.sentry_configs = []
24
+ self.langfuse_configs = []
24
25
  self._process_config()
25
26
 
26
27
  def get_llm_config(self, model_name):
@@ -47,6 +48,12 @@ class Config(metaclass=SingletonMeta):
47
48
  return sentry
48
49
  raise ValueError(f"No configuration found for server: {name}")
49
50
 
51
+ def get_langfuse_config(self, name):
52
+ for langfuse in self.langfuse_configs:
53
+ if langfuse.get('name') == name:
54
+ return langfuse
55
+ raise ValueError(f"No configuration found for server: {name}")
56
+
50
57
  def _process_config(self):
51
58
  llm_config_list = self.config.get('LLMConfig', [])
52
59
  for llm_config in llm_config_list:
@@ -0,0 +1,15 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class LangfuseConfig(BaseModel):
5
+ name: str
6
+ secretKey: str
7
+ publicKey: str
8
+ baseUrl: str
9
+ enable: bool
10
+
11
+ @classmethod
12
+ def from_config(cls, server_name: str):
13
+ from sycommon.config.Config import Config
14
+ langfuse_config = Config().get_langfuse_config(server_name)
15
+ return cls(**langfuse_config)
sycommon/llm/embedding.py CHANGED
@@ -25,15 +25,21 @@ class Embedding(metaclass=SingletonMeta):
25
25
 
26
26
  # 并发信号量
27
27
  self.semaphore = asyncio.Semaphore(self.max_concurrency)
28
+ # 全局默认超时:永不超时(None)
29
+ self.default_timeout = aiohttp.ClientTimeout(total=None)
28
30
 
29
31
  async def _get_embeddings_http_async(
30
32
  self,
31
33
  input: Union[str, List[str]],
32
34
  encoding_format: str = None,
33
35
  model: str = None,
36
+ timeout: aiohttp.ClientTimeout = None,
34
37
  **kwargs
35
38
  ):
36
39
  async with self.semaphore:
40
+ # 优先使用传入的超时,无则用全局默认
41
+ request_timeout = timeout or self.default_timeout
42
+
37
43
  # 优先使用传入的模型名,无则用默认值
38
44
  target_model = model or self.default_embedding_model
39
45
  target_base_url = EmbeddingConfig.from_config(target_model).baseUrl
@@ -46,14 +52,23 @@ class Embedding(metaclass=SingletonMeta):
46
52
  }
47
53
  request_body.update(kwargs)
48
54
 
49
- async with aiohttp.ClientSession() as session:
50
- async with session.post(url, json=request_body) as response:
51
- if response.status != 200:
52
- error_detail = await response.text()
53
- SYLogger.error(
54
- f"Embedding request failed (model: {target_model}): {error_detail}")
55
- return None
56
- return await response.json()
55
+ try:
56
+ async with aiohttp.ClientSession(timeout=request_timeout) as session:
57
+ async with session.post(url, json=request_body) as response:
58
+ if response.status != 200:
59
+ error_detail = await response.text()
60
+ SYLogger.error(
61
+ f"Embedding request failed (model: {target_model}): {error_detail}")
62
+ return None
63
+ return await response.json()
64
+ except asyncio.TimeoutError:
65
+ SYLogger.error(
66
+ f"Embedding request timeout (model: {target_model})")
67
+ return None
68
+ except Exception as e:
69
+ SYLogger.error(
70
+ f"Embedding request unexpected error (model: {target_model}): {str(e)}")
71
+ return None
57
72
 
58
73
  async def _get_reranker_http_async(
59
74
  self,
@@ -64,9 +79,13 @@ class Embedding(metaclass=SingletonMeta):
64
79
  max_chunks_per_doc: Optional[int] = None,
65
80
  return_documents: Optional[bool] = True,
66
81
  return_len: Optional[bool] = True,
82
+ timeout: aiohttp.ClientTimeout = None,
67
83
  **kwargs
68
84
  ):
69
85
  async with self.semaphore:
86
+ # 优先使用传入的超时,无则用全局默认
87
+ request_timeout = timeout or self.default_timeout
88
+
70
89
  # 优先使用传入的模型名,无则用默认值
71
90
  target_model = model or self.default_reranker_model
72
91
  target_base_url = RerankerConfig.from_config(target_model).baseUrl
@@ -84,19 +103,29 @@ class Embedding(metaclass=SingletonMeta):
84
103
  }
85
104
  request_body.update(kwargs)
86
105
 
87
- async with aiohttp.ClientSession() as session:
88
- async with session.post(url, json=request_body) as response:
89
- if response.status != 200:
90
- error_detail = await response.text()
91
- SYLogger.error(
92
- f"Rerank request failed (model: {target_model}): {error_detail}")
93
- return None
94
- return await response.json()
106
+ try:
107
+ async with aiohttp.ClientSession(timeout=request_timeout) as session:
108
+ async with session.post(url, json=request_body) as response:
109
+ if response.status != 200:
110
+ error_detail = await response.text()
111
+ SYLogger.error(
112
+ f"Rerank request failed (model: {target_model}): {error_detail}")
113
+ return None
114
+ return await response.json()
115
+ except asyncio.TimeoutError:
116
+ SYLogger.error(
117
+ f"Rerank request timeout (model: {target_model})")
118
+ return None
119
+ except Exception as e:
120
+ SYLogger.error(
121
+ f"Rerank request unexpected error (model: {target_model}): {str(e)}")
122
+ return None
95
123
 
96
124
  async def get_embeddings(
97
125
  self,
98
126
  corpus: List[str],
99
- model: str = None
127
+ model: str = None,
128
+ timeout: Optional[Union[int, float]] = None
100
129
  ):
101
130
  """
102
131
  获取语料库的嵌入向量,结果顺序与输入语料库顺序一致
@@ -104,12 +133,24 @@ class Embedding(metaclass=SingletonMeta):
104
133
  Args:
105
134
  corpus: 待生成嵌入向量的文本列表
106
135
  model: 可选,指定使用的embedding模型名称,默认使用bge-large-zh-v1.5
136
+ timeout: 可选,超时时间(秒):
137
+ - 传int/float:表示总超时时间(秒)
138
+ - 不传/None:使用默认永不超时配置
107
139
  """
140
+ request_timeout = None
141
+ if timeout is not None:
142
+ if isinstance(timeout, (int, float)):
143
+ request_timeout = aiohttp.ClientTimeout(total=timeout)
144
+ else:
145
+ SYLogger.warning(
146
+ f"Invalid timeout type: {type(timeout)}, must be int/float, use default timeout")
147
+
108
148
  SYLogger.info(
109
- f"Requesting embeddings for corpus: {corpus} (model: {model or self.default_embedding_model}, max_concurrency: {self.max_concurrency})")
110
- # 给每个异步任务传入模型名称
149
+ f"Requesting embeddings for corpus: {corpus} (model: {model or self.default_embedding_model}, max_concurrency: {self.max_concurrency}, timeout: {timeout or 'None'})")
150
+
151
+ # 给每个异步任务传入模型名称和超时配置
111
152
  tasks = [self._get_embeddings_http_async(
112
- text, model=model) for text in corpus]
153
+ text, model=model, timeout=request_timeout) for text in corpus]
113
154
  results = await asyncio.gather(*tasks)
114
155
 
115
156
  vectors = []
@@ -131,7 +172,8 @@ class Embedding(metaclass=SingletonMeta):
131
172
  self,
132
173
  top_results: List[str],
133
174
  query: str,
134
- model: str = None
175
+ model: str = None,
176
+ timeout: Optional[Union[int, float]] = None
135
177
  ):
136
178
  """
137
179
  对搜索结果进行重排序
@@ -140,10 +182,23 @@ class Embedding(metaclass=SingletonMeta):
140
182
  top_results: 待重排序的文本列表
141
183
  query: 排序参考的查询语句
142
184
  model: 可选,指定使用的reranker模型名称,默认使用bge-reranker-large
185
+ timeout: 可选,超时时间(秒):
186
+ - 传int/float:表示总超时时间(秒)
187
+ - 不传/None:使用默认永不超时配置
143
188
  """
189
+ request_timeout = None
190
+ if timeout is not None:
191
+ if isinstance(timeout, (int, float)):
192
+ request_timeout = aiohttp.ClientTimeout(total=timeout)
193
+ else:
194
+ SYLogger.warning(
195
+ f"Invalid timeout type: {type(timeout)}, must be int/float, use default timeout")
196
+
144
197
  SYLogger.info(
145
- f"Requesting reranker for top_results: {top_results} (model: {model or self.default_reranker_model}, max_concurrency: {self.max_concurrency})")
146
- data = await self._get_reranker_http_async(top_results, query, model=model)
198
+ f"Requesting reranker for top_results: {top_results} (model: {model or self.default_reranker_model}, max_concurrency: {self.max_concurrency}, timeout: {timeout or 'None'})")
199
+
200
+ data = await self._get_reranker_http_async(
201
+ top_results, query, model=model, timeout=request_timeout)
147
202
  SYLogger.info(
148
203
  f"Reranker for top_results: {top_results} completed (model: {model or self.default_reranker_model})")
149
204
  return data
sycommon/llm/get_llm.py CHANGED
@@ -1,4 +1,6 @@
1
+ import os
1
2
  from typing import Dict, Type, List, Optional, Callable, Any
3
+ from sycommon.config.Config import Config
2
4
  from sycommon.llm.llm_logger import LLMLogger
3
5
  from langchain_core.language_models import BaseChatModel
4
6
  from langchain_core.runnables import Runnable, RunnableLambda, RunnableConfig
@@ -10,6 +12,7 @@ from pydantic import BaseModel, ValidationError, Field
10
12
  from sycommon.config.LLMConfig import LLMConfig
11
13
  from sycommon.llm.llm_tokens import TokensCallbackHandler
12
14
  from sycommon.logging.kafka_log import SYLogger
15
+ from langfuse.langchain import CallbackHandler
13
16
 
14
17
 
15
18
  class StructuredRunnableWithToken(Runnable):
@@ -230,6 +233,21 @@ def get_llm(
230
233
  if not llmConfig:
231
234
  raise Exception(f"无效的模型配置:{model}")
232
235
 
236
+ callbacks = [LLMLogger()]
237
+
238
+ config = Config().config
239
+ server_name = config.get('Name', '')
240
+ langfuse_configs = config.get('LangfuseConfig', [])
241
+ target_config = next(
242
+ (item for item in langfuse_configs if item.get('name') == server_name), None)
243
+ if target_config and target_config.get('enable', False):
244
+ os.environ["LANGFUSE_SECRET_KEY"] = target_config.get('secretKey', '')
245
+ os.environ["LANGFUSE_PUBLIC_KEY"] = target_config.get('publicKey', '')
246
+ os.environ["LANGFUSE_BASE_URL"] = target_config.get('baseUrl', '')
247
+
248
+ langfuse_handler = CallbackHandler()
249
+ callbacks += [langfuse_handler]
250
+
233
251
  llm = init_chat_model(
234
252
  model_provider=llmConfig.provider,
235
253
  model=llmConfig.model,
@@ -237,7 +255,7 @@ def get_llm(
237
255
  api_key="-",
238
256
  temperature=0.1,
239
257
  streaming=streaming,
240
- callbacks=[LLMLogger()]
258
+ callbacks=callbacks
241
259
  )
242
260
 
243
261
  if llm is None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sycommon-python-lib
3
- Version: 0.1.56b12
3
+ Version: 0.1.56b14
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -13,6 +13,7 @@ Requires-Dist: kafka-python>=2.3.0
13
13
  Requires-Dist: langchain>=1.2.0
14
14
  Requires-Dist: langchain-core>=1.2.6
15
15
  Requires-Dist: langchain-openai>=1.1.6
16
+ Requires-Dist: langfuse>=3.11.2
16
17
  Requires-Dist: langgraph>=1.0.5
17
18
  Requires-Dist: loguru>=0.7.3
18
19
  Requires-Dist: mysql-connector-python>=9.5.0
@@ -1,10 +1,11 @@
1
1
  command/cli.py,sha256=bP2LCLkRvfETIwWkVD70q5xFxMI4D3BpH09Ws1f-ENc,5849
2
2
  sycommon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  sycommon/services.py,sha256=vcO2vbe2U1CA4ykLdH1rnxgqUIouukE-wTRsjRl2kBI,11683
4
- sycommon/config/Config.py,sha256=Q-HGp-10uTTCOAwnxwT4g-hrOWGDWl7bFPYZZHOmiOo,3742
4
+ sycommon/config/Config.py,sha256=L4vlGsVFL1ZHEULxvE8-VyLF-wDBuOMZGmWXIldqfn8,4014
5
5
  sycommon/config/DatabaseConfig.py,sha256=ILiUuYT9_xJZE2W-RYuC3JCt_YLKc1sbH13-MHIOPhg,804
6
6
  sycommon/config/EmbeddingConfig.py,sha256=gPKwiDYbeu1GpdIZXMmgqM7JqBIzCXi0yYuGRLZooMI,362
7
7
  sycommon/config/LLMConfig.py,sha256=yU-aIqePIeF6msfRVEtGq7SXZVDfHyTi6JduKjhMO_4,371
8
+ sycommon/config/LangfuseConfig.py,sha256=t2LulAtnMUvIINOKHXNWlT5PtgNb7IuaHURjWlbma38,370
8
9
  sycommon/config/MQConfig.py,sha256=_RDcmIdyWKjmgM5ZnriOoI-DpaxgXs7CD0awdAD6z88,252
9
10
  sycommon/config/RerankerConfig.py,sha256=35sVwzus2IscvTHnCG63Orl2pC-pMsrVi6wAGDmOH3U,341
10
11
  sycommon/config/SentryConfig.py,sha256=OsLb3G9lTsCSZ7tWkcXWJHmvfILQopBxje5pjnkFJfo,320
@@ -18,8 +19,8 @@ sycommon/health/health_check.py,sha256=EhfbhspRpQiKJaxdtE-PzpKQO_ucaFKtQxIm16F5M
18
19
  sycommon/health/metrics.py,sha256=fHqO73JuhoZkNPR-xIlxieXiTCvttq-kG-tvxag1s1s,268
19
20
  sycommon/health/ping.py,sha256=FTlnIKk5y1mPfS1ZGOeT5IM_2udF5aqVLubEtuBp18M,250
20
21
  sycommon/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- sycommon/llm/embedding.py,sha256=Wcm2W7JU3FyZXvOhMSdyhiZJhJS1MwW8bMqdrOzD2TY,5768
22
- sycommon/llm/get_llm.py,sha256=wawJO_WSLSYPE8ImL421SYBPtAvWqwbRAcUN7d5i0W0,9434
22
+ sycommon/llm/embedding.py,sha256=HknwDqXmRQcAZ8-6d8wZ6n7Bv7HtxTajDt1vvzHGeFQ,8411
23
+ sycommon/llm/get_llm.py,sha256=vPwGNm2DaF4-ZzhfRUcDFJY756IK93pvGjAnuhP_Fec,10179
23
24
  sycommon/llm/llm_logger.py,sha256=n4UeNy_-g4oHQOsw-VUzF4uo3JVRLtxaMp1FcI8FiEo,5437
24
25
  sycommon/llm/llm_tokens.py,sha256=-udDyFcmyzx6UAwIi6_d_wwI5kMd5w0-WcS2soVPQxg,4309
25
26
  sycommon/logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -78,8 +79,8 @@ sycommon/tools/env.py,sha256=Ah-tBwG2C0_hwLGFebVQgKdWWXCjTzBuF23gCkLHYy4,2437
78
79
  sycommon/tools/merge_headers.py,sha256=HV_i52Q-9se3SP8qh7ZGYl8bP7Fxtal4CGVkyMwEdM8,4373
79
80
  sycommon/tools/snowflake.py,sha256=lVEe5mNCOgz5OqGQpf5_nXaGnRJlI2STX2s-ppTtanA,11947
80
81
  sycommon/tools/timing.py,sha256=OiiE7P07lRoMzX9kzb8sZU9cDb0zNnqIlY5pWqHcnkY,2064
81
- sycommon_python_lib-0.1.56b12.dist-info/METADATA,sha256=dkuadRkMxJOl31ynqjcEezKtvoQ7On9qeGyGSnxCUZ0,7270
82
- sycommon_python_lib-0.1.56b12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
83
- sycommon_python_lib-0.1.56b12.dist-info/entry_points.txt,sha256=q_h2nbvhhmdnsOUZEIwpuoDjaNfBF9XqppDEmQn9d_A,46
84
- sycommon_python_lib-0.1.56b12.dist-info/top_level.txt,sha256=98CJ-cyM2WIKxLz-Pf0AitWLhJyrfXvyY8slwjTXNuc,17
85
- sycommon_python_lib-0.1.56b12.dist-info/RECORD,,
82
+ sycommon_python_lib-0.1.56b14.dist-info/METADATA,sha256=6ctE6A1k94pk7BDDaUWojL_gBLx8dodryWjZjLOa0yU,7302
83
+ sycommon_python_lib-0.1.56b14.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
84
+ sycommon_python_lib-0.1.56b14.dist-info/entry_points.txt,sha256=q_h2nbvhhmdnsOUZEIwpuoDjaNfBF9XqppDEmQn9d_A,46
85
+ sycommon_python_lib-0.1.56b14.dist-info/top_level.txt,sha256=98CJ-cyM2WIKxLz-Pf0AitWLhJyrfXvyY8slwjTXNuc,17
86
+ sycommon_python_lib-0.1.56b14.dist-info/RECORD,,