Files
dify/api/services/ops_service.py
T
+101 0a20210a59 feat: Add W&B Weave Tracing Integration (#14262)
Signed-off-by: Yuichiro Utsumi <[email protected]>
Signed-off-by: -LAN- <[email protected]>
Signed-off-by: yihong0618 <[email protected]>
Signed-off-by: kenwoodjw <[email protected]>
Signed-off-by: ChengZi <[email protected]>
Signed-off-by: cl <[email protected]>
Co-authored-by: Yu Chun Chang <[email protected]>
Co-authored-by: Kyle Chang <[email protected]>
Co-authored-by: Lick-liu <[email protected]>
Co-authored-by: crazywoola <[email protected]>
Co-authored-by: Yuichiro Utsumi <[email protected]>
Co-authored-by: NFish <[email protected]>
Co-authored-by: Yeuoly <[email protected]>
Co-authored-by: Wu Tianwei <[email protected]>
Co-authored-by: DDDDD12138 <[email protected]>
Co-authored-by: Jyong <[email protected]>
Co-authored-by: -LAN- <[email protected]>
Co-authored-by: Novice <[email protected]>
Co-authored-by: yihong <[email protected]>
Co-authored-by: Kalo Chin <[email protected]>
Co-authored-by: zxhlyh <[email protected]>
Co-authored-by: jiangbo721 <[email protected]>
Co-authored-by: 刘江波 <[email protected]>
Co-authored-by: Lam <[email protected]>
Co-authored-by: crazywoola <[email protected]>
Co-authored-by: Mars <[email protected]>
Co-authored-by: mars <[email protected]>
Co-authored-by: Joe <[email protected]>
Co-authored-by: Rafael Carvalho <[email protected]>
Co-authored-by: Joel <[email protected]>
Co-authored-by: 非法操作 <[email protected]>
Co-authored-by: kenwoodjw <[email protected]>
Co-authored-by: codingjaguar <[email protected]>
Co-authored-by: ChengZi <[email protected]>
Co-authored-by: Fei He <[email protected]>
Co-authored-by: Arcaner <[email protected]>
Co-authored-by: Xiyuan Chen <[email protected]>
Co-authored-by: KVOJJJin <[email protected]>
Co-authored-by: XiaoBa <[email protected]>
Co-authored-by: Xiaoba Yu <[email protected]>
Co-authored-by: zhangyuhang <[email protected]>
Co-authored-by: yuhang2.zhang <[email protected]>
Co-authored-by: 诗浓 <[email protected]>
Co-authored-by: RookieAgent <[email protected]>
Co-authored-by: sho-takano-dev <[email protected]>
Co-authored-by: 過世秋風 <[email protected]>
Co-authored-by: Yi Feng <[email protected]>
Co-authored-by: QuantumGhost <[email protected]>
Co-authored-by: Yongtao Huang <[email protected]>
Co-authored-by: ShadowJobs <[email protected]>
Co-authored-by: LinYing <[email protected]>
Co-authored-by: Benjamin <[email protected]>
Co-authored-by: LiuBodong <[email protected]>
Co-authored-by: huangzhuo1949 <[email protected]>
Co-authored-by: huangzhuo <[email protected]>
Co-authored-by: csurong <[email protected]>
Co-authored-by: 傻笑zz <[email protected]>
Co-authored-by: L8ng <[email protected]>
Co-authored-by: Bowen Liang <[email protected]>
Co-authored-by: Novice Lee <[email protected]>
Co-authored-by: GuanMu <[email protected]>
Co-authored-by: LittleFish-15 <[email protected]>
Co-authored-by: 诗浓 <[email protected]>
Co-authored-by: luckylhb90 <[email protected]>
Co-authored-by: hobo.l <[email protected]>
Co-authored-by: Gen Sato <[email protected]>
Co-authored-by: twwu <[email protected]>
Co-authored-by: StoneFancyX <[email protected]>
Co-authored-by: StoneFancyX <[email protected]>
Co-authored-by: Naoki KOBAYASHI <[email protected]>
Co-authored-by: kurokobo <[email protected]>
Co-authored-by: cyflhn <[email protected]>
Co-authored-by: Yingchun Lai <[email protected]>
Co-authored-by: jimmyfen <[email protected]>
Co-authored-by: Xuetao Song <[email protected]>
Co-authored-by: Panpan <[email protected]>
Co-authored-by: wyy-holding <[email protected]>
Co-authored-by: リイノ Lin <[email protected]>
Co-authored-by: Ning <[email protected]>
Co-authored-by: Linh Nguyen <[email protected]>
Co-authored-by: Junjie.M <[email protected]>
Co-authored-by: Ron <[email protected]>
Co-authored-by: Novice <[email protected]>
Co-authored-by: NanoNova <[email protected]>
Co-authored-by: JaydenZhou <[email protected]>
Co-authored-by: dotdotdot <[email protected]>
Co-authored-by: Good Wood <[email protected]>
Co-authored-by: Ryosei Karaki <[email protected]>
Co-authored-by: chenhuan0728 <[email protected]>
Co-authored-by: chenhuan <huan.chen0728@foxmail>
Co-authored-by: lenbo <[email protected]>
Co-authored-by: Jiang <[email protected]>
Co-authored-by: jiangzhijie <[email protected]>
Co-authored-by: Yongtao Huang <[email protected]>
Co-authored-by: zhangkun-21 <[email protected]>
Co-authored-by: hsiong <[email protected]>
Co-authored-by: 李远军 <[email protected]>
Co-authored-by: yourchanges <[email protected]>
Co-authored-by: David <[email protected]>
Co-authored-by: liuzhenghua <[email protected]>
Co-authored-by: taokuizu <[email protected]>
Co-authored-by: Hanqing Zhao <[email protected]>
Co-authored-by: JimintheBox <[email protected]>
Co-authored-by: wlleiiwang <[email protected]>
Co-authored-by: wlleiiwang <[email protected]>
Co-authored-by: Alex <[email protected]>
Co-authored-by: yuanlong <[email protected]>
Co-authored-by: wanttobeamaster <[email protected]>
Co-authored-by: xiaozhiqing.xzq <[email protected]>
Co-authored-by: Chenhe Gu <[email protected]>
Co-authored-by: tyounami <[email protected]>
Co-authored-by: bo.zhao <[email protected]>
Co-authored-by: ClSlaid <[email protected]>
Co-authored-by: adru <[email protected]>
Co-authored-by: horochx <[email protected]>
2025-04-26 04:28:30 -07:00

207 lines
8.2 KiB
Python

from typing import Optional
from core.ops.ops_trace_manager import OpsTraceManager, provider_config_map
from extensions.ext_database import db
from models.model import App, TraceAppConfig
class OpsService:
@classmethod
def get_tracing_app_config(cls, app_id: str, tracing_provider: str):
"""
Get tracing app config
:param app_id: app id
:param tracing_provider: tracing provider
:return:
"""
trace_config_data: Optional[TraceAppConfig] = (
db.session.query(TraceAppConfig)
.filter(TraceAppConfig.app_id == app_id, TraceAppConfig.tracing_provider == tracing_provider)
.first()
)
if not trace_config_data:
return None
# decrypt_token and obfuscated_token
app = db.session.query(App).filter(App.id == app_id).first()
if not app:
return None
tenant_id = app.tenant_id
decrypt_tracing_config = OpsTraceManager.decrypt_tracing_config(
tenant_id, tracing_provider, trace_config_data.tracing_config
)
new_decrypt_tracing_config = OpsTraceManager.obfuscated_decrypt_token(tracing_provider, decrypt_tracing_config)
if tracing_provider == "langfuse" and (
"project_key" not in decrypt_tracing_config or not decrypt_tracing_config.get("project_key")
):
try:
project_key = OpsTraceManager.get_trace_config_project_key(decrypt_tracing_config, tracing_provider)
new_decrypt_tracing_config.update(
{
"project_url": "{host}/project/{key}".format(
host=decrypt_tracing_config.get("host"), key=project_key
)
}
)
except Exception:
new_decrypt_tracing_config.update(
{"project_url": "{host}/".format(host=decrypt_tracing_config.get("host"))}
)
if tracing_provider == "langsmith" and (
"project_url" not in decrypt_tracing_config or not decrypt_tracing_config.get("project_url")
):
try:
project_url = OpsTraceManager.get_trace_config_project_url(decrypt_tracing_config, tracing_provider)
new_decrypt_tracing_config.update({"project_url": project_url})
except Exception:
new_decrypt_tracing_config.update({"project_url": "https://smith.langchain.com/"})
if tracing_provider == "opik" and (
"project_url" not in decrypt_tracing_config or not decrypt_tracing_config.get("project_url")
):
try:
project_url = OpsTraceManager.get_trace_config_project_url(decrypt_tracing_config, tracing_provider)
new_decrypt_tracing_config.update({"project_url": project_url})
except Exception:
new_decrypt_tracing_config.update({"project_url": "https://www.comet.com/opik/"})
if tracing_provider == "weave" and (
"project_url" not in decrypt_tracing_config or not decrypt_tracing_config.get("project_url")
):
try:
project_url = OpsTraceManager.get_trace_config_project_url(decrypt_tracing_config, tracing_provider)
new_decrypt_tracing_config.update({"project_url": project_url})
except Exception:
new_decrypt_tracing_config.update({"project_url": "https://wandb.ai/"})
trace_config_data.tracing_config = new_decrypt_tracing_config
return trace_config_data.to_dict()
@classmethod
def create_tracing_app_config(cls, app_id: str, tracing_provider: str, tracing_config: dict):
"""
Create tracing app config
:param app_id: app id
:param tracing_provider: tracing provider
:param tracing_config: tracing config
:return:
"""
if tracing_provider not in provider_config_map and tracing_provider:
return {"error": f"Invalid tracing provider: {tracing_provider}"}
config_class, other_keys = (
provider_config_map[tracing_provider]["config_class"],
provider_config_map[tracing_provider]["other_keys"],
)
# FIXME: ignore type error
default_config_instance = config_class(**tracing_config) # type: ignore
for key in other_keys: # type: ignore
if key in tracing_config and tracing_config[key] == "":
tracing_config[key] = getattr(default_config_instance, key, None)
# api check
if not OpsTraceManager.check_trace_config_is_effective(tracing_config, tracing_provider):
return {"error": "Invalid Credentials"}
# get project url
if tracing_provider == "langfuse":
project_key = OpsTraceManager.get_trace_config_project_key(tracing_config, tracing_provider)
project_url = "{host}/project/{key}".format(host=tracing_config.get("host"), key=project_key)
elif tracing_provider in ("langsmith", "opik"):
project_url = OpsTraceManager.get_trace_config_project_url(tracing_config, tracing_provider)
else:
project_url = None
# check if trace config already exists
trace_config_data: Optional[TraceAppConfig] = (
db.session.query(TraceAppConfig)
.filter(TraceAppConfig.app_id == app_id, TraceAppConfig.tracing_provider == tracing_provider)
.first()
)
if trace_config_data:
return None
# get tenant id
app = db.session.query(App).filter(App.id == app_id).first()
if not app:
return None
tenant_id = app.tenant_id
tracing_config = OpsTraceManager.encrypt_tracing_config(tenant_id, tracing_provider, tracing_config)
if project_url:
tracing_config["project_url"] = project_url
trace_config_data = TraceAppConfig(
app_id=app_id,
tracing_provider=tracing_provider,
tracing_config=tracing_config,
)
db.session.add(trace_config_data)
db.session.commit()
return {"result": "success"}
@classmethod
def update_tracing_app_config(cls, app_id: str, tracing_provider: str, tracing_config: dict):
"""
Update tracing app config
:param app_id: app id
:param tracing_provider: tracing provider
:param tracing_config: tracing config
:return:
"""
if tracing_provider not in provider_config_map:
raise ValueError(f"Invalid tracing provider: {tracing_provider}")
# check if trace config already exists
current_trace_config = (
db.session.query(TraceAppConfig)
.filter(TraceAppConfig.app_id == app_id, TraceAppConfig.tracing_provider == tracing_provider)
.first()
)
if not current_trace_config:
return None
# get tenant id
app = db.session.query(App).filter(App.id == app_id).first()
if not app:
return None
tenant_id = app.tenant_id
tracing_config = OpsTraceManager.encrypt_tracing_config(
tenant_id, tracing_provider, tracing_config, current_trace_config.tracing_config
)
# api check
# decrypt_token
decrypt_tracing_config = OpsTraceManager.decrypt_tracing_config(tenant_id, tracing_provider, tracing_config)
if not OpsTraceManager.check_trace_config_is_effective(decrypt_tracing_config, tracing_provider):
raise ValueError("Invalid Credentials")
current_trace_config.tracing_config = tracing_config
db.session.commit()
return current_trace_config.to_dict()
@classmethod
def delete_tracing_app_config(cls, app_id: str, tracing_provider: str):
"""
Delete tracing app config
:param app_id: app id
:param tracing_provider: tracing provider
:return:
"""
trace_config = (
db.session.query(TraceAppConfig)
.filter(TraceAppConfig.app_id == app_id, TraceAppConfig.tracing_provider == tracing_provider)
.first()
)
if not trace_config:
return None
db.session.delete(trace_config)
db.session.commit()
return True