Signed-off-by: Yuichiro Utsumi <utsumi.yuichiro@fujitsu.com> Signed-off-by: -LAN- <laipz8200@outlook.com> Signed-off-by: yihong0618 <zouzou0208@gmail.com> Signed-off-by: kenwoodjw <blackxin55+@gmail.com> Signed-off-by: ChengZi <chen.zhang@zilliz.com> Signed-off-by: cl <cailue@apache.org> Co-authored-by: Yu Chun Chang <changyuchun159630@gmail.com> Co-authored-by: Kyle Chang <kylechang@91app.com> Co-authored-by: Lick-liu <51771897+Lick-liu@users.noreply.github.com> Co-authored-by: crazywoola <427733928@qq.com> Co-authored-by: Yuichiro Utsumi <81412151+utsumi-fj@users.noreply.github.com> Co-authored-by: NFish <douxc512@gmail.com> Co-authored-by: Yeuoly <45712896+Yeuoly@users.noreply.github.com> Co-authored-by: Wu Tianwei <30284043+WTW0313@users.noreply.github.com> Co-authored-by: DDDDD12138 <43703884+DDDDD12138@users.noreply.github.com> Co-authored-by: Jyong <76649700+JohnJyong@users.noreply.github.com> Co-authored-by: -LAN- <laipz8200@outlook.com> Co-authored-by: Novice <857526207@qq.com> Co-authored-by: yihong <zouzou0208@gmail.com> Co-authored-by: Kalo Chin <91766386+fdb02983rhy@users.noreply.github.com> Co-authored-by: zxhlyh <jasonapring2015@outlook.com> Co-authored-by: jiangbo721 <365065261@qq.com> Co-authored-by: 刘江波 <jiangbo721@163.com> Co-authored-by: Lam <scau_ljw@126.com> Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> Co-authored-by: Mars <524574386@qq.com> Co-authored-by: mars <linjx2@by-health.com> Co-authored-by: Joe <79627742+ZhouhaoJiang@users.noreply.github.com> Co-authored-by: Rafael Carvalho <r.carvalho@me.com> Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: 非法操作 <hjlarry@163.com> Co-authored-by: kenwoodjw <blackxin55+@gmail.com> Co-authored-by: codingjaguar <codingjaguar@gmail.com> Co-authored-by: ChengZi <chen.zhang@zilliz.com> Co-authored-by: Fei He <droxer.he@gmail.com> Co-authored-by: Arcaner <52057416+lrhan321@users.noreply.github.com> Co-authored-by: Xiyuan Chen <52963600+GareArc@users.noreply.github.com> Co-authored-by: KVOJJJin <jzongcode@gmail.com> Co-authored-by: XiaoBa <94062266+XiaoBa-Yu@users.noreply.github.com> Co-authored-by: Xiaoba Yu <xb1823725853@gmail.com> Co-authored-by: zhangyuhang <2827528315@qq.com> Co-authored-by: yuhang2.zhang <yuhang2.zhang@ly.com> Co-authored-by: 诗浓 <nyaashino@gmail.com> Co-authored-by: RookieAgent <42060616+Sakura4036@users.noreply.github.com> Co-authored-by: sho-takano-dev <shota.takano.dev@gmail.com> Co-authored-by: 過世秋風 <1040926235@qq.com> Co-authored-by: Yi Feng <66539215+bigyifeng@users.noreply.github.com> Co-authored-by: QuantumGhost <obelisk.reg+git@gmail.com> Co-authored-by: Yongtao Huang <99629139+hyongtao-db@users.noreply.github.com> Co-authored-by: ShadowJobs <794878115@qq.com> Co-authored-by: LinYing <linying@momenta.ai> Co-authored-by: Benjamin <benjaminx@gmail.com> Co-authored-by: LiuBodong <liubodong2010@126.com> Co-authored-by: huangzhuo1949 <167434202+huangzhuo1949@users.noreply.github.com> Co-authored-by: huangzhuo <huangzhuo1@xiaomi.com> Co-authored-by: csurong <csurong1@gmail.com> Co-authored-by: 傻笑zz <43721571+shaxiaozz@users.noreply.github.com> Co-authored-by: L8ng <straydragonl@foxmail.com> Co-authored-by: Bowen Liang <liangbowen@gf.com.cn> Co-authored-by: Novice Lee <novicelee@NoviPro.local> Co-authored-by: GuanMu <ballmanjq@gmail.com> Co-authored-by: LittleFish-15 <58618983+LittleFish-15@users.noreply.github.com> Co-authored-by: 诗浓 <844670992@qq.com> Co-authored-by: luckylhb90 <luckylhb90@gmail.com> Co-authored-by: hobo.l <hobo.l@binance.com> Co-authored-by: Gen Sato <52241300+halogen22@users.noreply.github.com> Co-authored-by: twwu <twwu@dify.ai> Co-authored-by: StoneFancyX <53338920+StoneFancyX@users.noreply.github.com> Co-authored-by: StoneFancyX <kindbin@qq.com> Co-authored-by: Naoki KOBAYASHI <naotama@gmail.com> Co-authored-by: kurokobo <kuro664@gmail.com> Co-authored-by: cyflhn <cyflhn@163.com> Co-authored-by: Yingchun Lai <laiyingchun@apache.org> Co-authored-by: jimmyfen <757343258@qq.com> Co-authored-by: Xuetao Song <xuetaomagicsong@gmail.com> Co-authored-by: Panpan <wurui.dev@gmail.com> Co-authored-by: wyy-holding <59436937+wyy-holding@users.noreply.github.com> Co-authored-by: リイノ Lin <sorphwer@gmail.com> Co-authored-by: Ning <accelerator314@gmail.com> Co-authored-by: Linh Nguyen <55907715+batman0911@users.noreply.github.com> Co-authored-by: Junjie.M <118170653@qq.com> Co-authored-by: Ron <svcvit@gmail.com> Co-authored-by: Novice <novice12185727@gmail.com> Co-authored-by: NanoNova <kid1412621@gmail.com> Co-authored-by: JaydenZhou <380774082@qq.com> Co-authored-by: dotdotdot <823150982@qq.com> Co-authored-by: Good Wood <slm_1990@126.com> Co-authored-by: Ryosei Karaki <38310693+karamaru-alpha@users.noreply.github.com> Co-authored-by: chenhuan0728 <54611342+chenhuan0728@users.noreply.github.com> Co-authored-by: chenhuan <huan.chen0728@foxmail> Co-authored-by: lenbo <islenbo@qq.com> Co-authored-by: Jiang <65766008+AlwaysBluer@users.noreply.github.com> Co-authored-by: jiangzhijie <jiangzhijie.jzj@alibaba-inc.com> Co-authored-by: Yongtao Huang <yongtaoh2022@gmail.com> Co-authored-by: zhangkun-21 <sephiroth0932@gmail.com> Co-authored-by: hsiong <37357447+hsiong@users.noreply.github.com> Co-authored-by: 李远军 <4842@9ji.com> Co-authored-by: yourchanges <yourchanges@gmail.com> Co-authored-by: David <guyuezhuying@126.com> Co-authored-by: liuzhenghua <1090179900@qq.com> Co-authored-by: taokuizu <taokuizu@qq.com> Co-authored-by: Hanqing Zhao <sherry9277@gmail.com> Co-authored-by: JimintheBox <gjwlals111@gmail.com> Co-authored-by: wlleiiwang <1025164922@qq.com> Co-authored-by: wlleiiwang <wlleiiwang@tencent.com> Co-authored-by: Alex <32982705+AlexYuan997@users.noreply.github.com> Co-authored-by: yuanlong <yuanlong@boco.com.cn> Co-authored-by: wanttobeamaster <45583625+wanttobeamaster@users.noreply.github.com> Co-authored-by: xiaozhiqing.xzq <xiaozhiqing.xzq@alibaba-inc.com> Co-authored-by: Chenhe Gu <guchenhe@gmail.com> Co-authored-by: tyounami <vkbo@qq.com> Co-authored-by: bo.zhao <bo.zhao@iglooinsure.com> Co-authored-by: ClSlaid <cailue@apache.org> Co-authored-by: adru <106513264+adpanru@users.noreply.github.com> Co-authored-by: horochx <32632779+horochx@users.noreply.github.com>tags/1.3.1
| LANGFUSE = "langfuse" | LANGFUSE = "langfuse" | ||||
| LANGSMITH = "langsmith" | LANGSMITH = "langsmith" | ||||
| OPIK = "opik" | OPIK = "opik" | ||||
| WEAVE = "weave" | |||||
| class BaseTracingConfig(BaseModel): | class BaseTracingConfig(BaseModel): | ||||
| return v | return v | ||||
| class WeaveConfig(BaseTracingConfig): | |||||
| """ | |||||
| Model class for Weave tracing config. | |||||
| """ | |||||
| api_key: str | |||||
| entity: str | None = None | |||||
| project: str | |||||
| endpoint: str = "https://trace.wandb.ai" | |||||
| @field_validator("endpoint") | |||||
| @classmethod | |||||
| def set_value(cls, v, info: ValidationInfo): | |||||
| if v is None or v == "": | |||||
| v = "https://trace.wandb.ai" | |||||
| if not v.startswith("https://"): | |||||
| raise ValueError("endpoint must start with https://") | |||||
| return v | |||||
| OPS_FILE_PATH = "ops_trace/" | OPS_FILE_PATH = "ops_trace/" | ||||
| OPS_TRACE_FAILED_KEY = "FAILED_OPS_TRACE" | OPS_TRACE_FAILED_KEY = "FAILED_OPS_TRACE" |
| LangSmithConfig, | LangSmithConfig, | ||||
| OpikConfig, | OpikConfig, | ||||
| TracingProviderEnum, | TracingProviderEnum, | ||||
| WeaveConfig, | |||||
| ) | ) | ||||
| from core.ops.entities.trace_entity import ( | from core.ops.entities.trace_entity import ( | ||||
| DatasetRetrievalTraceInfo, | DatasetRetrievalTraceInfo, | ||||
| ) | ) | ||||
| from core.ops.langfuse_trace.langfuse_trace import LangFuseDataTrace | from core.ops.langfuse_trace.langfuse_trace import LangFuseDataTrace | ||||
| from core.ops.langsmith_trace.langsmith_trace import LangSmithDataTrace | from core.ops.langsmith_trace.langsmith_trace import LangSmithDataTrace | ||||
| from core.ops.opik_trace.opik_trace import OpikDataTrace | |||||
| from core.ops.utils import get_message_data | from core.ops.utils import get_message_data | ||||
| from core.ops.weave_trace.weave_trace import WeaveDataTrace | |||||
| from extensions.ext_database import db | from extensions.ext_database import db | ||||
| from extensions.ext_storage import storage | from extensions.ext_storage import storage | ||||
| from models.model import App, AppModelConfig, Conversation, Message, MessageFile, TraceAppConfig | from models.model import App, AppModelConfig, Conversation, Message, MessageFile, TraceAppConfig | ||||
| def build_opik_trace_instance(config: OpikConfig): | def build_opik_trace_instance(config: OpikConfig): | ||||
| from core.ops.opik_trace.opik_trace import OpikDataTrace | |||||
| return OpikDataTrace(config) | return OpikDataTrace(config) | ||||
| "other_keys": ["project", "url", "workspace"], | "other_keys": ["project", "url", "workspace"], | ||||
| "trace_instance": lambda config: build_opik_trace_instance(config), | "trace_instance": lambda config: build_opik_trace_instance(config), | ||||
| }, | }, | ||||
| TracingProviderEnum.WEAVE.value: { | |||||
| "config_class": WeaveConfig, | |||||
| "secret_keys": ["api_key"], | |||||
| "other_keys": ["project", "entity", "endpoint"], | |||||
| "trace_instance": WeaveDataTrace, | |||||
| }, | |||||
| } | } | ||||
| from typing import Any, Optional, Union | |||||
| from pydantic import BaseModel, Field, field_validator | |||||
| from pydantic_core.core_schema import ValidationInfo | |||||
| from core.ops.utils import replace_text_with_content | |||||
| class WeaveTokenUsage(BaseModel): | |||||
| input_tokens: Optional[int] = None | |||||
| output_tokens: Optional[int] = None | |||||
| total_tokens: Optional[int] = None | |||||
| class WeaveMultiModel(BaseModel): | |||||
| file_list: Optional[list[str]] = Field(None, description="List of files") | |||||
| class WeaveTraceModel(WeaveTokenUsage, WeaveMultiModel): | |||||
| id: str = Field(..., description="ID of the trace") | |||||
| op: str = Field(..., description="Name of the operation") | |||||
| inputs: Optional[Union[str, dict[str, Any], list, None]] = Field(None, description="Inputs of the trace") | |||||
| outputs: Optional[Union[str, dict[str, Any], list, None]] = Field(None, description="Outputs of the trace") | |||||
| attributes: Optional[Union[str, dict[str, Any], list, None]] = Field( | |||||
| None, description="Metadata and attributes associated with trace" | |||||
| ) | |||||
| exception: Optional[str] = Field(None, description="Exception message of the trace") | |||||
| @field_validator("inputs", "outputs") | |||||
| @classmethod | |||||
| def ensure_dict(cls, v, info: ValidationInfo): | |||||
| field_name = info.field_name | |||||
| values = info.data | |||||
| if v == {} or v is None: | |||||
| return v | |||||
| usage_metadata = { | |||||
| "input_tokens": values.get("input_tokens", 0), | |||||
| "output_tokens": values.get("output_tokens", 0), | |||||
| "total_tokens": values.get("total_tokens", 0), | |||||
| } | |||||
| file_list = values.get("file_list", []) | |||||
| if isinstance(v, str): | |||||
| if field_name == "inputs": | |||||
| return { | |||||
| "messages": { | |||||
| "role": "user", | |||||
| "content": v, | |||||
| "usage_metadata": usage_metadata, | |||||
| "file_list": file_list, | |||||
| }, | |||||
| } | |||||
| elif field_name == "outputs": | |||||
| return { | |||||
| "choices": { | |||||
| "role": "ai", | |||||
| "content": v, | |||||
| "usage_metadata": usage_metadata, | |||||
| "file_list": file_list, | |||||
| }, | |||||
| } | |||||
| elif isinstance(v, list): | |||||
| data = {} | |||||
| if len(v) > 0 and isinstance(v[0], dict): | |||||
| # rename text to content | |||||
| v = replace_text_with_content(data=v) | |||||
| if field_name == "inputs": | |||||
| data = { | |||||
| "messages": [ | |||||
| dict(msg, **{"usage_metadata": usage_metadata, "file_list": file_list}) for msg in v | |||||
| ] | |||||
| if isinstance(v, list) | |||||
| else v, | |||||
| } | |||||
| elif field_name == "outputs": | |||||
| data = { | |||||
| "choices": { | |||||
| "role": "ai", | |||||
| "content": v, | |||||
| "usage_metadata": usage_metadata, | |||||
| "file_list": file_list, | |||||
| }, | |||||
| } | |||||
| return data | |||||
| else: | |||||
| return { | |||||
| "choices": { | |||||
| "role": "ai" if field_name == "outputs" else "user", | |||||
| "content": str(v), | |||||
| "usage_metadata": usage_metadata, | |||||
| "file_list": file_list, | |||||
| }, | |||||
| } | |||||
| if isinstance(v, dict): | |||||
| v["usage_metadata"] = usage_metadata | |||||
| v["file_list"] = file_list | |||||
| return v | |||||
| return v |
| import json | |||||
| import logging | |||||
| import os | |||||
| import uuid | |||||
| from datetime import datetime, timedelta | |||||
| from typing import Any, Optional, cast | |||||
| import wandb | |||||
| import weave | |||||
| from core.ops.base_trace_instance import BaseTraceInstance | |||||
| from core.ops.entities.config_entity import WeaveConfig | |||||
| from core.ops.entities.trace_entity import ( | |||||
| BaseTraceInfo, | |||||
| DatasetRetrievalTraceInfo, | |||||
| GenerateNameTraceInfo, | |||||
| MessageTraceInfo, | |||||
| ModerationTraceInfo, | |||||
| SuggestedQuestionTraceInfo, | |||||
| ToolTraceInfo, | |||||
| TraceTaskName, | |||||
| WorkflowTraceInfo, | |||||
| ) | |||||
| from core.ops.weave_trace.entities.weave_trace_entity import WeaveTraceModel | |||||
| from extensions.ext_database import db | |||||
| from models.model import EndUser, MessageFile | |||||
| from models.workflow import WorkflowNodeExecution | |||||
| logger = logging.getLogger(__name__) | |||||
| class WeaveDataTrace(BaseTraceInstance): | |||||
| def __init__( | |||||
| self, | |||||
| weave_config: WeaveConfig, | |||||
| ): | |||||
| super().__init__(weave_config) | |||||
| self.weave_api_key = weave_config.api_key | |||||
| self.project_name = weave_config.project | |||||
| self.entity = weave_config.entity | |||||
| # Login with API key first | |||||
| login_status = wandb.login(key=self.weave_api_key, verify=True, relogin=True) | |||||
| if not login_status: | |||||
| logger.error("Failed to login to Weights & Biases with the provided API key") | |||||
| raise ValueError("Weave login failed") | |||||
| # Then initialize weave client | |||||
| self.weave_client = weave.init( | |||||
| project_name=(f"{self.entity}/{self.project_name}" if self.entity else self.project_name) | |||||
| ) | |||||
| self.file_base_url = os.getenv("FILES_URL", "http://127.0.0.1:5001") | |||||
| self.calls: dict[str, Any] = {} | |||||
| def get_project_url( | |||||
| self, | |||||
| ): | |||||
| try: | |||||
| project_url = f"https://wandb.ai/{self.weave_client._project_id()}" | |||||
| return project_url | |||||
| except Exception as e: | |||||
| logger.debug(f"Weave get run url failed: {str(e)}") | |||||
| raise ValueError(f"Weave get run url failed: {str(e)}") | |||||
| def trace(self, trace_info: BaseTraceInfo): | |||||
| logger.debug(f"Trace info: {trace_info}") | |||||
| if isinstance(trace_info, WorkflowTraceInfo): | |||||
| self.workflow_trace(trace_info) | |||||
| if isinstance(trace_info, MessageTraceInfo): | |||||
| self.message_trace(trace_info) | |||||
| if isinstance(trace_info, ModerationTraceInfo): | |||||
| self.moderation_trace(trace_info) | |||||
| if isinstance(trace_info, SuggestedQuestionTraceInfo): | |||||
| self.suggested_question_trace(trace_info) | |||||
| if isinstance(trace_info, DatasetRetrievalTraceInfo): | |||||
| self.dataset_retrieval_trace(trace_info) | |||||
| if isinstance(trace_info, ToolTraceInfo): | |||||
| self.tool_trace(trace_info) | |||||
| if isinstance(trace_info, GenerateNameTraceInfo): | |||||
| self.generate_name_trace(trace_info) | |||||
| def workflow_trace(self, trace_info: WorkflowTraceInfo): | |||||
| trace_id = trace_info.message_id or trace_info.workflow_run_id | |||||
| if trace_info.start_time is None: | |||||
| trace_info.start_time = datetime.now() | |||||
| if trace_info.message_id: | |||||
| message_attributes = trace_info.metadata | |||||
| message_attributes["workflow_app_log_id"] = trace_info.workflow_app_log_id | |||||
| message_attributes["message_id"] = trace_info.message_id | |||||
| message_attributes["workflow_run_id"] = trace_info.workflow_run_id | |||||
| message_attributes["trace_id"] = trace_id | |||||
| message_attributes["start_time"] = trace_info.start_time | |||||
| message_attributes["end_time"] = trace_info.end_time | |||||
| message_attributes["tags"] = ["message", "workflow"] | |||||
| message_run = WeaveTraceModel( | |||||
| id=trace_info.message_id, | |||||
| op=str(TraceTaskName.MESSAGE_TRACE.value), | |||||
| inputs=dict(trace_info.workflow_run_inputs), | |||||
| outputs=dict(trace_info.workflow_run_outputs), | |||||
| total_tokens=trace_info.total_tokens, | |||||
| attributes=message_attributes, | |||||
| exception=trace_info.error, | |||||
| file_list=[], | |||||
| ) | |||||
| self.start_call(message_run, parent_run_id=trace_info.workflow_run_id) | |||||
| self.finish_call(message_run) | |||||
| workflow_attributes = trace_info.metadata | |||||
| workflow_attributes["workflow_run_id"] = trace_info.workflow_run_id | |||||
| workflow_attributes["trace_id"] = trace_id | |||||
| workflow_attributes["start_time"] = trace_info.start_time | |||||
| workflow_attributes["end_time"] = trace_info.end_time | |||||
| workflow_attributes["tags"] = ["workflow"] | |||||
| workflow_run = WeaveTraceModel( | |||||
| file_list=trace_info.file_list, | |||||
| total_tokens=trace_info.total_tokens, | |||||
| id=trace_info.workflow_run_id, | |||||
| op=str(TraceTaskName.WORKFLOW_TRACE.value), | |||||
| inputs=dict(trace_info.workflow_run_inputs), | |||||
| outputs=dict(trace_info.workflow_run_outputs), | |||||
| attributes=workflow_attributes, | |||||
| exception=trace_info.error, | |||||
| ) | |||||
| self.start_call(workflow_run, parent_run_id=trace_info.message_id) | |||||
| # through workflow_run_id get all_nodes_execution | |||||
| workflow_nodes_execution_id_records = ( | |||||
| db.session.query(WorkflowNodeExecution.id) | |||||
| .filter(WorkflowNodeExecution.workflow_run_id == trace_info.workflow_run_id) | |||||
| .all() | |||||
| ) | |||||
| for node_execution_id_record in workflow_nodes_execution_id_records: | |||||
| node_execution = ( | |||||
| db.session.query( | |||||
| WorkflowNodeExecution.id, | |||||
| WorkflowNodeExecution.tenant_id, | |||||
| WorkflowNodeExecution.app_id, | |||||
| WorkflowNodeExecution.title, | |||||
| WorkflowNodeExecution.node_type, | |||||
| WorkflowNodeExecution.status, | |||||
| WorkflowNodeExecution.inputs, | |||||
| WorkflowNodeExecution.outputs, | |||||
| WorkflowNodeExecution.created_at, | |||||
| WorkflowNodeExecution.elapsed_time, | |||||
| WorkflowNodeExecution.process_data, | |||||
| WorkflowNodeExecution.execution_metadata, | |||||
| ) | |||||
| .filter(WorkflowNodeExecution.id == node_execution_id_record.id) | |||||
| .first() | |||||
| ) | |||||
| if not node_execution: | |||||
| continue | |||||
| node_execution_id = node_execution.id | |||||
| tenant_id = node_execution.tenant_id | |||||
| app_id = node_execution.app_id | |||||
| node_name = node_execution.title | |||||
| node_type = node_execution.node_type | |||||
| status = node_execution.status | |||||
| if node_type == "llm": | |||||
| inputs = ( | |||||
| json.loads(node_execution.process_data).get("prompts", {}) if node_execution.process_data else {} | |||||
| ) | |||||
| else: | |||||
| inputs = json.loads(node_execution.inputs) if node_execution.inputs else {} | |||||
| outputs = json.loads(node_execution.outputs) if node_execution.outputs else {} | |||||
| created_at = node_execution.created_at or datetime.now() | |||||
| elapsed_time = node_execution.elapsed_time | |||||
| finished_at = created_at + timedelta(seconds=elapsed_time) | |||||
| execution_metadata = ( | |||||
| json.loads(node_execution.execution_metadata) if node_execution.execution_metadata else {} | |||||
| ) | |||||
| node_total_tokens = execution_metadata.get("total_tokens", 0) | |||||
| attributes = execution_metadata.copy() | |||||
| attributes.update( | |||||
| { | |||||
| "workflow_run_id": trace_info.workflow_run_id, | |||||
| "node_execution_id": node_execution_id, | |||||
| "tenant_id": tenant_id, | |||||
| "app_id": app_id, | |||||
| "app_name": node_name, | |||||
| "node_type": node_type, | |||||
| "status": status, | |||||
| } | |||||
| ) | |||||
| process_data = json.loads(node_execution.process_data) if node_execution.process_data else {} | |||||
| if process_data and process_data.get("model_mode") == "chat": | |||||
| attributes.update( | |||||
| { | |||||
| "ls_provider": process_data.get("model_provider", ""), | |||||
| "ls_model_name": process_data.get("model_name", ""), | |||||
| } | |||||
| ) | |||||
| attributes["tags"] = ["node_execution"] | |||||
| attributes["start_time"] = created_at | |||||
| attributes["end_time"] = finished_at | |||||
| attributes["elapsed_time"] = elapsed_time | |||||
| attributes["workflow_run_id"] = trace_info.workflow_run_id | |||||
| attributes["trace_id"] = trace_id | |||||
| node_run = WeaveTraceModel( | |||||
| total_tokens=node_total_tokens, | |||||
| op=node_type, | |||||
| inputs=inputs, | |||||
| outputs=outputs, | |||||
| file_list=trace_info.file_list, | |||||
| attributes=attributes, | |||||
| id=node_execution_id, | |||||
| exception=None, | |||||
| ) | |||||
| self.start_call(node_run, parent_run_id=trace_info.workflow_run_id) | |||||
| self.finish_call(node_run) | |||||
| self.finish_call(workflow_run) | |||||
| def message_trace(self, trace_info: MessageTraceInfo): | |||||
| # get message file data | |||||
| file_list = cast(list[str], trace_info.file_list) or [] | |||||
| message_file_data: Optional[MessageFile] = trace_info.message_file_data | |||||
| file_url = f"{self.file_base_url}/{message_file_data.url}" if message_file_data else "" | |||||
| file_list.append(file_url) | |||||
| attributes = trace_info.metadata | |||||
| message_data = trace_info.message_data | |||||
| if message_data is None: | |||||
| return | |||||
| message_id = message_data.id | |||||
| user_id = message_data.from_account_id | |||||
| attributes["user_id"] = user_id | |||||
| if message_data.from_end_user_id: | |||||
| end_user_data: Optional[EndUser] = ( | |||||
| db.session.query(EndUser).filter(EndUser.id == message_data.from_end_user_id).first() | |||||
| ) | |||||
| if end_user_data is not None: | |||||
| end_user_id = end_user_data.session_id | |||||
| attributes["end_user_id"] = end_user_id | |||||
| attributes["message_id"] = message_id | |||||
| attributes["start_time"] = trace_info.start_time | |||||
| attributes["end_time"] = trace_info.end_time | |||||
| attributes["tags"] = ["message", str(trace_info.conversation_mode)] | |||||
| message_run = WeaveTraceModel( | |||||
| id=message_id, | |||||
| op=str(TraceTaskName.MESSAGE_TRACE.value), | |||||
| input_tokens=trace_info.message_tokens, | |||||
| output_tokens=trace_info.answer_tokens, | |||||
| total_tokens=trace_info.total_tokens, | |||||
| inputs=trace_info.inputs, | |||||
| outputs=trace_info.outputs, | |||||
| exception=trace_info.error, | |||||
| file_list=file_list, | |||||
| attributes=attributes, | |||||
| ) | |||||
| self.start_call(message_run) | |||||
| # create llm run parented to message run | |||||
| llm_run = WeaveTraceModel( | |||||
| id=str(uuid.uuid4()), | |||||
| input_tokens=trace_info.message_tokens, | |||||
| output_tokens=trace_info.answer_tokens, | |||||
| total_tokens=trace_info.total_tokens, | |||||
| op="llm", | |||||
| inputs=trace_info.inputs, | |||||
| outputs=trace_info.outputs, | |||||
| attributes=attributes, | |||||
| file_list=[], | |||||
| exception=None, | |||||
| ) | |||||
| self.start_call( | |||||
| llm_run, | |||||
| parent_run_id=message_id, | |||||
| ) | |||||
| self.finish_call(llm_run) | |||||
| self.finish_call(message_run) | |||||
| def moderation_trace(self, trace_info: ModerationTraceInfo): | |||||
| if trace_info.message_data is None: | |||||
| return | |||||
| attributes = trace_info.metadata | |||||
| attributes["tags"] = ["moderation"] | |||||
| attributes["message_id"] = trace_info.message_id | |||||
| attributes["start_time"] = trace_info.start_time or trace_info.message_data.created_at | |||||
| attributes["end_time"] = trace_info.end_time or trace_info.message_data.updated_at | |||||
| moderation_run = WeaveTraceModel( | |||||
| id=str(uuid.uuid4()), | |||||
| op=str(TraceTaskName.MODERATION_TRACE.value), | |||||
| inputs=trace_info.inputs, | |||||
| outputs={ | |||||
| "action": trace_info.action, | |||||
| "flagged": trace_info.flagged, | |||||
| "preset_response": trace_info.preset_response, | |||||
| "inputs": trace_info.inputs, | |||||
| }, | |||||
| attributes=attributes, | |||||
| exception=getattr(trace_info, "error", None), | |||||
| file_list=[], | |||||
| ) | |||||
| self.start_call(moderation_run, parent_run_id=trace_info.message_id) | |||||
| self.finish_call(moderation_run) | |||||
| def suggested_question_trace(self, trace_info: SuggestedQuestionTraceInfo): | |||||
| message_data = trace_info.message_data | |||||
| if message_data is None: | |||||
| return | |||||
| attributes = trace_info.metadata | |||||
| attributes["message_id"] = trace_info.message_id | |||||
| attributes["tags"] = ["suggested_question"] | |||||
| attributes["start_time"] = (trace_info.start_time or message_data.created_at,) | |||||
| attributes["end_time"] = (trace_info.end_time or message_data.updated_at,) | |||||
| suggested_question_run = WeaveTraceModel( | |||||
| id=str(uuid.uuid4()), | |||||
| op=str(TraceTaskName.SUGGESTED_QUESTION_TRACE.value), | |||||
| inputs=trace_info.inputs, | |||||
| outputs=trace_info.suggested_question, | |||||
| attributes=attributes, | |||||
| exception=trace_info.error, | |||||
| file_list=[], | |||||
| ) | |||||
| self.start_call(suggested_question_run, parent_run_id=trace_info.message_id) | |||||
| self.finish_call(suggested_question_run) | |||||
| def dataset_retrieval_trace(self, trace_info: DatasetRetrievalTraceInfo): | |||||
| if trace_info.message_data is None: | |||||
| return | |||||
| attributes = trace_info.metadata | |||||
| attributes["message_id"] = trace_info.message_id | |||||
| attributes["tags"] = ["dataset_retrieval"] | |||||
| attributes["start_time"] = (trace_info.start_time or trace_info.message_data.created_at,) | |||||
| attributes["end_time"] = (trace_info.end_time or trace_info.message_data.updated_at,) | |||||
| dataset_retrieval_run = WeaveTraceModel( | |||||
| id=str(uuid.uuid4()), | |||||
| op=str(TraceTaskName.DATASET_RETRIEVAL_TRACE.value), | |||||
| inputs=trace_info.inputs, | |||||
| outputs={"documents": trace_info.documents}, | |||||
| attributes=attributes, | |||||
| exception=getattr(trace_info, "error", None), | |||||
| file_list=[], | |||||
| ) | |||||
| self.start_call(dataset_retrieval_run, parent_run_id=trace_info.message_id) | |||||
| self.finish_call(dataset_retrieval_run) | |||||
| def tool_trace(self, trace_info: ToolTraceInfo): | |||||
| attributes = trace_info.metadata | |||||
| attributes["tags"] = ["tool", trace_info.tool_name] | |||||
| attributes["start_time"] = trace_info.start_time | |||||
| attributes["end_time"] = trace_info.end_time | |||||
| tool_run = WeaveTraceModel( | |||||
| id=str(uuid.uuid4()), | |||||
| op=trace_info.tool_name, | |||||
| inputs=trace_info.tool_inputs, | |||||
| outputs=trace_info.tool_outputs, | |||||
| file_list=[cast(str, trace_info.file_url)] if trace_info.file_url else [], | |||||
| attributes=attributes, | |||||
| exception=trace_info.error, | |||||
| ) | |||||
| message_id = trace_info.message_id or getattr(trace_info, "conversation_id", None) | |||||
| message_id = message_id or None | |||||
| self.start_call(tool_run, parent_run_id=message_id) | |||||
| self.finish_call(tool_run) | |||||
| def generate_name_trace(self, trace_info: GenerateNameTraceInfo): | |||||
| attributes = trace_info.metadata | |||||
| attributes["tags"] = ["generate_name"] | |||||
| attributes["start_time"] = trace_info.start_time | |||||
| attributes["end_time"] = trace_info.end_time | |||||
| name_run = WeaveTraceModel( | |||||
| id=str(uuid.uuid4()), | |||||
| op=str(TraceTaskName.GENERATE_NAME_TRACE.value), | |||||
| inputs=trace_info.inputs, | |||||
| outputs=trace_info.outputs, | |||||
| attributes=attributes, | |||||
| exception=getattr(trace_info, "error", None), | |||||
| file_list=[], | |||||
| ) | |||||
| self.start_call(name_run) | |||||
| self.finish_call(name_run) | |||||
| def api_check(self): | |||||
| try: | |||||
| login_status = wandb.login(key=self.weave_api_key, verify=True, relogin=True) | |||||
| if not login_status: | |||||
| raise ValueError("Weave login failed") | |||||
| else: | |||||
| print("Weave login successful") | |||||
| return True | |||||
| except Exception as e: | |||||
| logger.debug(f"Weave API check failed: {str(e)}") | |||||
| raise ValueError(f"Weave API check failed: {str(e)}") | |||||
| def start_call(self, run_data: WeaveTraceModel, parent_run_id: Optional[str] = None): | |||||
| call = self.weave_client.create_call(op=run_data.op, inputs=run_data.inputs, attributes=run_data.attributes) | |||||
| self.calls[run_data.id] = call | |||||
| if parent_run_id: | |||||
| self.calls[run_data.id].parent_id = parent_run_id | |||||
| def finish_call(self, run_data: WeaveTraceModel): | |||||
| call = self.calls.get(run_data.id) | |||||
| if call: | |||||
| self.weave_client.finish_call(call=call, output=run_data.outputs, exception=run_data.exception) | |||||
| else: | |||||
| raise ValueError(f"Call with id {run_data.id} not found") |
| "transformers~=4.35.0", | "transformers~=4.35.0", | ||||
| "unstructured[docx,epub,md,ppt,pptx]~=0.16.1", | "unstructured[docx,epub,md,ppt,pptx]~=0.16.1", | ||||
| "validators==0.21.0", | "validators==0.21.0", | ||||
| "weave~=0.51.34", | |||||
| "yarl~=1.18.3", | "yarl~=1.18.3", | ||||
| ] | ] | ||||
| # Before adding new dependency, consider place it in | # Before adding new dependency, consider place it in |
| new_decrypt_tracing_config.update({"project_url": project_url}) | new_decrypt_tracing_config.update({"project_url": project_url}) | ||||
| except Exception: | except Exception: | ||||
| new_decrypt_tracing_config.update({"project_url": "https://www.comet.com/opik/"}) | 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 | trace_config_data.tracing_config = new_decrypt_tracing_config | ||||
| return trace_config_data.to_dict() | return trace_config_data.to_dict() | ||||
| trace_info = trace_type(**trace_info) | trace_info = trace_type(**trace_info) | ||||
| trace_instance.trace(trace_info) | trace_instance.trace(trace_info) | ||||
| logging.info(f"Processing trace tasks success, app_id: {app_id}") | logging.info(f"Processing trace tasks success, app_id: {app_id}") | ||||
| except Exception: | |||||
| except Exception as e: | |||||
| logging.info( | |||||
| f"error:\n\n\n{e}\n\n\n\n", | |||||
| ) | |||||
| failed_key = f"{OPS_TRACE_FAILED_KEY}_{app_id}" | failed_key = f"{OPS_TRACE_FAILED_KEY}_{app_id}" | ||||
| redis_client.incr(failed_key) | redis_client.incr(failed_key) | ||||
| logging.info(f"Processing trace tasks failed, app_id: {app_id}") | logging.info(f"Processing trace tasks failed, app_id: {app_id}") |
| version = 1 | version = 1 | ||||
| revision = 1 | |||||
| requires-python = ">=3.11, <3.13" | requires-python = ">=3.11, <3.13" | ||||
| resolution-markers = [ | resolution-markers = [ | ||||
| "python_full_version >= '3.12.4' and platform_python_implementation != 'PyPy'", | |||||
| "python_full_version >= '3.12' and python_full_version < '3.12.4' and platform_python_implementation != 'PyPy'", | |||||
| "python_full_version >= '3.12.4' and platform_python_implementation == 'PyPy'", | |||||
| "python_full_version >= '3.12' and python_full_version < '3.12.4' and platform_python_implementation == 'PyPy'", | |||||
| "python_full_version < '3.12' and platform_python_implementation != 'PyPy'", | |||||
| "python_full_version < '3.12' and platform_python_implementation == 'PyPy'", | |||||
| "python_full_version >= '3.12.4' and platform_python_implementation != 'PyPy' and sys_platform == 'linux'", | |||||
| "python_full_version >= '3.12.4' and platform_python_implementation != 'PyPy' and sys_platform != 'linux'", | |||||
| "python_full_version >= '3.12' and python_full_version < '3.12.4' and platform_python_implementation != 'PyPy' and sys_platform == 'linux'", | |||||
| "python_full_version >= '3.12' and python_full_version < '3.12.4' and platform_python_implementation != 'PyPy' and sys_platform != 'linux'", | |||||
| "python_full_version >= '3.12.4' and platform_python_implementation == 'PyPy' and sys_platform == 'linux'", | |||||
| "python_full_version >= '3.12.4' and platform_python_implementation == 'PyPy' and sys_platform != 'linux'", | |||||
| "python_full_version >= '3.12' and python_full_version < '3.12.4' and platform_python_implementation == 'PyPy' and sys_platform == 'linux'", | |||||
| "python_full_version >= '3.12' and python_full_version < '3.12.4' and platform_python_implementation == 'PyPy' and sys_platform != 'linux'", | |||||
| "python_full_version < '3.12' and platform_python_implementation != 'PyPy' and sys_platform == 'linux'", | |||||
| "python_full_version < '3.12' and platform_python_implementation != 'PyPy' and sys_platform != 'linux'", | |||||
| "python_full_version < '3.12' and platform_python_implementation == 'PyPy' and sys_platform == 'linux'", | |||||
| "python_full_version < '3.12' and platform_python_implementation == 'PyPy' and sys_platform != 'linux'", | |||||
| ] | ] | ||||
| [[package]] | [[package]] | ||||
| version = "1.2.2.post1" | version = "1.2.2.post1" | ||||
| source = { registry = "https://pypi.org/simple" } | source = { registry = "https://pypi.org/simple" } | ||||
| dependencies = [ | dependencies = [ | ||||
| { name = "colorama", marker = "os_name == 'nt'" }, | |||||
| { name = "colorama", marker = "os_name == 'nt' and sys_platform != 'linux'" }, | |||||
| { name = "packaging" }, | { name = "packaging" }, | ||||
| { name = "pyproject-hooks" }, | { name = "pyproject-hooks" }, | ||||
| ] | ] | ||||
| { name = "transformers" }, | { name = "transformers" }, | ||||
| { name = "unstructured", extra = ["docx", "epub", "md", "ppt", "pptx"] }, | { name = "unstructured", extra = ["docx", "epub", "md", "ppt", "pptx"] }, | ||||
| { name = "validators" }, | { name = "validators" }, | ||||
| { name = "weave" }, | |||||
| { name = "yarl" }, | { name = "yarl" }, | ||||
| ] | ] | ||||
| { name = "transformers", specifier = "~=4.35.0" }, | { name = "transformers", specifier = "~=4.35.0" }, | ||||
| { name = "unstructured", extras = ["docx", "epub", "md", "ppt", "pptx"], specifier = "~=0.16.1" }, | { name = "unstructured", extras = ["docx", "epub", "md", "ppt", "pptx"], specifier = "~=0.16.1" }, | ||||
| { name = "validators", specifier = "==0.21.0" }, | { name = "validators", specifier = "==0.21.0" }, | ||||
| { name = "weave", specifier = "~=0.51.34" }, | |||||
| { name = "yarl", specifier = "~=1.18.3" }, | { name = "yarl", specifier = "~=1.18.3" }, | ||||
| ] | ] | ||||
| { name = "xinference-client", specifier = "~=1.2.2" }, | { name = "xinference-client", specifier = "~=1.2.2" }, | ||||
| ] | ] | ||||
| [[package]] | |||||
| name = "diskcache" | |||||
| version = "5.6.3" | |||||
| source = { registry = "https://pypi.org/simple" } | |||||
| sdist = { url = "https://files.pythonhosted.org/packages/3f/21/1c1ffc1a039ddcc459db43cc108658f32c57d271d7289a2794e401d0fdb6/diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc", size = 67916 } | |||||
| wheels = [ | |||||
| { url = "https://files.pythonhosted.org/packages/3f/27/4570e78fc0bf5ea0ca45eb1de3818a23787af9b390c0b0a0033a1b8236f9/diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19", size = 45550 }, | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "distro" | name = "distro" | ||||
| version = "1.9.0" | version = "1.9.0" | ||||
| { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277 }, | { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277 }, | ||||
| ] | ] | ||||
| [[package]] | |||||
| name = "docker-pycreds" | |||||
| version = "0.4.0" | |||||
| source = { registry = "https://pypi.org/simple" } | |||||
| dependencies = [ | |||||
| { name = "six" }, | |||||
| ] | |||||
| sdist = { url = "https://files.pythonhosted.org/packages/c5/e6/d1f6c00b7221e2d7c4b470132c931325c8b22c51ca62417e300f5ce16009/docker-pycreds-0.4.0.tar.gz", hash = "sha256:6ce3270bcaf404cc4c3e27e4b6c70d3521deae82fb508767870fdbf772d584d4", size = 8754 } | |||||
| wheels = [ | |||||
| { url = "https://files.pythonhosted.org/packages/f5/e8/f6bd1eee09314e7e6dee49cbe2c5e22314ccdb38db16c9fc72d2fa80d054/docker_pycreds-0.4.0-py2.py3-none-any.whl", hash = "sha256:7266112468627868005106ec19cd0d722702d2b7d5912a28e19b826c3d37af49", size = 8982 }, | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "docstring-parser" | name = "docstring-parser" | ||||
| version = "0.16" | version = "0.16" | ||||
| { url = "https://files.pythonhosted.org/packages/11/b2/5d20664ef6a077bec9f27f7a7ee761edc64946d0b1e293726a3d074a9a18/gevent-24.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:68bee86b6e1c041a187347ef84cf03a792f0b6c7238378bf6ba4118af11feaae", size = 1541631 }, | { url = "https://files.pythonhosted.org/packages/11/b2/5d20664ef6a077bec9f27f7a7ee761edc64946d0b1e293726a3d074a9a18/gevent-24.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:68bee86b6e1c041a187347ef84cf03a792f0b6c7238378bf6ba4118af11feaae", size = 1541631 }, | ||||
| ] | ] | ||||
| [[package]] | |||||
| name = "gitdb" | |||||
| version = "4.0.12" | |||||
| source = { registry = "https://pypi.org/simple" } | |||||
| dependencies = [ | |||||
| { name = "smmap" }, | |||||
| ] | |||||
| sdist = { url = "https://files.pythonhosted.org/packages/72/94/63b0fc47eb32792c7ba1fe1b694daec9a63620db1e313033d18140c2320a/gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571", size = 394684 } | |||||
| wheels = [ | |||||
| { url = "https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf", size = 62794 }, | |||||
| ] | |||||
| [[package]] | |||||
| name = "gitpython" | |||||
| version = "3.1.44" | |||||
| source = { registry = "https://pypi.org/simple" } | |||||
| dependencies = [ | |||||
| { name = "gitdb" }, | |||||
| ] | |||||
| sdist = { url = "https://files.pythonhosted.org/packages/c0/89/37df0b71473153574a5cdef8f242de422a0f5d26d7a9e231e6f169b4ad14/gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269", size = 214196 } | |||||
| wheels = [ | |||||
| { url = "https://files.pythonhosted.org/packages/1d/9a/4114a9057db2f1462d5c8f8390ab7383925fe1ac012eaa42402ad65c2963/GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110", size = 207599 }, | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "gmpy2" | name = "gmpy2" | ||||
| version = "2.2.1" | version = "2.2.1" | ||||
| { url = "https://files.pythonhosted.org/packages/47/3a/1a7cac16438f4e5319a0c879416d5e5032c98c3db2874e6e5300b3b475e6/gotrue-2.11.4-py3-none-any.whl", hash = "sha256:712e5018acc00d93cfc6d7bfddc3114eb3c420ab03b945757a8ba38c5fc3caa8", size = 41106 }, | { url = "https://files.pythonhosted.org/packages/47/3a/1a7cac16438f4e5319a0c879416d5e5032c98c3db2874e6e5300b3b475e6/gotrue-2.11.4-py3-none-any.whl", hash = "sha256:712e5018acc00d93cfc6d7bfddc3114eb3c420ab03b945757a8ba38c5fc3caa8", size = 41106 }, | ||||
| ] | ] | ||||
| [[package]] | |||||
| name = "gql" | |||||
| version = "3.5.2" | |||||
| source = { registry = "https://pypi.org/simple" } | |||||
| dependencies = [ | |||||
| { name = "anyio" }, | |||||
| { name = "backoff" }, | |||||
| { name = "graphql-core" }, | |||||
| { name = "yarl" }, | |||||
| ] | |||||
| sdist = { url = "https://files.pythonhosted.org/packages/49/ef/5298d9d628b6a54b3b810052cb5a935d324fe28d9bfdeb741733d5c2446b/gql-3.5.2.tar.gz", hash = "sha256:07e1325b820c8ba9478e95de27ce9f23250486e7e79113dbb7659a442dc13e74", size = 180502 } | |||||
| wheels = [ | |||||
| { url = "https://files.pythonhosted.org/packages/ff/71/b028b937992056e721bbf0371e13819fcca0dacde7b3c821f775ed903917/gql-3.5.2-py2.py3-none-any.whl", hash = "sha256:c830ffc38b3997b2a146317b27758305ab3d0da3bde607b49f34e32affb23ba2", size = 74346 }, | |||||
| ] | |||||
| [package.optional-dependencies] | |||||
| aiohttp = [ | |||||
| { name = "aiohttp" }, | |||||
| ] | |||||
| requests = [ | |||||
| { name = "requests" }, | |||||
| { name = "requests-toolbelt" }, | |||||
| ] | |||||
| [[package]] | |||||
| name = "graphql-core" | |||||
| version = "3.2.4" | |||||
| source = { registry = "https://pypi.org/simple" } | |||||
| sdist = { url = "https://files.pythonhosted.org/packages/66/9e/aa527fb09a9d7399d5d7d2aa2da490e4580707652d3b4fc156996ae88a5b/graphql-core-3.2.4.tar.gz", hash = "sha256:acbe2e800980d0e39b4685dd058c2f4042660b89ebca38af83020fd872ff1264", size = 504611 } | |||||
| wheels = [ | |||||
| { url = "https://files.pythonhosted.org/packages/d1/33/cc72c4c658c6316f188a60bc4e5a91cd4ceaaa8c3e7e691ac9297e4e72c7/graphql_core-3.2.4-py3-none-any.whl", hash = "sha256:1604f2042edc5f3114f49cac9d77e25863be51b23a54a61a23245cf32f6476f0", size = 203179 }, | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "greenlet" | name = "greenlet" | ||||
| version = "3.1.1" | version = "3.1.1" | ||||
| { url = "https://files.pythonhosted.org/packages/37/f3/9b18362206b244167c958984b57c7f70a0289bfb59a530dd8af5f699b910/pillow-11.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5", size = 2375240 }, | { url = "https://files.pythonhosted.org/packages/37/f3/9b18362206b244167c958984b57c7f70a0289bfb59a530dd8af5f699b910/pillow-11.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5", size = 2375240 }, | ||||
| ] | ] | ||||
| [[package]] | |||||
| name = "platformdirs" | |||||
| version = "4.3.7" | |||||
| source = { registry = "https://pypi.org/simple" } | |||||
| sdist = { url = "https://files.pythonhosted.org/packages/b6/2d/7d512a3913d60623e7eb945c6d1b4f0bddf1d0b7ada5225274c87e5b53d1/platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351", size = 21291 } | |||||
| wheels = [ | |||||
| { url = "https://files.pythonhosted.org/packages/6d/45/59578566b3275b8fd9157885918fcd0c4d74162928a5310926887b856a51/platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94", size = 18499 }, | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "pluggy" | name = "pluggy" | ||||
| version = "1.5.0" | version = "1.5.0" | ||||
| { url = "https://files.pythonhosted.org/packages/af/cd/ed6e429fb0792ce368f66e83246264dd3a7a045b0b1e63043ed22a063ce5/pycryptodome-3.19.1-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:7c9e222d0976f68d0cf6409cfea896676ddc1d98485d601e9508f90f60e2b0a2", size = 2144914 }, | { url = "https://files.pythonhosted.org/packages/af/cd/ed6e429fb0792ce368f66e83246264dd3a7a045b0b1e63043ed22a063ce5/pycryptodome-3.19.1-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:7c9e222d0976f68d0cf6409cfea896676ddc1d98485d601e9508f90f60e2b0a2", size = 2144914 }, | ||||
| { url = "https://files.pythonhosted.org/packages/f6/23/b064bd4cfbf2cc5f25afcde0e7c880df5b20798172793137ba4b62d82e72/pycryptodome-3.19.1-cp35-abi3-win32.whl", hash = "sha256:4805e053571140cb37cf153b5c72cd324bb1e3e837cbe590a19f69b6cf85fd03", size = 1713105 }, | { url = "https://files.pythonhosted.org/packages/f6/23/b064bd4cfbf2cc5f25afcde0e7c880df5b20798172793137ba4b62d82e72/pycryptodome-3.19.1-cp35-abi3-win32.whl", hash = "sha256:4805e053571140cb37cf153b5c72cd324bb1e3e837cbe590a19f69b6cf85fd03", size = 1713105 }, | ||||
| { url = "https://files.pythonhosted.org/packages/7d/e0/ded1968a5257ab34216a0f8db7433897a2337d59e6d03be113713b346ea2/pycryptodome-3.19.1-cp35-abi3-win_amd64.whl", hash = "sha256:a470237ee71a1efd63f9becebc0ad84b88ec28e6784a2047684b693f458f41b7", size = 1749222 }, | { url = "https://files.pythonhosted.org/packages/7d/e0/ded1968a5257ab34216a0f8db7433897a2337d59e6d03be113713b346ea2/pycryptodome-3.19.1-cp35-abi3-win_amd64.whl", hash = "sha256:a470237ee71a1efd63f9becebc0ad84b88ec28e6784a2047684b693f458f41b7", size = 1749222 }, | ||||
| { url = "https://files.pythonhosted.org/packages/1d/e3/0c9679cd66cf5604b1f070bdf4525a0c01a15187be287d8348b2eafb718e/pycryptodome-3.19.1-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:ed932eb6c2b1c4391e166e1a562c9d2f020bfff44a0e1b108f67af38b390ea89", size = 1629005 }, | |||||
| { url = "https://files.pythonhosted.org/packages/13/75/0d63bf0daafd0580b17202d8a9dd57f28c8487f26146b3e2799b0c5a059c/pycryptodome-3.19.1-pp27-pypy_73-win32.whl", hash = "sha256:81e9d23c0316fc1b45d984a44881b220062336bbdc340aa9218e8d0656587934", size = 1697997 }, | |||||
| ] | ] | ||||
| [[package]] | [[package]] | ||||
| { name = "markupsafe" }, | { name = "markupsafe" }, | ||||
| ] | ] | ||||
| [[package]] | |||||
| name = "setproctitle" | |||||
| version = "1.3.5" | |||||
| source = { registry = "https://pypi.org/simple" } | |||||
| sdist = { url = "https://files.pythonhosted.org/packages/c4/4d/6a840c8d2baa07b57329490e7094f90aac177a1d5226bc919046f1106860/setproctitle-1.3.5.tar.gz", hash = "sha256:1e6eaeaf8a734d428a95d8c104643b39af7d247d604f40a7bebcf3960a853c5e", size = 26737 } | |||||
| wheels = [ | |||||
| { url = "https://files.pythonhosted.org/packages/ec/4a/9e0243c5df221102fb834a947f5753d9da06ad5f84e36b0e2e93f7865edb/setproctitle-1.3.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1c8dcc250872385f2780a5ea58050b58cbc8b6a7e8444952a5a65c359886c593", size = 17256 }, | |||||
| { url = "https://files.pythonhosted.org/packages/c7/a1/76ad2ba6f5bd00609238e3d64eeded4598e742a5f25b5cc1a0efdae5f674/setproctitle-1.3.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ca82fae9eb4800231dd20229f06e8919787135a5581da245b8b05e864f34cc8b", size = 11893 }, | |||||
| { url = "https://files.pythonhosted.org/packages/47/3a/75d11fedff5b21ba9a4c5fe3dfa5e596f831d094ef1896713a72e9e38833/setproctitle-1.3.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0424e1d33232322541cb36fb279ea5242203cd6f20de7b4fb2a11973d8e8c2ce", size = 31631 }, | |||||
| { url = "https://files.pythonhosted.org/packages/5a/12/58220de5600e0ed2e5562297173187d863db49babb03491ffe9c101299bc/setproctitle-1.3.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fec8340ab543144d04a9d805d80a0aad73fdeb54bea6ff94e70d39a676ea4ec0", size = 32975 }, | |||||
| { url = "https://files.pythonhosted.org/packages/fa/c4/fbb308680d83c1c7aa626950308318c6e6381a8273779163a31741f3c752/setproctitle-1.3.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eab441c89f181271ab749077dcc94045a423e51f2fb0b120a1463ef9820a08d0", size = 30126 }, | |||||
| { url = "https://files.pythonhosted.org/packages/31/6e/baaf70bd9a881dd8c12cbccdd7ca0ff291024a37044a8245e942e12e7135/setproctitle-1.3.5-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2c371550a2288901a0dcd84192691ebd3197a43c95f3e0b396ed6d1cedf5c6c", size = 31135 }, | |||||
| { url = "https://files.pythonhosted.org/packages/a6/dc/d8ab6b1c3d844dc14f596e3cce76604570848f8a67ba6a3812775ed2c015/setproctitle-1.3.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:78288ff5f9c415c56595b2257ad218936dd9fa726b36341b373b31ca958590fe", size = 30874 }, | |||||
| { url = "https://files.pythonhosted.org/packages/d4/84/62a359b3aa51228bd88f78b44ebb0256a5b96dd2487881c1e984a59b617d/setproctitle-1.3.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f1f13a25fc46731acab518602bb1149bfd8b5fabedf8290a7c0926d61414769d", size = 29893 }, | |||||
| { url = "https://files.pythonhosted.org/packages/e2/d6/b3c52c03ee41e7f006e1a737e0db1c58d1dc28e258b83548e653d0c34f1c/setproctitle-1.3.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1534d6cd3854d035e40bf4c091984cbdd4d555d7579676d406c53c8f187c006f", size = 32293 }, | |||||
| { url = "https://files.pythonhosted.org/packages/55/09/c0ba311879d9c05860503a7e2708ace85913b9a816786402a92c664fe930/setproctitle-1.3.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:62a01c76708daac78b9688ffb95268c57cb57fa90b543043cda01358912fe2db", size = 30247 }, | |||||
| { url = "https://files.pythonhosted.org/packages/9e/43/cc7155461f0b5a48aebdb87d78239ff3a51ebda0905de478d9fa6ab92d9c/setproctitle-1.3.5-cp311-cp311-win32.whl", hash = "sha256:ea07f29735d839eaed985990a0ec42c8aecefe8050da89fec35533d146a7826d", size = 11476 }, | |||||
| { url = "https://files.pythonhosted.org/packages/e7/57/6e937ac7aa52db69225f02db2cfdcb66ba1db6fdc65a4ddbdf78e214f72a/setproctitle-1.3.5-cp311-cp311-win_amd64.whl", hash = "sha256:ab3ae11e10d13d514d4a5a15b4f619341142ba3e18da48c40e8614c5a1b5e3c3", size = 12189 }, | |||||
| { url = "https://files.pythonhosted.org/packages/2b/19/04755958495de57e4891de50f03e77b3fe9ca6716a86de00faa00ad0ee5a/setproctitle-1.3.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:523424b9be4dea97d95b8a584b183f35c7bab2d0a3d995b01febf5b8a8de90e4", size = 17250 }, | |||||
| { url = "https://files.pythonhosted.org/packages/b9/3d/2ca9df5aa49b975296411dcbbe272cdb1c5e514c43b8be7d61751bb71a46/setproctitle-1.3.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b6ec1d86c1b4d7b5f2bdceadf213310cf24696b82480a2a702194b8a0bfbcb47", size = 11878 }, | |||||
| { url = "https://files.pythonhosted.org/packages/36/d6/e90e23b4627e016a4f862d4f892be92c9765dd6bf1e27a48e52cd166d4a3/setproctitle-1.3.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea6c505264275a43e9b2acd2acfc11ac33caf52bc3167c9fced4418a810f6b1c", size = 31940 }, | |||||
| { url = "https://files.pythonhosted.org/packages/15/13/167cdd55e00a8e10b36aad79646c3bf3c23fba0c08a9b8db9b74622c1b13/setproctitle-1.3.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b91e68e6685998e6353f296100ecabc313a6cb3e413d66a03d74b988b61f5ff", size = 33370 }, | |||||
| { url = "https://files.pythonhosted.org/packages/9b/22/574a110527df133409a75053b7d6ff740993ccf30b8713d042f26840d351/setproctitle-1.3.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc1fda208ae3a2285ad27aeab44c41daf2328abe58fa3270157a739866779199", size = 30628 }, | |||||
| { url = "https://files.pythonhosted.org/packages/52/79/78b05c7d792c9167b917acdab1773b1ff73b016560f45d8155be2baa1a82/setproctitle-1.3.5-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:828727d220e46f048b82289018300a64547b46aaed96bf8810c05fe105426b41", size = 31672 }, | |||||
| { url = "https://files.pythonhosted.org/packages/b0/62/4509735be062129694751ac55d5e1fbb6d86fa46a8689b7d5e2c23dae5b0/setproctitle-1.3.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:83b016221cf80028b2947be20630faa14e3e72a403e35f0ba29550b4e856767b", size = 31378 }, | |||||
| { url = "https://files.pythonhosted.org/packages/72/e7/b394c55934b89f00c2ef7d5e6f18cca5d8dfa26ef628700c4de0c85e3f3d/setproctitle-1.3.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6d8a411e752e794d052434139ca4234ffeceeb8d8d8ddc390a9051d7942b2726", size = 30370 }, | |||||
| { url = "https://files.pythonhosted.org/packages/13/ee/e1f27bf52d2bec7060bb6311ab0ccede8de98ed5394e3a59e7a14a453fb5/setproctitle-1.3.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:50cfbf86b9c63a2c2903f1231f0a58edeb775e651ae1af84eec8430b0571f29b", size = 32875 }, | |||||
| { url = "https://files.pythonhosted.org/packages/6e/08/13b561085d2de53b9becfa5578545d99114e9ff2aa3dc151bcaadf80b17e/setproctitle-1.3.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f3b5e2eacd572444770026c9dd3ddc7543ce427cdf452d40a408d1e95beefb30", size = 30903 }, | |||||
| { url = "https://files.pythonhosted.org/packages/65/f0/6cd06fffff2553be7b0571447d0c0ef8b727ef44cc2d6a33452677a311c8/setproctitle-1.3.5-cp312-cp312-win32.whl", hash = "sha256:cf4e3ded98027de2596c6cc5bbd3302adfb3ca315c848f56516bb0b7e88de1e9", size = 11468 }, | |||||
| { url = "https://files.pythonhosted.org/packages/c1/8c/e8a7cb568c4552618838941b332203bfc77ab0f2d67c1cb8f24dee0370ec/setproctitle-1.3.5-cp312-cp312-win_amd64.whl", hash = "sha256:f7a8c01ffd013dda2bed6e7d5cb59fbb609e72f805abf3ee98360f38f7758d9b", size = 12190 }, | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "setuptools" | name = "setuptools" | ||||
| version = "78.1.0" | version = "78.1.0" | ||||
| { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, | { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, | ||||
| ] | ] | ||||
| [[package]] | |||||
| name = "smmap" | |||||
| version = "5.0.2" | |||||
| source = { registry = "https://pypi.org/simple" } | |||||
| sdist = { url = "https://files.pythonhosted.org/packages/44/cd/a040c4b3119bbe532e5b0732286f805445375489fceaec1f48306068ee3b/smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5", size = 22329 } | |||||
| wheels = [ | |||||
| { url = "https://files.pythonhosted.org/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e", size = 24303 }, | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "sniffio" | name = "sniffio" | ||||
| version = "1.3.1" | version = "1.3.1" | ||||
| { url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 }, | { url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 }, | ||||
| ] | ] | ||||
| [[package]] | |||||
| name = "uuid-utils" | |||||
| version = "0.10.0" | |||||
| source = { registry = "https://pypi.org/simple" } | |||||
| sdist = { url = "https://files.pythonhosted.org/packages/66/0a/cbdb2eb4845dafeb632d02a18f47b02f87f2ce4f25266f5e3c017976ce89/uuid_utils-0.10.0.tar.gz", hash = "sha256:5db0e1890e8f008657ffe6ded4d9459af724ab114cfe82af1557c87545301539", size = 18828 } | |||||
| wheels = [ | |||||
| { url = "https://files.pythonhosted.org/packages/44/54/9d22fa16b19e5d1676eba510f08a9c458d96e2a62ff2c8ebad64251afb18/uuid_utils-0.10.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8d5a4508feefec62456cd6a41bcdde458d56827d908f226803b886d22a3d5e63", size = 573006 }, | |||||
| { url = "https://files.pythonhosted.org/packages/08/8e/f895c6e52aa603e521fbc13b8626ba5dd99b6e2f5a55aa96ba5b232f4c53/uuid_utils-0.10.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:dbefc2b9113f9dfe56bdae58301a2b3c53792221410d422826f3d1e3e6555fe7", size = 292543 }, | |||||
| { url = "https://files.pythonhosted.org/packages/b6/58/cc4834f377a5e97d6e184408ad96d13042308de56643b6e24afe1f6f34df/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffc49c33edf87d1ec8112a9b43e4cf55326877716f929c165a2cc307d31c73d5", size = 323340 }, | |||||
| { url = "https://files.pythonhosted.org/packages/37/e3/6aeddf148f6a7dd7759621b000e8c85382ec83f52ae79b60842d1dc3ab6b/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0636b6208f69d5a4e629707ad2a89a04dfa8d1023e1999181f6830646ca048a1", size = 329653 }, | |||||
| { url = "https://files.pythonhosted.org/packages/0c/00/dd6c2164ace70b7b1671d9129267df331481d7d1e5f9c5e6a564f07953f6/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7bc06452856b724df9dedfc161c3582199547da54aeb81915ec2ed54f92d19b0", size = 365471 }, | |||||
| { url = "https://files.pythonhosted.org/packages/b4/e7/0ab8080fcae5462a7b5e555c1cef3d63457baffb97a59b9bc7b005a3ecb1/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:263b2589111c61decdd74a762e8f850c9e4386fb78d2cf7cb4dfc537054cda1b", size = 325844 }, | |||||
| { url = "https://files.pythonhosted.org/packages/73/39/52d94e9ef75b03f44b39ffc6ac3167e93e74ef4d010a93d25589d9f48540/uuid_utils-0.10.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a558db48b7096de6b4d2d2210d82bba8586a6d55f99106b03bb7d01dc5c5bcd6", size = 344389 }, | |||||
| { url = "https://files.pythonhosted.org/packages/7c/29/4824566f62666238290d99c62a58e4ab2a8b9cf2eccf94cebd9b3359131e/uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:807465067f3c892514230326ac71a79b28a8dfe2c88ecd2d5675fc844f3c76b5", size = 510078 }, | |||||
| { url = "https://files.pythonhosted.org/packages/5e/8f/bbcc7130d652462c685f0d3bd26bb214b754215b476340885a4cb50fb89a/uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:57423d4a2b9d7b916de6dbd75ba85465a28f9578a89a97f7d3e098d9aa4e5d4a", size = 515937 }, | |||||
| { url = "https://files.pythonhosted.org/packages/23/f8/34e0c00f5f188604d336713e6a020fcf53b10998e8ab24735a39ab076740/uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:76d8d660f18ff6b767e319b1b5f927350cd92eafa4831d7ef5b57fdd1d91f974", size = 494111 }, | |||||
| { url = "https://files.pythonhosted.org/packages/1a/52/b7f0066cc90a7a9c28d54061ed195cd617fde822e5d6ac3ccc88509c3c44/uuid_utils-0.10.0-cp39-abi3-win32.whl", hash = "sha256:6c11a71489338837db0b902b75e1ba7618d5d29f05fde4f68b3f909177dbc226", size = 173520 }, | |||||
| { url = "https://files.pythonhosted.org/packages/8b/15/f04f58094674d333974243fb45d2c740cf4b79186fb707168e57943c84a3/uuid_utils-0.10.0-cp39-abi3-win_amd64.whl", hash = "sha256:11c55ae64f6c0a7a0c741deae8ca2a4eaa11e9c09dbb7bec2099635696034cf7", size = 182965 }, | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "uuid6" | name = "uuid6" | ||||
| version = "2024.7.10" | version = "2024.7.10" | ||||
| { url = "https://files.pythonhosted.org/packages/37/da/7ccbe82470dc27e1cfd0466dc637248be906eb8447c28a40c1c74cf617ee/volcengine_compat-1.0.156-py3-none-any.whl", hash = "sha256:4abc149a7601ebad8fa2d28fab50c7945145cf74daecb71bca797b0bdc82c5a5", size = 677272 }, | { url = "https://files.pythonhosted.org/packages/37/da/7ccbe82470dc27e1cfd0466dc637248be906eb8447c28a40c1c74cf617ee/volcengine_compat-1.0.156-py3-none-any.whl", hash = "sha256:4abc149a7601ebad8fa2d28fab50c7945145cf74daecb71bca797b0bdc82c5a5", size = 677272 }, | ||||
| ] | ] | ||||
| [[package]] | |||||
| name = "wandb" | |||||
| version = "0.18.3" | |||||
| source = { registry = "https://pypi.org/simple" } | |||||
| dependencies = [ | |||||
| { name = "click" }, | |||||
| { name = "docker-pycreds" }, | |||||
| { name = "gitpython" }, | |||||
| { name = "platformdirs" }, | |||||
| { name = "protobuf" }, | |||||
| { name = "psutil" }, | |||||
| { name = "pyyaml" }, | |||||
| { name = "requests" }, | |||||
| { name = "sentry-sdk" }, | |||||
| { name = "setproctitle" }, | |||||
| { name = "setuptools" }, | |||||
| ] | |||||
| sdist = { url = "https://files.pythonhosted.org/packages/cc/57/8a61979c40a7a0a5206ef3369ed474326135bf292f172019f35dca97a235/wandb-0.18.3.tar.gz", hash = "sha256:eb2574cea72bc908c6ce1b37edf7a889619e6e06e1b4714eecfe0662ded43c06", size = 8686381 } | |||||
| wheels = [ | |||||
| { url = "https://files.pythonhosted.org/packages/1c/4a/6fa1d584ecd69cea5b9943ec5cfa36276cbd567efa8709135a7e4ab89cfb/wandb-0.18.3-py3-none-any.whl", hash = "sha256:7da64f7da0ff7572439de10bfd45534e8811e71e78ac2ccc3b818f1c0f3a9aef", size = 5015658 }, | |||||
| { url = "https://files.pythonhosted.org/packages/59/8f/deef595ca67833ea5aceb5da5fc10759a5e8f8bce85b17761b1614fa2ba9/wandb-0.18.3-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:6674d8a5c40c79065b9c7eb765136756d5ebc9457a5f9abc820a660fb23f8b67", size = 10081571 }, | |||||
| { url = "https://files.pythonhosted.org/packages/06/85/b55642d095407369dd7ad1d8ea1e7f410d60fcdb6c29bcc9afb1e5522d51/wandb-0.18.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:741f566e409a2684d3047e4cc25e8e914d78196b901190937b24b6abb8b052e5", size = 10008319 }, | |||||
| { url = "https://files.pythonhosted.org/packages/b4/53/5387afaab29876e669973b3bb5bda829e3c10e509caef59f614bf20c0106/wandb-0.18.3-py3-none-macosx_11_0_x86_64.whl", hash = "sha256:8be5e877570b693001c52dcc2089e48e6a4dcbf15f3adf5c9349f95148b59d58", size = 10250633 }, | |||||
| { url = "https://files.pythonhosted.org/packages/bd/79/2fa554283afa7259e296313160164947daf52e0d42b04d6ecf9c5af01e15/wandb-0.18.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d788852bd4739fa18de3918f309c3a955b5cef3247fae1c40df3a63af637e1a0", size = 12339454 }, | |||||
| { url = "https://files.pythonhosted.org/packages/86/a6/11eaa16c96469b4d6fc0fb3271e70d5bbe2c3a93c15fc677de9a1aa4374a/wandb-0.18.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab81424eb207d78239a8d69c90521a70074fb81e3709055484e43c76fe44dc08", size = 12970950 }, | |||||
| { url = "https://files.pythonhosted.org/packages/13/dd/ccaa5a51e2557368300eec9e362b5688151e45a052e33017633baa3011a9/wandb-0.18.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:2c91315b8b62423eae18577d66a4b4bb8e4341a7d5c849cb2963e3b3dff0bf6d", size = 13038220 }, | |||||
| { url = "https://files.pythonhosted.org/packages/bc/6f/fabbf2161078556384ef48f3db89182773010cdd14900986004e702b85f5/wandb-0.18.3-py3-none-win32.whl", hash = "sha256:92a647dab783938ec87776a9fae8a13e72e6dad939c53e357cdea9d2570f0ad8", size = 12573298 }, | |||||
| { url = "https://files.pythonhosted.org/packages/d8/7b/e94b46d620d26b2e1f486f2746febdcb6579be20f361355b40263ddd8262/wandb-0.18.3-py3-none-win_amd64.whl", hash = "sha256:29cac2cfa3124241fed22cfedc9a52e1500275ee9bbb0b428ce4bf63c4723bf0", size = 12573303 }, | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "watchfiles" | name = "watchfiles" | ||||
| version = "1.0.5" | version = "1.0.5" | ||||
| { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166 }, | { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166 }, | ||||
| ] | ] | ||||
| [[package]] | |||||
| name = "weave" | |||||
| version = "0.51.43" | |||||
| source = { registry = "https://pypi.org/simple" } | |||||
| dependencies = [ | |||||
| { name = "diskcache" }, | |||||
| { name = "emoji" }, | |||||
| { name = "gql", extra = ["aiohttp", "requests"] }, | |||||
| { name = "jsonschema" }, | |||||
| { name = "numpy" }, | |||||
| { name = "packaging" }, | |||||
| { name = "pydantic" }, | |||||
| { name = "rich" }, | |||||
| { name = "tenacity" }, | |||||
| { name = "uuid-utils" }, | |||||
| { name = "wandb" }, | |||||
| ] | |||||
| sdist = { url = "https://files.pythonhosted.org/packages/e1/b4/8fb1e21bc0b0442be9c4c5e4644847596cd75a35a313a5887f1eadda8da2/weave-0.51.43.tar.gz", hash = "sha256:bab4ba6f7ba33f1975e5f6399b7fc4ad6b25c0e2cd22d197bb9358a7b9596b91", size = 368936 } | |||||
| wheels = [ | |||||
| { url = "https://files.pythonhosted.org/packages/a8/40/1e374d3f1f8389a4228426b5a87aae7428a7eb74dfa633de98d86796eb41/weave-0.51.43-py3-none-any.whl", hash = "sha256:2e9faa0e21bd5a6fea363142891ee4f2e347951b98f0d7082acb0273432cb940", size = 473685 }, | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "weaviate-client" | name = "weaviate-client" | ||||
| version = "3.21.0" | version = "3.21.0" |
| import { useBoolean } from 'ahooks' | import { useBoolean } from 'ahooks' | ||||
| import TracingIcon from './tracing-icon' | import TracingIcon from './tracing-icon' | ||||
| import ProviderPanel from './provider-panel' | import ProviderPanel from './provider-panel' | ||||
| import type { LangFuseConfig, LangSmithConfig, OpikConfig } from './type' | |||||
| import type { LangFuseConfig, LangSmithConfig, OpikConfig, WeaveConfig } from './type' | |||||
| import { TracingProvider } from './type' | import { TracingProvider } from './type' | ||||
| import ProviderConfigModal from './provider-config-modal' | import ProviderConfigModal from './provider-config-modal' | ||||
| import Indicator from '@/app/components/header/indicator' | import Indicator from '@/app/components/header/indicator' | ||||
| langSmithConfig: LangSmithConfig | null | langSmithConfig: LangSmithConfig | null | ||||
| langFuseConfig: LangFuseConfig | null | langFuseConfig: LangFuseConfig | null | ||||
| opikConfig: OpikConfig | null | opikConfig: OpikConfig | null | ||||
| onConfigUpdated: (provider: TracingProvider, payload: LangSmithConfig | LangFuseConfig | OpikConfig) => void | |||||
| weaveConfig: WeaveConfig | null | |||||
| onConfigUpdated: (provider: TracingProvider, payload: LangSmithConfig | LangFuseConfig | OpikConfig | WeaveConfig) => void | |||||
| onConfigRemoved: (provider: TracingProvider) => void | onConfigRemoved: (provider: TracingProvider) => void | ||||
| } | } | ||||
| langSmithConfig, | langSmithConfig, | ||||
| langFuseConfig, | langFuseConfig, | ||||
| opikConfig, | opikConfig, | ||||
| weaveConfig, | |||||
| onConfigUpdated, | onConfigUpdated, | ||||
| onConfigRemoved, | onConfigRemoved, | ||||
| }) => { | }) => { | ||||
| } | } | ||||
| }, [onChooseProvider]) | }, [onChooseProvider]) | ||||
| const handleConfigUpdated = useCallback((payload: LangSmithConfig | LangFuseConfig | OpikConfig) => { | |||||
| const handleConfigUpdated = useCallback((payload: LangSmithConfig | LangFuseConfig | OpikConfig | WeaveConfig) => { | |||||
| onConfigUpdated(currentProvider!, payload) | onConfigUpdated(currentProvider!, payload) | ||||
| hideConfigModal() | hideConfigModal() | ||||
| }, [currentProvider, hideConfigModal, onConfigUpdated]) | }, [currentProvider, hideConfigModal, onConfigUpdated]) | ||||
| hideConfigModal() | hideConfigModal() | ||||
| }, [currentProvider, hideConfigModal, onConfigRemoved]) | }, [currentProvider, hideConfigModal, onConfigRemoved]) | ||||
| const providerAllConfigured = langSmithConfig && langFuseConfig && opikConfig | |||||
| const providerAllNotConfigured = !langSmithConfig && !langFuseConfig && !opikConfig | |||||
| const providerAllConfigured = langSmithConfig && langFuseConfig && opikConfig && weaveConfig | |||||
| const providerAllNotConfigured = !langSmithConfig && !langFuseConfig && !opikConfig && !weaveConfig | |||||
| const switchContent = ( | const switchContent = ( | ||||
| <Switch | <Switch | ||||
| /> | /> | ||||
| ) | ) | ||||
| const weavePanel = ( | |||||
| <ProviderPanel | |||||
| type={TracingProvider.weave} | |||||
| readOnly={readOnly} | |||||
| config={weaveConfig} | |||||
| hasConfigured={!!weaveConfig} | |||||
| onConfig={handleOnConfig(TracingProvider.weave)} | |||||
| isChosen={chosenProvider === TracingProvider.weave} | |||||
| onChoose={handleOnChoose(TracingProvider.weave)} | |||||
| key="weave-provider-panel" | |||||
| /> | |||||
| ) | |||||
| const configuredProviderPanel = () => { | const configuredProviderPanel = () => { | ||||
| const configuredPanels: JSX.Element[] = [] | const configuredPanels: JSX.Element[] = [] | ||||
| if (langSmithConfig) | |||||
| configuredPanels.push(langSmithPanel) | |||||
| if (langFuseConfig) | if (langFuseConfig) | ||||
| configuredPanels.push(langfusePanel) | configuredPanels.push(langfusePanel) | ||||
| if (langSmithConfig) | |||||
| configuredPanels.push(langSmithPanel) | |||||
| if (opikConfig) | if (opikConfig) | ||||
| configuredPanels.push(opikPanel) | configuredPanels.push(opikPanel) | ||||
| if (weaveConfig) | |||||
| configuredPanels.push(weavePanel) | |||||
| return configuredPanels | return configuredPanels | ||||
| } | } | ||||
| const moreProviderPanel = () => { | const moreProviderPanel = () => { | ||||
| const notConfiguredPanels: JSX.Element[] = [] | const notConfiguredPanels: JSX.Element[] = [] | ||||
| if (!langSmithConfig) | |||||
| notConfiguredPanels.push(langSmithPanel) | |||||
| if (!langFuseConfig) | if (!langFuseConfig) | ||||
| notConfiguredPanels.push(langfusePanel) | notConfiguredPanels.push(langfusePanel) | ||||
| if (!langSmithConfig) | |||||
| notConfiguredPanels.push(langSmithPanel) | |||||
| if (!opikConfig) | if (!opikConfig) | ||||
| notConfiguredPanels.push(opikPanel) | notConfiguredPanels.push(opikPanel) | ||||
| if (!weaveConfig) | |||||
| notConfiguredPanels.push(weavePanel) | |||||
| return notConfiguredPanels | return notConfiguredPanels | ||||
| } | } | ||||
| return langSmithConfig | return langSmithConfig | ||||
| if (currentProvider === TracingProvider.langfuse) | if (currentProvider === TracingProvider.langfuse) | ||||
| return langFuseConfig | return langFuseConfig | ||||
| return opikConfig | |||||
| if (currentProvider === TracingProvider.opik) | |||||
| return opikConfig | |||||
| return weaveConfig | |||||
| } | } | ||||
| return ( | return ( | ||||
| <> | <> | ||||
| <div className='system-xs-medium-uppercase text-text-tertiary'>{t(`${I18N_PREFIX}.configProviderTitle.${providerAllConfigured ? 'configured' : 'notConfigured'}`)}</div> | <div className='system-xs-medium-uppercase text-text-tertiary'>{t(`${I18N_PREFIX}.configProviderTitle.${providerAllConfigured ? 'configured' : 'notConfigured'}`)}</div> | ||||
| <div className='mt-2 space-y-2'> | <div className='mt-2 space-y-2'> | ||||
| {langSmithPanel} | |||||
| {langfusePanel} | {langfusePanel} | ||||
| {langSmithPanel} | |||||
| {opikPanel} | {opikPanel} | ||||
| {weavePanel} | |||||
| </div> | </div> | ||||
| </> | </> | ||||
| ) | ) |
| [TracingProvider.langSmith]: 'https://docs.smith.langchain.com/', | [TracingProvider.langSmith]: 'https://docs.smith.langchain.com/', | ||||
| [TracingProvider.langfuse]: 'https://docs.langfuse.com', | [TracingProvider.langfuse]: 'https://docs.langfuse.com', | ||||
| [TracingProvider.opik]: 'https://www.comet.com/docs/opik/tracing/integrations/dify#setup-instructions', | [TracingProvider.opik]: 'https://www.comet.com/docs/opik/tracing/integrations/dify#setup-instructions', | ||||
| [TracingProvider.weave]: 'https://weave-docs.wandb.ai/', | |||||
| } | } |
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { usePathname } from 'next/navigation' | import { usePathname } from 'next/navigation' | ||||
| import { useBoolean } from 'ahooks' | import { useBoolean } from 'ahooks' | ||||
| import type { LangFuseConfig, LangSmithConfig, OpikConfig } from './type' | |||||
| import type { LangFuseConfig, LangSmithConfig, OpikConfig, WeaveConfig } from './type' | |||||
| import { TracingProvider } from './type' | import { TracingProvider } from './type' | ||||
| import TracingIcon from './tracing-icon' | import TracingIcon from './tracing-icon' | ||||
| import ConfigButton from './config-button' | import ConfigButton from './config-button' | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import { LangfuseIcon, LangsmithIcon, OpikIcon } from '@/app/components/base/icons/src/public/tracing' | |||||
| import { LangfuseIcon, LangsmithIcon, OpikIcon, WeaveIcon } from '@/app/components/base/icons/src/public/tracing' | |||||
| import Indicator from '@/app/components/header/indicator' | import Indicator from '@/app/components/header/indicator' | ||||
| import { fetchTracingConfig as doFetchTracingConfig, fetchTracingStatus, updateTracingStatus } from '@/service/apps' | import { fetchTracingConfig as doFetchTracingConfig, fetchTracingStatus, updateTracingStatus } from '@/service/apps' | ||||
| import type { TracingStatus } from '@/models/app' | import type { TracingStatus } from '@/models/app' | ||||
| ? LangfuseIcon | ? LangfuseIcon | ||||
| : inUseTracingProvider === TracingProvider.opik | : inUseTracingProvider === TracingProvider.opik | ||||
| ? OpikIcon | ? OpikIcon | ||||
| : LangsmithIcon | |||||
| : inUseTracingProvider === TracingProvider.weave | |||||
| ? WeaveIcon | |||||
| : LangsmithIcon | |||||
| const [langSmithConfig, setLangSmithConfig] = useState<LangSmithConfig | null>(null) | const [langSmithConfig, setLangSmithConfig] = useState<LangSmithConfig | null>(null) | ||||
| const [langFuseConfig, setLangFuseConfig] = useState<LangFuseConfig | null>(null) | const [langFuseConfig, setLangFuseConfig] = useState<LangFuseConfig | null>(null) | ||||
| const [opikConfig, setOpikConfig] = useState<OpikConfig | null>(null) | const [opikConfig, setOpikConfig] = useState<OpikConfig | null>(null) | ||||
| const hasConfiguredTracing = !!(langSmithConfig || langFuseConfig || opikConfig) | |||||
| const [weaveConfig, setWeaveConfig] = useState<WeaveConfig | null>(null) | |||||
| const hasConfiguredTracing = !!(langSmithConfig || langFuseConfig || opikConfig || weaveConfig) | |||||
| const fetchTracingConfig = async () => { | const fetchTracingConfig = async () => { | ||||
| const { tracing_config: langSmithConfig, has_not_configured: langSmithHasNotConfig } = await doFetchTracingConfig({ appId, provider: TracingProvider.langSmith }) | const { tracing_config: langSmithConfig, has_not_configured: langSmithHasNotConfig } = await doFetchTracingConfig({ appId, provider: TracingProvider.langSmith }) | ||||
| const { tracing_config: opikConfig, has_not_configured: OpikHasNotConfig } = await doFetchTracingConfig({ appId, provider: TracingProvider.opik }) | const { tracing_config: opikConfig, has_not_configured: OpikHasNotConfig } = await doFetchTracingConfig({ appId, provider: TracingProvider.opik }) | ||||
| if (!OpikHasNotConfig) | if (!OpikHasNotConfig) | ||||
| setOpikConfig(opikConfig as OpikConfig) | setOpikConfig(opikConfig as OpikConfig) | ||||
| const { tracing_config: weaveConfig, has_not_configured: weaveHasNotConfig } = await doFetchTracingConfig({ appId, provider: TracingProvider.weave }) | |||||
| if (!weaveHasNotConfig) | |||||
| setWeaveConfig(weaveConfig as WeaveConfig) | |||||
| } | } | ||||
| const handleTracingConfigUpdated = async (provider: TracingProvider) => { | const handleTracingConfigUpdated = async (provider: TracingProvider) => { | ||||
| setLangFuseConfig(tracing_config as LangFuseConfig) | setLangFuseConfig(tracing_config as LangFuseConfig) | ||||
| else if (provider === TracingProvider.opik) | else if (provider === TracingProvider.opik) | ||||
| setOpikConfig(tracing_config as OpikConfig) | setOpikConfig(tracing_config as OpikConfig) | ||||
| else if (provider === TracingProvider.weave) | |||||
| setWeaveConfig(tracing_config as WeaveConfig) | |||||
| } | } | ||||
| const handleTracingConfigRemoved = (provider: TracingProvider) => { | const handleTracingConfigRemoved = (provider: TracingProvider) => { | ||||
| setLangFuseConfig(null) | setLangFuseConfig(null) | ||||
| else if (provider === TracingProvider.opik) | else if (provider === TracingProvider.opik) | ||||
| setOpikConfig(null) | setOpikConfig(null) | ||||
| else if (provider === TracingProvider.weave) | |||||
| setWeaveConfig(null) | |||||
| if (provider === inUseTracingProvider) { | if (provider === inUseTracingProvider) { | ||||
| handleTracingStatusChange({ | handleTracingStatusChange({ | ||||
| enabled: false, | enabled: false, | ||||
| langSmithConfig={langSmithConfig} | langSmithConfig={langSmithConfig} | ||||
| langFuseConfig={langFuseConfig} | langFuseConfig={langFuseConfig} | ||||
| opikConfig={opikConfig} | opikConfig={opikConfig} | ||||
| weaveConfig={weaveConfig} | |||||
| onConfigUpdated={handleTracingConfigUpdated} | onConfigUpdated={handleTracingConfigUpdated} | ||||
| onConfigRemoved={handleTracingConfigRemoved} | onConfigRemoved={handleTracingConfigRemoved} | ||||
| controlShowPopup={controlShowPopup} | controlShowPopup={controlShowPopup} | ||||
| langSmithConfig={langSmithConfig} | langSmithConfig={langSmithConfig} | ||||
| langFuseConfig={langFuseConfig} | langFuseConfig={langFuseConfig} | ||||
| opikConfig={opikConfig} | opikConfig={opikConfig} | ||||
| weaveConfig={weaveConfig} | |||||
| onConfigUpdated={handleTracingConfigUpdated} | onConfigUpdated={handleTracingConfigUpdated} | ||||
| onConfigRemoved={handleTracingConfigRemoved} | onConfigRemoved={handleTracingConfigRemoved} | ||||
| controlShowPopup={controlShowPopup} | controlShowPopup={controlShowPopup} |
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { useBoolean } from 'ahooks' | import { useBoolean } from 'ahooks' | ||||
| import Field from './field' | import Field from './field' | ||||
| import type { LangFuseConfig, LangSmithConfig, OpikConfig } from './type' | |||||
| import type { LangFuseConfig, LangSmithConfig, OpikConfig, WeaveConfig } from './type' | |||||
| import { TracingProvider } from './type' | import { TracingProvider } from './type' | ||||
| import { docURL } from './config' | import { docURL } from './config' | ||||
| import { | import { | ||||
| type Props = { | type Props = { | ||||
| appId: string | appId: string | ||||
| type: TracingProvider | type: TracingProvider | ||||
| payload?: LangSmithConfig | LangFuseConfig | OpikConfig | null | |||||
| payload?: LangSmithConfig | LangFuseConfig | OpikConfig | WeaveConfig | null | |||||
| onRemoved: () => void | onRemoved: () => void | ||||
| onCancel: () => void | onCancel: () => void | ||||
| onSaved: (payload: LangSmithConfig | LangFuseConfig | OpikConfig) => void | |||||
| onSaved: (payload: LangSmithConfig | LangFuseConfig | OpikConfig | WeaveConfig) => void | |||||
| onChosen: (provider: TracingProvider) => void | onChosen: (provider: TracingProvider) => void | ||||
| } | } | ||||
| workspace: '', | workspace: '', | ||||
| } | } | ||||
| const weaveConfigTemplate = { | |||||
| api_key: '', | |||||
| entity: '', | |||||
| project: '', | |||||
| endpoint: '', | |||||
| } | |||||
| const ProviderConfigModal: FC<Props> = ({ | const ProviderConfigModal: FC<Props> = ({ | ||||
| appId, | appId, | ||||
| type, | type, | ||||
| const isEdit = !!payload | const isEdit = !!payload | ||||
| const isAdd = !isEdit | const isAdd = !isEdit | ||||
| const [isSaving, setIsSaving] = useState(false) | const [isSaving, setIsSaving] = useState(false) | ||||
| const [config, setConfig] = useState<LangSmithConfig | LangFuseConfig | OpikConfig>((() => { | |||||
| const [config, setConfig] = useState<LangSmithConfig | LangFuseConfig | OpikConfig | WeaveConfig>((() => { | |||||
| if (isEdit) | if (isEdit) | ||||
| return payload | return payload | ||||
| else if (type === TracingProvider.langfuse) | else if (type === TracingProvider.langfuse) | ||||
| return langFuseConfigTemplate | return langFuseConfigTemplate | ||||
| return opikConfigTemplate | |||||
| else if (type === TracingProvider.opik) | |||||
| return opikConfigTemplate | |||||
| return weaveConfigTemplate | |||||
| })()) | })()) | ||||
| const [isShowRemoveConfirm, { | const [isShowRemoveConfirm, { | ||||
| setTrue: showRemoveConfirm, | setTrue: showRemoveConfirm, | ||||
| // const postData = config as OpikConfig | // const postData = config as OpikConfig | ||||
| } | } | ||||
| if (type === TracingProvider.weave) { | |||||
| const postData = config as WeaveConfig | |||||
| if (!errorMessage && !postData.api_key) | |||||
| errorMessage = t('common.errorMsg.fieldRequired', { field: 'API Key' }) | |||||
| if (!errorMessage && !postData.project) | |||||
| errorMessage = t('common.errorMsg.fieldRequired', { field: t(`${I18N_PREFIX}.project`) }) | |||||
| } | |||||
| return errorMessage | return errorMessage | ||||
| }, [config, t, type]) | }, [config, t, type]) | ||||
| const handleSave = useCallback(async () => { | const handleSave = useCallback(async () => { | ||||
| </div> | </div> | ||||
| <div className='space-y-4'> | <div className='space-y-4'> | ||||
| {type === TracingProvider.weave && ( | |||||
| <> | |||||
| <Field | |||||
| label='API Key' | |||||
| labelClassName='!text-sm' | |||||
| isRequired | |||||
| value={(config as WeaveConfig).api_key} | |||||
| onChange={handleConfigChange('api_key')} | |||||
| placeholder={t(`${I18N_PREFIX}.placeholder`, { key: 'API Key' })!} | |||||
| /> | |||||
| <Field | |||||
| label={t(`${I18N_PREFIX}.project`)!} | |||||
| labelClassName='!text-sm' | |||||
| isRequired | |||||
| value={(config as WeaveConfig).project} | |||||
| onChange={handleConfigChange('project')} | |||||
| placeholder={t(`${I18N_PREFIX}.placeholder`, { key: t(`${I18N_PREFIX}.project`) })!} | |||||
| /> | |||||
| <Field | |||||
| label='Entity' | |||||
| labelClassName='!text-sm' | |||||
| value={(config as WeaveConfig).entity} | |||||
| onChange={handleConfigChange('entity')} | |||||
| placeholder={t(`${I18N_PREFIX}.placeholder`, { key: 'Entity' })!} | |||||
| /> | |||||
| <Field | |||||
| label='Endpoint' | |||||
| labelClassName='!text-sm' | |||||
| value={(config as WeaveConfig).endpoint} | |||||
| onChange={handleConfigChange('endpoint')} | |||||
| placeholder={'https://trace.wandb.ai/'} | |||||
| /> | |||||
| </> | |||||
| )} | |||||
| {type === TracingProvider.langSmith && ( | {type === TracingProvider.langSmith && ( | ||||
| <> | <> | ||||
| <Field | <Field | ||||
| /> | /> | ||||
| </> | </> | ||||
| )} | )} | ||||
| </div> | </div> | ||||
| <div className='my-8 flex h-8 items-center justify-between'> | <div className='my-8 flex h-8 items-center justify-between'> | ||||
| <a | <a |
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { TracingProvider } from './type' | import { TracingProvider } from './type' | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import { LangfuseIconBig, LangsmithIconBig, OpikIconBig } from '@/app/components/base/icons/src/public/tracing' | |||||
| import { LangfuseIconBig, LangsmithIconBig, OpikIconBig, WeaveIconBig } from '@/app/components/base/icons/src/public/tracing' | |||||
| import { Eye as View } from '@/app/components/base/icons/src/vender/solid/general' | import { Eye as View } from '@/app/components/base/icons/src/vender/solid/general' | ||||
| const I18N_PREFIX = 'app.tracing' | const I18N_PREFIX = 'app.tracing' | ||||
| [TracingProvider.langSmith]: LangsmithIconBig, | [TracingProvider.langSmith]: LangsmithIconBig, | ||||
| [TracingProvider.langfuse]: LangfuseIconBig, | [TracingProvider.langfuse]: LangfuseIconBig, | ||||
| [TracingProvider.opik]: OpikIconBig, | [TracingProvider.opik]: OpikIconBig, | ||||
| [TracingProvider.weave]: WeaveIconBig, | |||||
| })[type] | })[type] | ||||
| } | } | ||||
| langSmith = 'langsmith', | langSmith = 'langsmith', | ||||
| langfuse = 'langfuse', | langfuse = 'langfuse', | ||||
| opik = 'opik', | opik = 'opik', | ||||
| weave = 'weave', | |||||
| } | } | ||||
| export type LangSmithConfig = { | export type LangSmithConfig = { | ||||
| workspace: string | workspace: string | ||||
| url: string | url: string | ||||
| } | } | ||||
| export type WeaveConfig = { | |||||
| api_key: string | |||||
| entity: string | |||||
| project: string | |||||
| endpoint: string | |||||
| } |
| // GENERATE BY script | |||||
| // DON NOT EDIT IT MANUALLY | |||||
| import * as React from 'react' | |||||
| import data from './WeaveIcon.json' | |||||
| import IconBase from '@/app/components/base/icons/IconBase' | |||||
| import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' | |||||
| const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( | |||||
| props, | |||||
| ref, | |||||
| ) => <IconBase {...props} ref={ref} data={data as IconData} />) | |||||
| Icon.displayName = 'WeaveIcon' | |||||
| export default Icon |
| // GENERATE BY script | |||||
| // DON NOT EDIT IT MANUALLY | |||||
| import * as React from 'react' | |||||
| import data from './WeaveIconBig.json' | |||||
| import IconBase from '@/app/components/base/icons/IconBase' | |||||
| import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' | |||||
| const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( | |||||
| props, | |||||
| ref, | |||||
| ) => <IconBase {...props} ref={ref} data={data as IconData} />) | |||||
| Icon.displayName = 'WeaveIconBig' | |||||
| export default Icon |
| export { default as OpikIconBig } from './OpikIconBig' | export { default as OpikIconBig } from './OpikIconBig' | ||||
| export { default as OpikIcon } from './OpikIcon' | export { default as OpikIcon } from './OpikIcon' | ||||
| export { default as TracingIcon } from './TracingIcon' | export { default as TracingIcon } from './TracingIcon' | ||||
| export { default as WeaveIconBig } from './WeaveIconBig' | |||||
| export { default as WeaveIcon } from './WeaveIcon' |
| title: 'Opik', | title: 'Opik', | ||||
| description: 'Opik is an open-source platform for evaluating, testing, and monitoring LLM applications.', | description: 'Opik is an open-source platform for evaluating, testing, and monitoring LLM applications.', | ||||
| }, | }, | ||||
| weave: { | |||||
| title: 'Weave', | |||||
| description: 'Weave is an open-source platform for evaluating, testing, and monitoring LLM applications.', | |||||
| }, | |||||
| inUse: 'In use', | inUse: 'In use', | ||||
| configProvider: { | configProvider: { | ||||
| title: 'Config ', | title: 'Config ', |
| import type { LangFuseConfig, LangSmithConfig, OpikConfig, TracingProvider } from '@/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/type' | |||||
| import type { App, AppMode, AppSSO, AppTemplate, SiteConfig } from '@/types/app' | |||||
| import type { LangFuseConfig, LangSmithConfig, OpikConfig, TracingProvider, WeaveConfig } from '@/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/type' | |||||
| import type { App, AppSSO, AppTemplate, SiteConfig } from '@/types/app' | |||||
| import type { Dependency } from '@/app/components/plugins/types' | import type { Dependency } from '@/app/components/plugins/types' | ||||
| export enum DSLImportMode { | export enum DSLImportMode { | ||||
| export type TracingConfig = { | export type TracingConfig = { | ||||
| tracing_provider: TracingProvider | tracing_provider: TracingProvider | ||||
| tracing_config: LangSmithConfig | LangFuseConfig | OpikConfig | |||||
| tracing_config: LangSmithConfig | LangFuseConfig | OpikConfig | WeaveConfig | |||||
| } | } |