Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
22 changes: 10 additions & 12 deletions .agents/skills/commit-message/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,21 @@ Use Conventional Commit form:
```text
<type>(<scope>): <imperative summary>
<optional body>
<body>
<optional footer>
<footer(optional)>
```

- Choose the most specific suitable type: `feat`, `fix`, `ref` (repository convention for behavior-preserving restructuring), `perf`, `test`, `docs`, `chore`, `ci`, `style`, or `revert`.
- Add a scope only when it meaningfully narrows the change.
- Keep the subject at 72 characters or fewer, lowercase, imperative, and without a trailing period.
- Add a body when the subject alone does not explain the purpose or a meaningful behavior change. Keep it focused on what changed and why; wrap prose at about 100 characters.
- Add `BREAKING CHANGE: ...` or an issue-closing footer only when the diff or conversation supports it.

Use direct, specific language. Name relevant APIs, versions, errors, or files when they clarify the change. Avoid restating the diff, unsupported claims, decorative examples, and filler.

For substantive changes, prefer a compact code snippet or ASCII diagram in the body when it explains behavior or data flow more clearly than prose. Keep it focused and omit it when it adds no clarity.

## Output and commit execution

For a message suggestion, return one copyable message in a fenced code block. Add at most one brief sentence explaining a non-obvious type or scope choice. Ask a focused question only when the intent cannot reasonably be inferred from the diff and conversation.
- always add a body. The body must:
- start with a clear AI-generated notice: `> 🤖 **This text was AI-generated.**`
- explain the problem and the solution like you are writing docs for a user. Use simple english and link to issues/prs/docs as appropriate
- for both the problem and solution, try to include code snippets or ASCII diagrams that illustrates the change. ASCII diagrams should be in code snippet blocks
- mention limitations or next steps if applicable
- do not add validation or testing sections unless there is an extremely good reason to do so
- Add `BREAKING CHANGE: ...` or an issue-closing footer only when the diff or conversation supports it. If the change is breaking, make sure to append `!` to the type, like `feat!`
- add relevant github or linear issues to the footer if applicable

Do not run `git commit` or `git commit --amend` unless the user explicitly asks you to commit. When committing a multiline message, preserve real newline characters: prefer writing the message to a temporary file and using `git commit -F <file>` (or `git commit --amend -F <file>`). Multiple `-m` flags or ANSI-C quoting are acceptable for simple cases. Never assume literal `\n` inside ordinary quotes becomes a newline. After committing, verify the stored message with `git log -1 --format=medium`.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions py/src/braintrust/integrations/cohere/test_cohere.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,37 @@ def test_wrap_cohere_rerank_sync(memory_logger):
assert span["metrics"].get("search_units") == 1


@pytest.mark.vcr
def test_wrap_cohere_rerank_relevant_spans(memory_logger):
client = _v2_client(require_methods=("rerank",))
if "relevant_spans" not in inspect.signature(client.rerank).parameters:
pytest.skip("Cohere rerank relevant_spans requires a newer SDK")
client = wrap_cohere(client)

model = "rerank-v5.0-fast"
documents = [
"Paris is the capital of France. The Eiffel Tower is a famous landmark in Paris.",
"Vienna is the capital of Austria. The city is known for its classical music.",
]
relevant_spans = {"mode": "enabled", "threshold": 0.3, "max_spans": 10}
response = client.rerank(
model=model,
query="What is the capital of France?",
documents=documents,
top_n=2,
relevant_spans=relevant_spans,
)
assert any(result.relevant_spans for result in response.results)
assert any(result.relevant_spans is None for result in response.results)

spans = memory_logger.pop()
assert len(spans) == 1
span = spans[0]
assert span["context"]["span_origin"]["instrumentation"]["name"] == "cohere-auto"
assert span["metadata"]["relevant_spans"] == relevant_spans
assert span["output"] == [result.model_dump(exclude_none=True) for result in response.results]


@pytest.mark.vcr
def test_wrap_cohere_chat_stream_v1_sync(memory_logger):
assert not memory_logger.pop()
Expand Down
21 changes: 13 additions & 8 deletions py/src/braintrust/integrations/cohere/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def start_span(*args, **kwargs):
"max_chunks_per_doc",
"max_tokens_per_doc",
"rank_fields",
"relevant_spans",
"priority",
)
_AUDIO_TRANSCRIPTION_METADATA_KEYS = (
Expand Down Expand Up @@ -337,8 +338,8 @@ def _embed_output(result: Any) -> dict[str, Any] | None:
def _rerank_output(result: Any) -> list[dict[str, Any]] | None:
"""Return the top-N rerank results (capped at 100) from a rerank response.
Each result is summarized to ``{index, relevance_score}`` — the document
payload (if present via ``return_documents=True``) is dropped on purpose.
Each result includes its index, relevance score, and relevant spans when
present. The document payload (via ``return_documents=True``) is dropped.
"""
results = _get_field(result, "results")
if not isinstance(results, list):
Expand All @@ -348,12 +349,16 @@ def _rerank_output(result: Any) -> list[dict[str, Any]] | None:
for item in results[:100]:
if item is None:
continue
out.append(
{
"index": _get_field(item, "index"),
"relevance_score": _get_field(item, "relevance_score"),
}
)
entry = {
"index": _get_field(item, "index"),
"relevance_score": _get_field(item, "relevance_score"),
}
relevant_spans = _get_field(item, "relevant_spans")
if relevant_spans is not None:
entry["relevant_spans"] = [
{key: _get_field(span, key) for key in ("start", "end", "score")} for span in relevant_spans
]
out.append(entry)
return out


Expand Down
Loading