Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(weave): ruff: enable TRY300 #2904

Merged
merged 5 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 45 additions & 35 deletions docs/notebooks/online_monitoring.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"<!-- docusaurus_head_meta::start\n",
"---\n",
"title: Integrating with Weave - Production Dashboard\n",
"---\n",
"## <!-- docusaurus_head_meta::start\n",
"\n",
"## title: Integrating with Weave - Production Dashboard\n",
"\n",
"docusaurus_head_meta::end -->\n",
"\n",

"<!--- @wandbcode{cod-notebook} -->"
"<!--- @wandbcode{cod-notebook} -->\n"
]
},
{
Expand All @@ -23,26 +22,28 @@
"The GenAI tooling landscape is rapidly evolving - new frameworks, tools, and applications are emerging all the time. Weave aims to be a one-stop-shop for all your GenAI monitoring and evaluation needs. This also means that sometimes it is necessary to integrate with existing platforms or extend Weave to fit the specific needs of your project or organization.\n",
"\n",
"In this cookbook, we'll demonstrate how to leverage Weave's powerful APIs and functions to create a custom dashboard for production monitoring as an extension to the Traces view in Weave. We'll focus on:\n",
"* Fetching traces, costs, feedback, and other metrics from Weave\n",
"* Creating aggregate views for user feedback and cost distribution\n",
"* Creating visualizations for token usage and latency over time\n",
"\n",
"You can try out the dashboard with your own Weave project by installing streamlit and running [this production dashboard script](https://github.com/NiWaRe/agent-dev-collection)!"
"- Fetching traces, costs, feedback, and other metrics from Weave\n",
"- Creating aggregate views for user feedback and cost distribution\n",
"- Creating visualizations for token usage and latency over time\n",
"\n",
"You can try out the dashboard with your own Weave project by installing streamlit and running [this production dashboard script](https://github.com/NiWaRe/agent-dev-collection)!\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<img src=\"https://github.com/NiWaRe/knowledge-worker-weave/blob/master/screenshots/dashboard_weave_preview.jpg?raw=true\" width=\"1000\" alt=\"Example Production Dashboard with Weave\" />"
"<img src=\"https://github.com/NiWaRe/knowledge-worker-weave/blob/master/screenshots/dashboard_weave_preview.jpg?raw=true\" width=\"1000\" alt=\"Example Production Dashboard with Weave\" />\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. Setup\n",
"To follow along this tutorial you'll only need to install the following packages:"
"\n",
"To follow along this tutorial you'll only need to install the following packages:\n"
]
},
{
Expand All @@ -58,18 +59,19 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# 2. Implementation"
"# 2. Implementation\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.1 Initializing Weave Client and Defining Costs\n",
"First, we'll set up a function to initialize the Weave client and add costs for each model. \n",
"\n",
"* We have included the standard costs for many standard models but we also make it easy to add your own custom costs and custom models. In the following we'll show how to add custom costs for a few models and use the standard costs for the rest.\n",
"* The costs are calculate based on the tracked tokens for each call in Weave. For many LLM vendor libraries, we will automatically track the token usage, but it is also possible to return custom token counts for any call. See this cookbook on how to define the token count and cost calculation for a custom model - [custom cost cookbook](https://weave-docs.wandb.ai/reference/gen_notebooks/custom_model_cost#setting-up-a-model-with-weave)."
"First, we'll set up a function to initialize the Weave client and add costs for each model.\n",
"\n",
"- We have included the standard costs for many standard models but we also make it easy to add your own custom costs and custom models. In the following we'll show how to add custom costs for a few models and use the standard costs for the rest.\n",
"- The costs are calculate based on the tracked tokens for each call in Weave. For many LLM vendor libraries, we will automatically track the token usage, but it is also possible to return custom token counts for any call. See this cookbook on how to define the token count and cost calculation for a custom model - [custom cost cookbook](https://weave-docs.wandb.ai/reference/gen_notebooks/custom_model_cost#setting-up-a-model-with-weave).\n"
]
},
{
Expand Down Expand Up @@ -119,10 +121,11 @@
" prompt_token_cost=prompt_cost,\n",
" completion_token_cost=completion_cost,\n",
" )\n",
" return client\n",
" except Exception as e:\n",
" print(f\"Failed to initialize Weave client for project '{project_name}': {e}\")\n",
" return None\n",
" else:\n",
" return client\n",
"\n",
"\n",
"client = init_weave_client(PROJECT_NAME)"
Expand All @@ -133,19 +136,22 @@
"metadata": {},
"source": [
"## 2.2 Fetching Calls Data from Weave\n",
"\n",
"In order to fetch call data from Weave, we have two options:\n",
"\n",
"1. Fetching Data call-by-call\n",
"2. Using high-level APIs\n",
"\n",
"### 2.2.1 Fetching Data call-by-call\n",
"\n",
"The first option to access data from Weave is to retrieve a list of filtered calls and extract the wanted data call-by-call. For that we can use the `calls_query_stream` API to fetch the calls data from Weave:\n",
"\n",
"* `calls_query_stream` API: This API allows us to fetch the calls data from Weave.\n",
"* `filter` dictionary: This dictionary contains the filter parameters to fetch the calls data - see [here](https://weave-docs.wandb.ai/reference/python-sdk/weave/trace_server/weave.trace_server.trace_server_interface/#class-callschema) for more details.\n",
"* `expand_columns` list: This list contains the columns to expand in the calls data.\n",
"* `sort_by` list: This list contains the sorting parameters for the calls data.\n",
"* `include_costs` boolean: This boolean indicates whether to include the costs in the calls data.\n",
"* `include_feedback` boolean: This boolean indicates whether to include the feedback in the calls data."
"- `calls_query_stream` API: This API allows us to fetch the calls data from Weave.\n",
"- `filter` dictionary: This dictionary contains the filter parameters to fetch the calls data - see [here](https://weave-docs.wandb.ai/reference/python-sdk/weave/trace_server/weave.trace_server.trace_server_interface/#class-callschema) for more details.\n",
"- `expand_columns` list: This list contains the columns to expand in the calls data.\n",
"- `sort_by` list: This list contains the sorting parameters for the calls data.\n",
"- `include_costs` boolean: This boolean indicates whether to include the costs in the calls data.\n",
"- `include_feedback` boolean: This boolean indicates whether to include the feedback in the calls data.\n"
]
},
{
Expand Down Expand Up @@ -183,10 +189,11 @@
" itertools.islice(calls_stream, limit)\n",
" ) # limit the number of calls to fetch if too many\n",
" print(f\"Fetched {len(calls)} calls.\")\n",
" return calls\n",
" except Exception as e:\n",
" print(f\"Error fetching calls: {e}\")\n",
" return []\n",
" else:\n",
" return calls\n",
"\n",
"\n",
"calls = fetch_calls(client, PROJECT_NAME, datetime.now() - timedelta(days=1), True, 100)"
Expand Down Expand Up @@ -369,7 +376,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Processing the calls is very easy with the return from Weave - we'll extract the relevant information and store it in a list of dictionaries. We'll then convert the list of dictionaries to a pandas DataFrame and return it. "
"Processing the calls is very easy with the return from Weave - we'll extract the relevant information and store it in a list of dictionaries. We'll then convert the list of dictionaries to a pandas DataFrame and return it.\n"
]
},
{
Expand Down Expand Up @@ -536,8 +543,9 @@
"metadata": {},
"source": [
"### 2.2.2 Using high-level APIs\n",
"Instead of goin through every call Weave also provides high-level APIs to directly access model costs, feedback, and other metrics. \n",
"For example, for the cost, we'll use the `query_costs` API to fetch the costs of all used LLMs using in project:"
"\n",
"Instead of goin through every call Weave also provides high-level APIs to directly access model costs, feedback, and other metrics.\n",
"For example, for the cost, we'll use the `query_costs` API to fetch the costs of all used LLMs using in project:\n"
]
},
{
Expand Down Expand Up @@ -732,7 +740,8 @@
"metadata": {},
"source": [
"## 2.4 Gathering inputs and generating visualizations\n",
"Next, we can generate the visualizations using plotly. This is the most basic dashboard, but you can customize it as you like! For a more complex example, check out a Streamlit example [here](https://github.com/NiWaRe/knowledge-worker-weave/blob/master/prod_dashboard.py)."
"\n",
"Next, we can generate the visualizations using plotly. This is the most basic dashboard, but you can customize it as you like! For a more complex example, check out a Streamlit example [here](https://github.com/NiWaRe/knowledge-worker-weave/blob/master/prod_dashboard.py).\n"
]
},
{
Expand Down Expand Up @@ -2728,16 +2737,17 @@
"metadata": {},
"source": [
"# Conclusion\n",
"\n",
"In this cookbook, we demonstrated how to create a custom production monitoring dashboard using Weave's APIs and functions. Weave currently focuses on fast integrations for easy input of data as well as extraction of the data for custom processes.\n",
"\n",
"* **Data Input:** \n",
" * Framework-agnostic tracing with [@weave-op()](https://weave-docs.wandb.ai/quickstart#2-log-a-trace-to-a-new-project) decorator and the possibility to import calls from CSV (see related [import cookbook](https://weave-docs.wandb.ai/reference/gen_notebooks/import_from_csv))\n",
" * Service API endpoints to log to Weave from for various programming frameworks and languages, see [here](https://weave-docs.wandb.ai/reference/service-api/call-start-call-start-post) for more details.\n",
"* **Data Output:**\n",
" * Easy download of the data in CSV, TSV, JSONL, JSON formats - see [here](https://weave-docs.wandb.ai/guides/tracking/tracing#querying--exporting-calls) for more details.\n",
" * Easy export using programmatic access to the data - see \"Use Python\" section in the export panel as described in this cookbook. See [here](https://weave-docs.wandb.ai/guides/tracking/tracing#querying--exporting-calls) for more details.\n",
"- **Data Input:**\n",
" - Framework-agnostic tracing with [@weave-op()](https://weave-docs.wandb.ai/quickstart#2-log-a-trace-to-a-new-project) decorator and the possibility to import calls from CSV (see related [import cookbook](https://weave-docs.wandb.ai/reference/gen_notebooks/import_from_csv))\n",
" - Service API endpoints to log to Weave from for various programming frameworks and languages, see [here](https://weave-docs.wandb.ai/reference/service-api/call-start-call-start-post) for more details.\n",
"- **Data Output:**\n",
" - Easy download of the data in CSV, TSV, JSONL, JSON formats - see [here](https://weave-docs.wandb.ai/guides/tracking/tracing#querying--exporting-calls) for more details.\n",
" - Easy export using programmatic access to the data - see \"Use Python\" section in the export panel as described in this cookbook. See [here](https://weave-docs.wandb.ai/guides/tracking/tracing#querying--exporting-calls) for more details.\n",
"\n",
"This custom dashboard extends Weave's native Traces view, allowing for tailored monitoring of LLM applications in production. If you're interested in viewing a more complex dashboard, check out a Streamlit example where you can add your own Weave project URL [in this repo](https://github.com/NiWaRe/agent-dev-collection)."
"This custom dashboard extends Weave's native Traces view, allowing for tailored monitoring of LLM applications in production. If you're interested in viewing a more complex dashboard, check out a Streamlit example where you can add your own Weave project URL [in this repo](https://github.com/NiWaRe/agent-dev-collection).\n"
]
}
],
Expand Down
2 changes: 1 addition & 1 deletion docs/scripts/generate_images.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ async def generate_screenshot_from_browser(
if element:
await element.screenshot(path=output_path)
else:
raise Exception(f"Element with selector '{selector}' not found")
raise ValueError(f"Element with selector '{selector}' not found")
else:
await page.screenshot(path=output_path, full_page=True)

Expand Down
6 changes: 4 additions & 2 deletions examples/agents/programmer.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ def list_files(directory: str) -> str:
if len(result) > LENGTH_LIMIT:
result = result[:LENGTH_LIMIT]
result += "\n... (truncated)"
return result
except Exception as e:
return json.dumps([str(e)])
else:
return result


@weave.op()
Expand All @@ -64,9 +65,10 @@ def write_to_file(path: str, content: str) -> str:
try:
with open(path, "w") as f:
f.write(content)
return "File written successfully."
except Exception as e:
return str(e)
else:
return "File written successfully."


@weave.op()
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ select = [
"F401", # https://docs.astral.sh/ruff/rules/unused-import/
"TID252", # https://docs.astral.sh/ruff/rules/relative-imports/#relative-imports-tid252
"UP", # https://docs.astral.sh/ruff/rules/#pyupgrade-up
"TRY002", # https://docs.astral.sh/ruff/rules/raise-vanilla-class/
"TRY004", # https://docs.astral.sh/ruff/rules/type-check-without-type-error/
"TRY300", # https://docs.astral.sh/ruff/rules/try-consider-else/
]
ignore = [
# we use Google style
Expand Down
16 changes: 8 additions & 8 deletions tests/trace/test_op_return_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,14 +482,14 @@ def fn():
size -= 1
yield size
if size == 5:
raise Exception("test")
raise ValueError("test")

add_accumulator(fn, lambda inputs: simple_list_accumulator)

try:
for item in fn():
pass
except Exception:
except ValueError:
pass

res = client.server.calls_query(
Expand All @@ -515,14 +515,14 @@ async def fn():
size -= 1
yield size
if size == 5:
raise Exception("test")
raise ValueError("test")

add_accumulator(fn, lambda inputs: simple_list_accumulator)

try:
async for item in fn():
pass
except Exception:
except ValueError:
pass

res = client.server.calls_query(
Expand Down Expand Up @@ -550,7 +550,7 @@ def __next__(self):
if self.size == 0:
raise StopIteration
if self.size == 5:
raise Exception("test")
raise ValueError("test")
self.size -= 1
return self.size

Expand All @@ -563,7 +563,7 @@ def fn():
try:
for item in fn():
pass
except Exception:
except ValueError:
pass

res = client.server.calls_query(
Expand Down Expand Up @@ -592,7 +592,7 @@ async def __anext__(self):
if self.size == 0:
raise StopAsyncIteration
if self.size == 5:
raise Exception("test")
raise ValueError("test")
self.size -= 1
return self.size

Expand All @@ -605,7 +605,7 @@ def fn():
try:
async for item in fn():
pass
except Exception:
except ValueError:
pass

res = client.server.calls_query(
Expand Down
8 changes: 4 additions & 4 deletions tests/trace/test_weave_client_mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,16 +312,16 @@ def test_table_mutation_saving_replace_rows(client):

def test_table_cant_append_bad_data(client):
t = weave.Table(rows=[{"a": 1, "b": 2}])
with pytest.raises(ValueError):
with pytest.raises(TypeError):
t.append(1)
with pytest.raises(ValueError):
with pytest.raises(TypeError):
t.append([1, 2, 3])

ref = weave.publish(t)
t2 = ref.get()
with pytest.raises(ValueError):
with pytest.raises(TypeError):
t2.append(1)
with pytest.raises(ValueError):
with pytest.raises(TypeError):
t2.append([1, 2, 3])


Expand Down
4 changes: 2 additions & 2 deletions weave/deploy/gcp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ def deploy(
dir = compile(model_ref, model_method, wandb_project, auth_entity, base_image)
ref = parse_uri(model_ref)
if not isinstance(ref, ObjectRef):
raise ValueError(f"Expected a weave object uri, got {type(ref)}")
raise TypeError(f"Expected a weave object uri, got {type(ref)}")
name = safe_name(f"{ref.project}-{ref.name}")
project = wandb_project or ref.project
key = env.weave_wandb_api_key()
Expand Down Expand Up @@ -310,7 +310,7 @@ def develop(
)
model_uri = parse_uri(model_ref)
if not isinstance(model_uri, ObjectRef):
raise ValueError(f"Expected a weave object uri, got {type(model_uri)}")
raise TypeError(f"Expected a weave object uri, got {type(model_uri)}")
name = safe_name(model_uri.name)
docker = shutil.which("docker")
if docker is None:
Expand Down
2 changes: 1 addition & 1 deletion weave/deploy/modal/stub.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def fastapi_app() -> FastAPI:

uri_ref = parse_uri(os.environ["MODEL_REF"])
if not isinstance(uri_ref, ObjectRef):
raise ValueError(f"Expected a weave object uri, got {type(uri_ref)}")
raise TypeError(f"Expected a weave object uri, got {type(uri_ref)}")
app = object_method_app(uri_ref, auth_entity=os.environ.get("AUTH_ENTITY"))

api.init(os.environ["PROJECT_NAME"])
Expand Down
2 changes: 1 addition & 1 deletion weave/flow/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def convert_to_table(cls, rows: Any) -> weave.Table:
raise ValueError("Attempted to construct a Dataset with an empty list.")
for row in rows.rows:
if not isinstance(row, dict):
raise ValueError(
raise TypeError(
"Attempted to construct a Dataset with a non-dict object. Found type: "
+ str(type(row))
+ " of row: "
Expand Down
2 changes: 1 addition & 1 deletion weave/flow/eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def model_post_init(self, __context: Any) -> None:
if isinstance(scorer, Scorer):
pass
elif isinstance(scorer, type):
raise ValueError(
raise TypeError(
f"Scorer {scorer.__name__} must be an instance, not a class. Did you forget to instantiate?"
)
elif callable(scorer) and not is_op(scorer):
Expand Down
4 changes: 2 additions & 2 deletions weave/flow/prompt/prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def append(
for item in item:
self.append(item)
else:
raise ValueError(f"Cannot append {item} of type {type(item)} to Prompt")
raise TypeError(f"Cannot append {item} of type {type(item)} to Prompt")

def __iadd__(self, item: Any) -> "Prompt":
self.append(item)
Expand Down Expand Up @@ -401,7 +401,7 @@ def from_obj(obj: Any) -> "EasyPrompt":
@staticmethod
def load(fp: IO) -> "EasyPrompt":
if isinstance(fp, str): # Common mistake
raise ValueError(
raise TypeError(
"Prompt.load() takes a file-like object, not a string. Did you mean Prompt.e()?"
)
data = json.load(fp)
Expand Down
Loading
Loading