chore: import upstream snapshot with attribution
Integ / changes (push) Has been skipped
Pre-commit / pre-commit (push) Failing after 1s
CLI exit codes / changes (push) Has been skipped
Test (Install) / changes (push) Has been skipped
Test (Python) / changes (push) Has been skipped
Test (TypeScript) / changes (push) Has been skipped
CLI exit codes / cli-gate (push) Has been cancelled
Test (Install) / test-install-gate (push) Has been cancelled
Integ / integ-gate (push) Has been cancelled
Test (Python) / test-python-gate (push) Has been cancelled
Test (TypeScript) / test-typescript-gate (push) Has been cancelled
Test (Install) / python-minimal (3.12) (push) Has been cancelled
Test (Install) / python-minimal (3.11) (push) Has been cancelled
Test (Install) / python-extra (agno, mirage.agents.agno) (push) Has been cancelled
Test (Install) / python-extra (chroma, mirage.resource.chroma) (push) Has been cancelled
Test (Install) / python-extra (pdf, mirage.core.filetype.pdf) (push) Has been cancelled
Integ / integ (push) Has been cancelled
Integ / integ-database (push) Has been cancelled
Integ / integ-database-ts (push) Has been cancelled
Integ / integ-data (push) Has been cancelled
Integ / integ-ssh (push) Has been cancelled
Integ / integ-ssh-ts (push) Has been cancelled
Test (Python) / audit (push) Has been cancelled
Test (TypeScript) / test (push) Has been cancelled
Test (TypeScript) / python-fs-shim (push) Has been cancelled
CLI exit codes / Python CLI (push) Has been cancelled
CLI exit codes / TypeScript CLI (push) Has been cancelled
CLI exit codes / Cross-language snapshot interop (push) Has been cancelled
Test (Python) / test (push) Has been cancelled
Test (Python) / import-isolation (deepagents, openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Python) / import-isolation (deepagents, pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Integ / integ-ts (push) Has been cancelled
Integ / integ-fuse (push) Has been cancelled
Test (Install) / python-extra (databricks, mirage.resource.databricks_volume) (push) Has been cancelled
Test (Install) / python-extra (deepagents, mirage.agents.langchain) (push) Has been cancelled
Test (Install) / python-extra (email, mirage.resource.email) (push) Has been cancelled
Test (Install) / python-extra (fuse, mirage.fuse.mount) (push) Has been cancelled
Test (Install) / python-extra (hdf5, mirage.core.filetype.hdf5) (push) Has been cancelled
Test (Install) / python-extra (hf, mirage.resource.hf_buckets) (push) Has been cancelled
Test (Install) / python-extra (lancedb, mirage.resource.lancedb) (push) Has been cancelled
Test (Install) / python-extra (langfuse, mirage.resource.langfuse) (push) Has been cancelled
Test (Install) / python-extra (mongodb, mirage.resource.mongodb) (push) Has been cancelled
Test (Install) / python-extra (nextcloud, mirage.resource.nextcloud) (push) Has been cancelled
Test (Install) / python-extra (openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Install) / python-extra (openhands, mirage.agents.openhands, 3.12) (push) Has been cancelled
Test (Install) / python-extra (parquet, mirage.core.filetype.parquet) (push) Has been cancelled
Test (Install) / python-extra (postgres, mirage.resource.postgres) (push) Has been cancelled
Test (Install) / python-extra (pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Test (Install) / python-extra (qdrant, mirage.resource.qdrant) (push) Has been cancelled
Test (Install) / python-extra (redis, mirage.resource.redis) (push) Has been cancelled
Test (Install) / python-extra (s3, mirage.resource.s3) (push) Has been cancelled
Test (Install) / python-extra (ssh, mirage.resource.ssh) (push) Has been cancelled
Test (Install) / ts-minimal (push) Has been cancelled
Integ / changes (push) Has been skipped
Pre-commit / pre-commit (push) Failing after 1s
CLI exit codes / changes (push) Has been skipped
Test (Install) / changes (push) Has been skipped
Test (Python) / changes (push) Has been skipped
Test (TypeScript) / changes (push) Has been skipped
CLI exit codes / cli-gate (push) Has been cancelled
Test (Install) / test-install-gate (push) Has been cancelled
Integ / integ-gate (push) Has been cancelled
Test (Python) / test-python-gate (push) Has been cancelled
Test (TypeScript) / test-typescript-gate (push) Has been cancelled
Test (Install) / python-minimal (3.12) (push) Has been cancelled
Test (Install) / python-minimal (3.11) (push) Has been cancelled
Test (Install) / python-extra (agno, mirage.agents.agno) (push) Has been cancelled
Test (Install) / python-extra (chroma, mirage.resource.chroma) (push) Has been cancelled
Test (Install) / python-extra (pdf, mirage.core.filetype.pdf) (push) Has been cancelled
Integ / integ (push) Has been cancelled
Integ / integ-database (push) Has been cancelled
Integ / integ-database-ts (push) Has been cancelled
Integ / integ-data (push) Has been cancelled
Integ / integ-ssh (push) Has been cancelled
Integ / integ-ssh-ts (push) Has been cancelled
Test (Python) / audit (push) Has been cancelled
Test (TypeScript) / test (push) Has been cancelled
Test (TypeScript) / python-fs-shim (push) Has been cancelled
CLI exit codes / Python CLI (push) Has been cancelled
CLI exit codes / TypeScript CLI (push) Has been cancelled
CLI exit codes / Cross-language snapshot interop (push) Has been cancelled
Test (Python) / test (push) Has been cancelled
Test (Python) / import-isolation (deepagents, openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Python) / import-isolation (deepagents, pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Integ / integ-ts (push) Has been cancelled
Integ / integ-fuse (push) Has been cancelled
Test (Install) / python-extra (databricks, mirage.resource.databricks_volume) (push) Has been cancelled
Test (Install) / python-extra (deepagents, mirage.agents.langchain) (push) Has been cancelled
Test (Install) / python-extra (email, mirage.resource.email) (push) Has been cancelled
Test (Install) / python-extra (fuse, mirage.fuse.mount) (push) Has been cancelled
Test (Install) / python-extra (hdf5, mirage.core.filetype.hdf5) (push) Has been cancelled
Test (Install) / python-extra (hf, mirage.resource.hf_buckets) (push) Has been cancelled
Test (Install) / python-extra (lancedb, mirage.resource.lancedb) (push) Has been cancelled
Test (Install) / python-extra (langfuse, mirage.resource.langfuse) (push) Has been cancelled
Test (Install) / python-extra (mongodb, mirage.resource.mongodb) (push) Has been cancelled
Test (Install) / python-extra (nextcloud, mirage.resource.nextcloud) (push) Has been cancelled
Test (Install) / python-extra (openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Install) / python-extra (openhands, mirage.agents.openhands, 3.12) (push) Has been cancelled
Test (Install) / python-extra (parquet, mirage.core.filetype.parquet) (push) Has been cancelled
Test (Install) / python-extra (postgres, mirage.resource.postgres) (push) Has been cancelled
Test (Install) / python-extra (pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Test (Install) / python-extra (qdrant, mirage.resource.qdrant) (push) Has been cancelled
Test (Install) / python-extra (redis, mirage.resource.redis) (push) Has been cancelled
Test (Install) / python-extra (s3, mirage.resource.s3) (push) Has been cancelled
Test (Install) / python-extra (ssh, mirage.resource.ssh) (push) Has been cancelled
Test (Install) / ts-minimal (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import time
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from mirage import MountMode, Workspace
|
||||
from mirage.resource.langfuse import LangfuseConfig, LangfuseResource
|
||||
|
||||
load_dotenv(".env.development")
|
||||
|
||||
config = LangfuseConfig(
|
||||
public_key=os.environ["LANGFUSE_PUBLIC_KEY"],
|
||||
secret_key=os.environ["LANGFUSE_SECRET_KEY"],
|
||||
host=os.environ["LANGFUSE_HOST"],
|
||||
default_trace_limit=20,
|
||||
)
|
||||
resource = LangfuseResource(config=config)
|
||||
|
||||
|
||||
async def _run(ws, cmd):
|
||||
print(f"\n>>> {cmd}")
|
||||
r = await ws.execute(cmd)
|
||||
out = (await r.stdout_str()).strip()
|
||||
err = await r.stderr_str()
|
||||
if out:
|
||||
for line in out.splitlines()[:10]:
|
||||
print(f" {line[:120]}")
|
||||
total = len(out.splitlines())
|
||||
if total > 10:
|
||||
print(f" ... ({total} lines total)")
|
||||
if err:
|
||||
print(f" [stderr] {err.strip()[:120]}")
|
||||
if not out and not err:
|
||||
print(f" (empty, exit={r.exit_code})")
|
||||
return r
|
||||
|
||||
|
||||
async def _timed(ws, cmd):
|
||||
start = time.perf_counter()
|
||||
out = await (await ws.execute(cmd)).stdout_str()
|
||||
return (time.perf_counter() - start) * 1000, out
|
||||
|
||||
|
||||
async def main():
|
||||
ws = Workspace({"/langfuse": resource}, mode=MountMode.READ)
|
||||
|
||||
print("=== not-found errors show the full virtual path ===")
|
||||
for cmd in ("cat /langfuse/__nf_missing__.txt",
|
||||
"head /langfuse/__nf_missing__.txt",
|
||||
"stat /langfuse/__nf_missing__.txt"):
|
||||
result = await ws.execute(cmd)
|
||||
print(f"$ {cmd}")
|
||||
print(f" exit={result.exit_code} "
|
||||
f"{(await result.stderr_str()).strip()}")
|
||||
|
||||
print("=" * 60)
|
||||
print("LS across all directories")
|
||||
print("=" * 60)
|
||||
|
||||
await _run(ws, "ls /langfuse/")
|
||||
await _run(ws, "ls /langfuse/traces/")
|
||||
await _run(ws, "ls /langfuse/sessions/")
|
||||
await _run(ws, "ls /langfuse/prompts/")
|
||||
await _run(ws, "ls /langfuse/datasets/")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("CAT across different resource types")
|
||||
print("=" * 60)
|
||||
|
||||
r = await ws.execute("ls /langfuse/traces/")
|
||||
traces_out = (await r.stdout_str()).strip()
|
||||
trace_files = [f for f in traces_out.splitlines() if f.strip()]
|
||||
if trace_files:
|
||||
tp = f"/langfuse/traces/{trace_files[0].strip()}"
|
||||
await _run(ws, f'cat "{tp}" | head -n 5')
|
||||
else:
|
||||
print(" no traces found, skipping cat trace")
|
||||
|
||||
await _run(ws, 'cat "/langfuse/prompts/summarize/1.json"')
|
||||
await _run(ws, 'cat "/langfuse/datasets/qa-eval/items.jsonl"')
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("GREP across different scopes")
|
||||
print("=" * 60)
|
||||
|
||||
await _run(ws, 'grep "chat" "/langfuse/traces/"')
|
||||
|
||||
await _run(ws, 'grep "support" "/langfuse/traces/"')
|
||||
|
||||
await _run(ws, 'grep "chat-session" "/langfuse/sessions/"')
|
||||
|
||||
await _run(ws, 'grep "summarize" "/langfuse/prompts/"')
|
||||
|
||||
await _run(ws, 'grep "qa" "/langfuse/datasets/"')
|
||||
|
||||
if trace_files:
|
||||
tp = f"/langfuse/traces/{trace_files[0].strip()}"
|
||||
await _run(ws, f'grep "name" "{tp}"')
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("JQ across different resource types")
|
||||
print("=" * 60)
|
||||
|
||||
if trace_files:
|
||||
tp = f"/langfuse/traces/{trace_files[0].strip()}"
|
||||
await _run(ws, f'jq ".name" "{tp}"')
|
||||
await _run(ws, f'jq ".session_id" "{tp}"')
|
||||
await _run(ws, f'jq ".input" "{tp}"')
|
||||
|
||||
await _run(
|
||||
ws,
|
||||
'jq ".prompt" "/langfuse/prompts/summarize/1.json"',
|
||||
)
|
||||
await _run(
|
||||
ws,
|
||||
'jq ".config" "/langfuse/prompts/classify/1.json"',
|
||||
)
|
||||
|
||||
await _run(
|
||||
ws,
|
||||
'jq ".[] | .input" '
|
||||
'"/langfuse/datasets/qa-eval/items.jsonl"',
|
||||
)
|
||||
await _run(
|
||||
ws,
|
||||
'jq -r ".[] | .expected_output.answer" '
|
||||
'"/langfuse/datasets/qa-eval/items.jsonl"',
|
||||
)
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("SESSION browsing")
|
||||
print("=" * 60)
|
||||
|
||||
await _run(ws, "ls /langfuse/sessions/chat-session-001/")
|
||||
|
||||
r = await ws.execute("ls /langfuse/sessions/chat-session-001/", )
|
||||
session_traces = (await r.stdout_str()).strip().splitlines()
|
||||
if session_traces:
|
||||
st = session_traces[0].strip()
|
||||
sp = f"/langfuse/sessions/chat-session-001/{st}"
|
||||
await _run(ws, f'cat "{sp}" | head -n 3')
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("PROMPTS and DATASETS detail")
|
||||
print("=" * 60)
|
||||
|
||||
await _run(ws, "ls /langfuse/prompts/summarize/")
|
||||
await _run(ws, "ls /langfuse/datasets/qa-eval/")
|
||||
await _run(ws, "ls /langfuse/datasets/qa-eval/runs/")
|
||||
|
||||
await _run(ws, 'stat "/langfuse/prompts/summarize"')
|
||||
await _run(ws, 'stat "/langfuse/datasets/qa-eval"')
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("TREE, FIND, NAVIGATION")
|
||||
print("=" * 60)
|
||||
|
||||
await _run(ws, "tree -L 2 /langfuse/")
|
||||
await _run(
|
||||
ws,
|
||||
'find "/langfuse/prompts/" -name "*.json"',
|
||||
)
|
||||
# -path matches the display path; -size counts dirs and sizeless
|
||||
# rendered files as 0 (so +0c drops them, -1k keeps them).
|
||||
await _run(ws, 'find "/langfuse/" -maxdepth 1 -path "*prompts*"')
|
||||
await _run(ws, 'find "/langfuse/" -maxdepth 1 -size +0c')
|
||||
await _run(ws, 'find "/langfuse/" -maxdepth 1 -size -1k')
|
||||
|
||||
await ws.execute('cd "/langfuse/prompts"')
|
||||
await _run(ws, "pwd")
|
||||
await _run(ws, "ls")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("CACHING: warm reads served from cache (no backend fetch)")
|
||||
print("=" * 60)
|
||||
r = await ws.execute('find "/langfuse/prompts/" -name "*.json"')
|
||||
prompt_files = (await r.stdout_str()).strip().splitlines()
|
||||
if prompt_files:
|
||||
cache_file = prompt_files[0].strip()
|
||||
cold_ms, body = await _timed(ws, f'cat "{cache_file}"')
|
||||
warm_ms, _ = await _timed(ws, f'cat "{cache_file}"')
|
||||
grep_ms, _ = await _timed(ws, f'grep . "{cache_file}"')
|
||||
head_ms, _ = await _timed(ws, f'head -n 1 "{cache_file}"')
|
||||
tail_ms, _ = await _timed(ws, f'tail -n 1 "{cache_file}"')
|
||||
wc_ms, _ = await _timed(ws, f'wc -l "{cache_file}"')
|
||||
print(f" file={cache_file} size={len(body)}B")
|
||||
print(
|
||||
f" cold cat={cold_ms:.0f}ms warm cat={warm_ms:.0f}ms "
|
||||
f"grep={grep_ms:.0f}ms head={head_ms:.0f}ms tail={tail_ms:.0f}ms "
|
||||
f"wc={wc_ms:.0f}ms")
|
||||
print(f" served_from_cache={warm_ms < cold_ms / 5} "
|
||||
f"(warm speedup {cold_ms / max(warm_ms, 0.001):.0f}x)")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("GLOB: mid-path patterns walk segment by segment")
|
||||
print("=" * 60)
|
||||
r = await ws.execute("echo /langfuse/prom*/*")
|
||||
out = (await r.stdout_str()).strip()
|
||||
print(f" echo /langfuse/prom*/* -> {out[:200]}")
|
||||
assert "/langfuse/prompts/" in out, "mid-path glob did not expand"
|
||||
|
||||
# A glob that matches nothing stays the literal word, so the
|
||||
# command reports it like GNU coreutils.
|
||||
r = await ws.execute("cat /langfuse/zz-none-*/x.json")
|
||||
err = (await r.stderr_str()).strip()
|
||||
print(f" cat /langfuse/zz-none-*/x.json -> exit={r.exit_code} "
|
||||
f"{err[:120]}")
|
||||
assert r.exit_code == 1 and "zz-none-*" in err
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,90 @@
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from mirage import Mount, MountMode, Workspace
|
||||
from mirage.resource.langfuse import LangfuseConfig, LangfuseResource
|
||||
|
||||
load_dotenv(".env.development")
|
||||
|
||||
config = LangfuseConfig(
|
||||
public_key=os.environ["LANGFUSE_PUBLIC_KEY"],
|
||||
secret_key=os.environ["LANGFUSE_SECRET_KEY"],
|
||||
host=os.environ["LANGFUSE_HOST"],
|
||||
)
|
||||
resource = LangfuseResource(config=config)
|
||||
|
||||
with Workspace({"/langfuse/": Mount(resource, mode=MountMode.READ,
|
||||
fuse=True)}) as ws:
|
||||
mp = ws.fuse_mountpoint
|
||||
|
||||
print(f"=== FUSE MODE: mounted at {mp} ===\n")
|
||||
|
||||
print("--- os.listdir() top-level ---")
|
||||
top_level = os.listdir(mp)
|
||||
for entry in top_level:
|
||||
print(f" {entry}")
|
||||
|
||||
if not top_level:
|
||||
print(" no entries found")
|
||||
else:
|
||||
print("\n--- os.listdir() traces ---")
|
||||
traces = os.listdir(f"{mp}/traces")
|
||||
for t in traces[:5]:
|
||||
print(f" {t}")
|
||||
if len(traces) > 5:
|
||||
print(f" ... ({len(traces)} total)")
|
||||
|
||||
if traces:
|
||||
first_trace = traces[0]
|
||||
path = f"{mp}/traces/{first_trace}"
|
||||
print(f"\n--- open() + read {first_trace} ---")
|
||||
with open(path) as f:
|
||||
content = f.read().strip()
|
||||
if content:
|
||||
try:
|
||||
doc = json.loads(content)
|
||||
print(f" name: {doc.get('name', '?')}")
|
||||
print(f" id: {doc.get('id', '?')}")
|
||||
except json.JSONDecodeError:
|
||||
for line in content.splitlines()[:5]:
|
||||
print(f" {line[:120]}")
|
||||
else:
|
||||
print(" (empty)")
|
||||
|
||||
print("\n--- os.listdir() prompts ---")
|
||||
prompts = os.listdir(f"{mp}/prompts")
|
||||
for p in prompts:
|
||||
print(f" {p}")
|
||||
|
||||
print("\n--- os.listdir() datasets ---")
|
||||
datasets = os.listdir(f"{mp}/datasets")
|
||||
for d in datasets:
|
||||
print(f" {d}")
|
||||
|
||||
print(f"\n>>> FUSE mounted at: {mp}")
|
||||
print(">>> Open another terminal and run:")
|
||||
print(f">>> ls {mp}/")
|
||||
print(f">>> cat {mp}/traces/<trace-id>.json")
|
||||
print(">>> Press Enter to unmount and exit...")
|
||||
input()
|
||||
|
||||
records = ws.ops.records
|
||||
total = sum(r.bytes for r in records)
|
||||
print(f"\nStats: {len(records)} ops, "
|
||||
f"{total} bytes transferred")
|
||||
@@ -0,0 +1,106 @@
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from mirage import MountMode, Workspace
|
||||
from mirage.resource.langfuse import LangfuseConfig, LangfuseResource
|
||||
|
||||
load_dotenv(".env.development")
|
||||
|
||||
config = LangfuseConfig(
|
||||
public_key=os.environ["LANGFUSE_PUBLIC_KEY"],
|
||||
secret_key=os.environ["LANGFUSE_SECRET_KEY"],
|
||||
host=os.environ["LANGFUSE_HOST"],
|
||||
)
|
||||
resource = LangfuseResource(config=config)
|
||||
|
||||
|
||||
async def main():
|
||||
with Workspace({"/langfuse/": resource}, mode=MountMode.READ) as ws:
|
||||
vos = sys.modules["os"]
|
||||
print("=== VFS MODE: open() reads from Langfuse ===\n")
|
||||
|
||||
print("--- os.listdir() top-level ---")
|
||||
top_level = vos.listdir("/langfuse")
|
||||
for entry in top_level:
|
||||
print(f" {entry}")
|
||||
|
||||
print("\n--- os.listdir() traces ---")
|
||||
traces = vos.listdir("/langfuse/traces")
|
||||
for t in traces[:5]:
|
||||
print(f" {t}")
|
||||
if len(traces) > 5:
|
||||
print(f" ... ({len(traces)} total)")
|
||||
|
||||
if not traces:
|
||||
print(" no traces found")
|
||||
return
|
||||
|
||||
first_trace = traces[0]
|
||||
path = f"/langfuse/traces/{first_trace}"
|
||||
print(f"\n--- open() + read {first_trace} ---")
|
||||
with open(path) as f:
|
||||
content = f.read()
|
||||
try:
|
||||
doc = json.loads(content)
|
||||
print(f" name: {doc.get('name', '?')}")
|
||||
print(f" id: {doc.get('id', '?')}")
|
||||
sid = doc.get("sessionId", doc.get("session_id", "?"))
|
||||
print(f" session_id: {sid}")
|
||||
except json.JSONDecodeError:
|
||||
for line in content.splitlines()[:5]:
|
||||
print(f" {line[:120]}")
|
||||
|
||||
print("\n--- os.listdir() sessions ---")
|
||||
sessions = vos.listdir("/langfuse/sessions")
|
||||
for s in sessions:
|
||||
print(f" {s}")
|
||||
|
||||
print("\n--- os.listdir() prompts ---")
|
||||
prompts = vos.listdir("/langfuse/prompts")
|
||||
for p in prompts:
|
||||
print(f" {p}")
|
||||
|
||||
print("\n--- os.listdir() datasets ---")
|
||||
datasets = vos.listdir("/langfuse/datasets")
|
||||
for d in datasets:
|
||||
print(f" {d}")
|
||||
|
||||
if datasets:
|
||||
ds = datasets[0]
|
||||
print(f"\n--- os.listdir() datasets/{ds} ---")
|
||||
items = vos.listdir(f"/langfuse/datasets/{ds}")
|
||||
for item in items:
|
||||
print(f" {item}")
|
||||
|
||||
print("\n--- bash history ---")
|
||||
with open("/.bash_history") as f:
|
||||
for i, line in enumerate(f):
|
||||
if i >= 6:
|
||||
break
|
||||
print(f" {line.rstrip()[:120]}")
|
||||
|
||||
records = ws.ops.records
|
||||
total = sum(r.bytes for r in records)
|
||||
print(f"\nStats: {len(records)} ops, "
|
||||
f"{total} bytes transferred")
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,318 @@
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from langfuse import Langfuse, propagate_attributes
|
||||
|
||||
load_dotenv("/Users/zecheng/strukto/mirage/.env.development")
|
||||
|
||||
langfuse = Langfuse(
|
||||
public_key=os.environ["LANGFUSE_PUBLIC_KEY"],
|
||||
secret_key=os.environ["LANGFUSE_SECRET_KEY"],
|
||||
host=os.environ["LANGFUSE_HOST"],
|
||||
)
|
||||
|
||||
print("Auth check:", langfuse.auth_check())
|
||||
|
||||
print("\n=== Creating prompts ===")
|
||||
|
||||
for name, prompt_text, cfg, label in [
|
||||
("summarize",
|
||||
"Summarize the following text in {{style}} style:\n\n{{text}}", {
|
||||
"model": "gpt-4o",
|
||||
"temperature": 0.3
|
||||
}, "production"),
|
||||
("summarize",
|
||||
"You are an expert summarizer. Summarize in {{style}} style:\n\n{{text}}",
|
||||
{
|
||||
"model": "gpt-4o",
|
||||
"temperature": 0.2
|
||||
}, "staging"),
|
||||
("classify",
|
||||
"Classify the sentiment as positive, negative, or neutral:\n\n{{text}}", {
|
||||
"model": "gpt-4o-mini",
|
||||
"temperature": 0
|
||||
}, "production"),
|
||||
("extract-entities",
|
||||
"Extract all named entities. Return as JSON.\n\n{{text}}", {
|
||||
"model": "gpt-4o",
|
||||
"temperature": 0
|
||||
}, "production"),
|
||||
]:
|
||||
langfuse.create_prompt(
|
||||
name=name,
|
||||
type="text",
|
||||
prompt=prompt_text,
|
||||
config=cfg,
|
||||
labels=[label],
|
||||
)
|
||||
print(f" created: {name} [{label}]")
|
||||
|
||||
print("\n=== Creating traces ===")
|
||||
|
||||
traces_data = [
|
||||
{
|
||||
"trace_name": "chat-completion",
|
||||
"session_id": "chat-session-001",
|
||||
"user_id": "user-alice",
|
||||
"tags": ["chat", "geography"],
|
||||
"input": {
|
||||
"messages": [{
|
||||
"role": "user",
|
||||
"content": "What is the capital of France?"
|
||||
}]
|
||||
},
|
||||
"output": {
|
||||
"response": "The capital of France is Paris."
|
||||
},
|
||||
"model": "gpt-4o",
|
||||
},
|
||||
{
|
||||
"trace_name": "chat-completion",
|
||||
"session_id": "chat-session-001",
|
||||
"user_id": "user-alice",
|
||||
"tags": ["chat", "geography"],
|
||||
"input": {
|
||||
"messages": [{
|
||||
"role": "user",
|
||||
"content": "Tell me more about Paris"
|
||||
}]
|
||||
},
|
||||
"output": {
|
||||
"response":
|
||||
"Paris is known for the Eiffel Tower and Louvre Museum."
|
||||
},
|
||||
"model": "gpt-4o",
|
||||
},
|
||||
{
|
||||
"trace_name": "chat-completion",
|
||||
"session_id": "chat-session-002",
|
||||
"user_id": "user-bob",
|
||||
"tags": ["chat", "science"],
|
||||
"input": {
|
||||
"messages": [{
|
||||
"role": "user",
|
||||
"content": "Explain quantum computing"
|
||||
}]
|
||||
},
|
||||
"output": {
|
||||
"response":
|
||||
"Quantum computing uses qubits that can be in superposition..."
|
||||
},
|
||||
"model": "gpt-4o",
|
||||
},
|
||||
{
|
||||
"trace_name": "summarize-document",
|
||||
"session_id": "chat-session-002",
|
||||
"user_id": "user-bob",
|
||||
"tags": ["summarization", "science"],
|
||||
"input": {
|
||||
"text": "A long research paper about quantum computing..."
|
||||
},
|
||||
"output": {
|
||||
"summary":
|
||||
"This paper introduces a novel approach to error correction..."
|
||||
},
|
||||
"model": "gpt-4o",
|
||||
},
|
||||
{
|
||||
"trace_name": "support-classify",
|
||||
"session_id": "support-ticket-101",
|
||||
"user_id": "user-charlie",
|
||||
"tags": ["support", "classification"],
|
||||
"input": {
|
||||
"text": "I can't log in, keeps showing error 403"
|
||||
},
|
||||
"output": {
|
||||
"category": "authentication",
|
||||
"priority": "high"
|
||||
},
|
||||
"model": "gpt-4o-mini",
|
||||
},
|
||||
{
|
||||
"trace_name": "support-respond",
|
||||
"session_id": "support-ticket-101",
|
||||
"user_id": "user-charlie",
|
||||
"tags": ["support", "response"],
|
||||
"input": {
|
||||
"ticket": "Can't log in, error 403"
|
||||
},
|
||||
"output": {
|
||||
"response": "Please try clearing your browser cookies..."
|
||||
},
|
||||
"model": "gpt-4o",
|
||||
},
|
||||
{
|
||||
"trace_name": "entity-extraction",
|
||||
"user_id": "user-alice",
|
||||
"tags": ["extraction", "ner"],
|
||||
"input": {
|
||||
"text": "Apple CEO Tim Cook announced new products in Cupertino."
|
||||
},
|
||||
"output": {
|
||||
"entities": [{
|
||||
"name": "Apple",
|
||||
"type": "ORG"
|
||||
}, {
|
||||
"name": "Tim Cook",
|
||||
"type": "PERSON"
|
||||
}]
|
||||
},
|
||||
"model": "gpt-4o",
|
||||
},
|
||||
{
|
||||
"trace_name": "chat-completion",
|
||||
"user_id": "user-dave",
|
||||
"tags": ["chat", "creative"],
|
||||
"input": {
|
||||
"messages": [{
|
||||
"role": "user",
|
||||
"content": "Write a haiku about programming"
|
||||
}]
|
||||
},
|
||||
"output": {
|
||||
"response":
|
||||
"Code flows like water\n"
|
||||
"Bugs swim in the logic stream\n"
|
||||
"Debug, compile, run",
|
||||
},
|
||||
"model": "gpt-4o",
|
||||
},
|
||||
]
|
||||
|
||||
for td in traces_data:
|
||||
with propagate_attributes(
|
||||
trace_name=td["trace_name"],
|
||||
session_id=td.get("session_id"),
|
||||
user_id=td.get("user_id"),
|
||||
tags=td.get("tags"),
|
||||
metadata={"env": "production"},
|
||||
):
|
||||
with langfuse.start_as_current_observation(
|
||||
name=td["trace_name"],
|
||||
as_type="span",
|
||||
input=td["input"],
|
||||
output=td["output"],
|
||||
):
|
||||
with langfuse.start_as_current_observation(
|
||||
name=f"{td['trace_name']}-llm",
|
||||
as_type="generation",
|
||||
model=td["model"],
|
||||
input=td["input"],
|
||||
output=td["output"],
|
||||
usage_details={
|
||||
"input_tokens": 50 + len(str(td["input"])),
|
||||
"output_tokens": 30 + len(str(td["output"])),
|
||||
},
|
||||
):
|
||||
pass
|
||||
print(f" created: {td['trace_name']} "
|
||||
f"(session={td.get('session_id', '-')})")
|
||||
|
||||
print(f"\n total: {len(traces_data)} traces")
|
||||
|
||||
print("\n=== Creating datasets ===")
|
||||
|
||||
langfuse.create_dataset(name="qa-eval", description="QA evaluation")
|
||||
|
||||
qa_items = [
|
||||
({
|
||||
"question": "What is the capital of France?"
|
||||
}, {
|
||||
"answer": "Paris"
|
||||
}),
|
||||
({
|
||||
"question": "Who wrote Romeo and Juliet?"
|
||||
}, {
|
||||
"answer": "Shakespeare"
|
||||
}),
|
||||
({
|
||||
"question": "What is the speed of light?"
|
||||
}, {
|
||||
"answer": "299,792,458 m/s"
|
||||
}),
|
||||
({
|
||||
"question": "What is the largest planet?"
|
||||
}, {
|
||||
"answer": "Jupiter"
|
||||
}),
|
||||
({
|
||||
"question": "Who painted the Mona Lisa?"
|
||||
}, {
|
||||
"answer": "da Vinci"
|
||||
}),
|
||||
]
|
||||
for inp, exp in qa_items:
|
||||
langfuse.create_dataset_item(
|
||||
dataset_name="qa-eval",
|
||||
input=inp,
|
||||
expected_output=exp,
|
||||
)
|
||||
print(f" qa-eval: {len(qa_items)} items")
|
||||
|
||||
langfuse.create_dataset(name="sentiment-eval",
|
||||
description="Sentiment classification")
|
||||
|
||||
sent_items = [
|
||||
({
|
||||
"text": "I love this product!"
|
||||
}, {
|
||||
"sentiment": "positive"
|
||||
}),
|
||||
({
|
||||
"text": "Terrible experience"
|
||||
}, {
|
||||
"sentiment": "negative"
|
||||
}),
|
||||
({
|
||||
"text": "It was okay"
|
||||
}, {
|
||||
"sentiment": "neutral"
|
||||
}),
|
||||
({
|
||||
"text": "Best purchase ever"
|
||||
}, {
|
||||
"sentiment": "positive"
|
||||
}),
|
||||
({
|
||||
"text": "Completely broken"
|
||||
}, {
|
||||
"sentiment": "negative"
|
||||
}),
|
||||
]
|
||||
for inp, exp in sent_items:
|
||||
langfuse.create_dataset_item(
|
||||
dataset_name="sentiment-eval",
|
||||
input=inp,
|
||||
expected_output=exp,
|
||||
)
|
||||
print(f" sentiment-eval: {len(sent_items)} items")
|
||||
|
||||
print("\n=== Flushing ===")
|
||||
langfuse.flush()
|
||||
time.sleep(3)
|
||||
|
||||
print("\n=== Verifying ===")
|
||||
traces = langfuse.fetch_traces(limit=5)
|
||||
print(f" traces: {len(traces.data)} found")
|
||||
for t in traces.data[:3]:
|
||||
print(f" {t.name} (session={t.session_id})")
|
||||
|
||||
prompt = langfuse.get_prompt("summarize")
|
||||
print(f" summarize prompt: v{prompt.version}")
|
||||
|
||||
print("\nDone!")
|
||||
Reference in New Issue
Block a user