Skip to content
Open
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
3 changes: 3 additions & 0 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ jobs:
dotnet tool restore
dotnet csharpier check $CHANGED_FILES

- name: Check XML param docs (query/generate API)
run: python3 ci/check_xml_param_docs.py

- name: Run analyzer unit tests
run: |
if [[ "${{ needs.setup.outputs.dry-run }}" == "true" ]]; then
Expand Down
118 changes: 118 additions & 0 deletions ci/check_xml_param_docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/usr/bin/env python3
"""Fail when public query/generate methods document a summary but not their parameters.

CS1573 only fires when some parameters are documented but not all; CS1591 only
fires when the method has no doc comment at all. Methods with a <summary> and
zero <param> tags (Hybrid before this fix) slip through both. This check closes
that gap for the query/generate client surface.
"""

from __future__ import annotations

import re
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
CLIENT_ROOT = ROOT / "src" / "Weaviate.Client"

# Query/generate API partials (excludes TypedDataClient and other surfaces).
SCOPED_PREFIXES = (
"QueryClient.",
"GenerateClient.",
"Typed/TypedQueryClient.",
"Typed/TypedGenerateClient.",
)

METHOD_RE = re.compile(
r"(?P<docs>(?:[ \t]*///.*\n)+)\s*"
r"(?:(?:\s*\[[^\]]+\]\s*)*)"
r"(?P<mods>public\s+(?:static\s+)?(?:async\s+)?[\w<>\[\],\.\?\s]+\s+)?"
r"(?P<name>\w+)\s*\((?P<sig>[^)]*)\)"
r"(?:\s*where\s+[^{;]+)?\s*(?:=>|\{|;)",
re.MULTILINE,
)


def is_scoped(path: Path) -> bool:
rel = path.relative_to(CLIENT_ROOT).as_posix()
return any(rel.startswith(prefix) for prefix in SCOPED_PREFIXES)


def parse_param_names(signature: str) -> list[str]:
names: list[str] = []
for part in signature.split(","):
part = part.strip()
if not part:
continue
part = re.sub(r"\[[^\]]*\]", "", part)
part = part.split("=")[0].strip()
part = re.sub(r"^this\s+", "", part)
tokens = part.split()
if tokens:
names.append(tokens[-1].lstrip("@"))
return names


def check_file(path: Path) -> list[str]:
text = path.read_text(encoding="utf-8")
rel = path.relative_to(ROOT).as_posix()
issues: list[str] = []

for match in METHOD_RE.finditer(text):
docs = match.group("docs")
if "<summary>" not in docs:
continue

param_names = parse_param_names(match.group("sig"))
if not param_names:
continue

doc_params = re.findall(r'<param name="([^"]+)"', docs)
line = text[: match.start()].count("\n") + 1
method = match.group("name")

if not doc_params:
issues.append(
f"{rel}:{line}: {method} has <summary> but no <param> tags "
f"({len(param_names)} parameters)"
)
continue

missing = [name for name in param_names if name not in doc_params]
extra = [name for name in doc_params if name not in param_names]
if missing:
issues.append(
f"{rel}:{line}: {method} missing <param> for: {', '.join(missing)}"
)
if extra:
issues.append(
f"{rel}:{line}: {method} has undocumented extra <param> tags: "
f"{', '.join(extra)}"
)

return issues


def main() -> int:
issues: list[str] = []
for path in sorted(CLIENT_ROOT.rglob("*.cs")):
if not is_scoped(path):
continue
issues.extend(check_file(path))

if not issues:
print(
"XML param docs OK for query/generate client methods "
f"({', '.join(SCOPED_PREFIXES)})"
)
return 0

print(f"XML param doc check failed ({len(issues)} issue(s)):", file=sys.stderr)
for issue in issues:
print(f" {issue}", file=sys.stderr)
return 1


if __name__ == "__main__":
raise SystemExit(main())
129 changes: 129 additions & 0 deletions src/Weaviate.Client/GenerateClient.Hybrid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@ public partial class GenerateClient
/// <summary>
/// Hybrid search with generative AI capabilities.
/// </summary>
/// <param name="query">The query</param>
/// <param name="alpha">The alpha</param>
/// <param name="queryProperties">The query properties</param>
/// <param name="fusionType">The fusion type</param>
/// <param name="maxVectorDistance">The max vector distance</param>
/// <param name="limit">The limit</param>
/// <param name="offset">The offset</param>
/// <param name="bm25Operator">The bm 25 operator</param>
/// <param name="autoLimit">The auto limit</param>
/// <param name="filters">The filters</param>
/// <param name="rerank">The rerank</param>
/// <param name="boost">The boost for soft-ranking results. Preview: requires Weaviate 1.38+ (older servers silently ignore it)</param>
/// <param name="singlePrompt">The single prompt</param>
/// <param name="groupedTask">The grouped task</param>
/// <param name="provider">The provider</param>
/// <param name="returnProperties">The return properties</param>
/// <param name="returnReferences">The return references</param>
/// <param name="returnMetadata">The return metadata</param>
/// <param name="includeVectors">The include vectors</param>
/// <param name="cancellationToken">The cancellation token</param>
public Task<GenerativeWeaviateResult> Hybrid(
string query,
float? alpha = null,
Expand Down Expand Up @@ -60,6 +80,27 @@ public Task<GenerativeWeaviateResult> Hybrid(
/// <summary>
/// Hybrid search with generative AI capabilities.
/// </summary>
/// <param name="query">The query</param>
/// <param name="vectors">The vectors</param>
/// <param name="alpha">The alpha</param>
/// <param name="queryProperties">The query properties</param>
/// <param name="fusionType">The fusion type</param>
/// <param name="maxVectorDistance">The max vector distance</param>
/// <param name="limit">The limit</param>
/// <param name="offset">The offset</param>
/// <param name="bm25Operator">The bm 25 operator</param>
/// <param name="autoLimit">The auto limit</param>
/// <param name="filters">The filters</param>
/// <param name="rerank">The rerank</param>
/// <param name="boost">The boost for soft-ranking results. Preview: requires Weaviate 1.38+ (older servers silently ignore it)</param>
/// <param name="singlePrompt">The single prompt</param>
/// <param name="groupedTask">The grouped task</param>
/// <param name="provider">The provider</param>
/// <param name="returnProperties">The return properties</param>
/// <param name="returnReferences">The return references</param>
/// <param name="returnMetadata">The return metadata</param>
/// <param name="includeVectors">The include vectors</param>
/// <param name="cancellationToken">The cancellation token</param>
public async Task<GenerativeWeaviateResult> Hybrid(
string? query,
HybridVectorInput? vectors,
Expand Down Expand Up @@ -123,6 +164,27 @@ public async Task<GenerativeWeaviateResult> Hybrid(
/// <summary>
/// Hybrid search with generative AI capabilities and grouping.
/// </summary>
/// <param name="query">The query</param>
/// <param name="groupBy">The group by</param>
/// <param name="alpha">The alpha</param>
/// <param name="queryProperties">The query properties</param>
/// <param name="fusionType">The fusion type</param>
/// <param name="maxVectorDistance">The max vector distance</param>
/// <param name="limit">The limit</param>
/// <param name="offset">The offset</param>
/// <param name="bm25Operator">The bm 25 operator</param>
/// <param name="autoLimit">The auto limit</param>
/// <param name="filters">The filters</param>
/// <param name="rerank">The rerank</param>
/// <param name="boost">The boost for soft-ranking results. Preview: requires Weaviate 1.38+ (older servers silently ignore it)</param>
/// <param name="singlePrompt">The single prompt</param>
/// <param name="groupedTask">The grouped task</param>
/// <param name="provider">The provider</param>
/// <param name="returnProperties">The return properties</param>
/// <param name="returnReferences">The return references</param>
/// <param name="returnMetadata">The return metadata</param>
/// <param name="includeVectors">The include vectors</param>
/// <param name="cancellationToken">The cancellation token</param>
public Task<GenerativeGroupByResult> Hybrid(
string query,
GroupByRequest groupBy,
Expand Down Expand Up @@ -174,6 +236,28 @@ public Task<GenerativeGroupByResult> Hybrid(
/// <summary>
/// Hybrid search with generative AI capabilities and grouping.
/// </summary>
/// <param name="query">The query</param>
/// <param name="vectors">The vectors</param>
/// <param name="groupBy">The group by</param>
/// <param name="alpha">The alpha</param>
/// <param name="queryProperties">The query properties</param>
/// <param name="fusionType">The fusion type</param>
/// <param name="maxVectorDistance">The max vector distance</param>
/// <param name="limit">The limit</param>
/// <param name="offset">The offset</param>
/// <param name="bm25Operator">The bm 25 operator</param>
/// <param name="autoLimit">The auto limit</param>
/// <param name="filters">The filters</param>
/// <param name="rerank">The rerank</param>
/// <param name="boost">The boost for soft-ranking results. Preview: requires Weaviate 1.38+ (older servers silently ignore it)</param>
/// <param name="singlePrompt">The single prompt</param>
/// <param name="groupedTask">The grouped task</param>
/// <param name="provider">The provider</param>
/// <param name="returnProperties">The return properties</param>
/// <param name="returnReferences">The return references</param>
/// <param name="returnMetadata">The return metadata</param>
/// <param name="includeVectors">The include vectors</param>
/// <param name="cancellationToken">The cancellation token</param>
public async Task<GenerativeGroupByResult> Hybrid(
string? query,
HybridVectorInput? vectors,
Expand Down Expand Up @@ -256,6 +340,28 @@ public static class GenerateClientHybridExtensions
/// singlePrompt: "Describe this item"
/// );
/// </example>
/// <param name="client">The client</param>
/// <param name="query">The query</param>
/// <param name="vectors">The vectors</param>
/// <param name="alpha">The alpha</param>
/// <param name="queryProperties">The query properties</param>
/// <param name="fusionType">The fusion type</param>
/// <param name="maxVectorDistance">The max vector distance</param>
/// <param name="limit">The limit</param>
/// <param name="offset">The offset</param>
/// <param name="bm25Operator">The bm 25 operator</param>
/// <param name="autoLimit">The auto limit</param>
/// <param name="filters">The filters</param>
/// <param name="rerank">The rerank</param>
/// <param name="boost">The boost for soft-ranking results. Preview: requires Weaviate 1.38+ (older servers silently ignore it)</param>
/// <param name="singlePrompt">The single prompt</param>
/// <param name="groupedTask">The grouped task</param>
/// <param name="provider">The provider</param>
/// <param name="returnProperties">The return properties</param>
/// <param name="returnReferences">The return references</param>
/// <param name="returnMetadata">The return metadata</param>
/// <param name="includeVectors">The include vectors</param>
/// <param name="cancellationToken">The cancellation token</param>
public static async Task<GenerativeWeaviateResult> Hybrid(
this GenerateClient client,
string query,
Expand Down Expand Up @@ -308,6 +414,29 @@ await client.Hybrid(
/// Hybrid search with generative AI capabilities and grouping using a lambda to build HybridVectorInput.
/// This allows chaining NearVector or NearText configuration with target vectors.
/// </summary>
/// <param name="client">The client</param>
/// <param name="query">The query</param>
/// <param name="vectors">The vectors</param>
/// <param name="groupBy">The group by</param>
/// <param name="alpha">The alpha</param>
/// <param name="queryProperties">The query properties</param>
/// <param name="fusionType">The fusion type</param>
/// <param name="maxVectorDistance">The max vector distance</param>
/// <param name="limit">The limit</param>
/// <param name="offset">The offset</param>
/// <param name="bm25Operator">The bm 25 operator</param>
/// <param name="autoLimit">The auto limit</param>
/// <param name="filters">The filters</param>
/// <param name="rerank">The rerank</param>
/// <param name="boost">The boost for soft-ranking results. Preview: requires Weaviate 1.38+ (older servers silently ignore it)</param>
/// <param name="singlePrompt">The single prompt</param>
/// <param name="groupedTask">The grouped task</param>
/// <param name="provider">The provider</param>
/// <param name="returnProperties">The return properties</param>
/// <param name="returnReferences">The return references</param>
/// <param name="returnMetadata">The return metadata</param>
/// <param name="includeVectors">The include vectors</param>
/// <param name="cancellationToken">The cancellation token</param>
public static async Task<GenerativeGroupByResult> Hybrid(
this GenerateClient client,
string query,
Expand Down
70 changes: 70 additions & 0 deletions src/Weaviate.Client/GenerateClient.NearVector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,23 @@ public partial class GenerateClient
/// <summary>
/// Search near vector with generative AI capabilities.
/// </summary>
/// <param name="vectors">The vectors</param>
/// <param name="filters">The filters</param>
/// <param name="certainty">The certainty</param>
/// <param name="distance">The distance</param>
/// <param name="autoLimit">The auto limit</param>
/// <param name="limit">The limit</param>
/// <param name="offset">The offset</param>
/// <param name="rerank">The rerank</param>
/// <param name="boost">The boost for soft-ranking results. Preview: requires Weaviate 1.38+ (older servers silently ignore it)</param>
/// <param name="singlePrompt">The single prompt</param>
/// <param name="groupedTask">The grouped task</param>
/// <param name="provider">The provider</param>
/// <param name="returnProperties">The return properties</param>
/// <param name="returnReferences">The return references</param>
/// <param name="returnMetadata">The return metadata</param>
/// <param name="includeVectors">The include vectors</param>
/// <param name="cancellationToken">The cancellation token</param>
public async Task<GenerativeWeaviateResult> NearVector(
VectorSearchInput vectors,
Filter? filters = null,
Expand Down Expand Up @@ -55,6 +72,24 @@ await _client.GrpcClient.SearchNearVector(
/// <summary>
/// Search near vector with generative AI capabilities and grouping.
/// </summary>
/// <param name="vectors">The vectors</param>
/// <param name="groupBy">The group by</param>
/// <param name="filters">The filters</param>
/// <param name="certainty">The certainty</param>
/// <param name="distance">The distance</param>
/// <param name="autoLimit">The auto limit</param>
/// <param name="limit">The limit</param>
/// <param name="offset">The offset</param>
/// <param name="rerank">The rerank</param>
/// <param name="boost">The boost for soft-ranking results. Preview: requires Weaviate 1.38+ (older servers silently ignore it)</param>
/// <param name="singlePrompt">The single prompt</param>
/// <param name="groupedTask">The grouped task</param>
/// <param name="provider">The provider</param>
/// <param name="returnProperties">The return properties</param>
/// <param name="returnReferences">The return references</param>
/// <param name="returnMetadata">The return metadata</param>
/// <param name="includeVectors">The include vectors</param>
/// <param name="cancellationToken">The cancellation token</param>
public async Task<GenerativeGroupByResult> NearVector(
VectorSearchInput vectors,
GroupByRequest groupBy,
Expand Down Expand Up @@ -101,6 +136,23 @@ await _client.GrpcClient.SearchNearVector(
/// <summary>
/// Search near vector with generative AI capabilities using lambda builder.
/// </summary>
/// <param name="vectors">The vectors</param>
/// <param name="filters">The filters</param>
/// <param name="certainty">The certainty</param>
/// <param name="distance">The distance</param>
/// <param name="autoLimit">The auto limit</param>
/// <param name="limit">The limit</param>
/// <param name="offset">The offset</param>
/// <param name="rerank">The rerank</param>
/// <param name="boost">The boost for soft-ranking results. Preview: requires Weaviate 1.38+ (older servers silently ignore it)</param>
/// <param name="singlePrompt">The single prompt</param>
/// <param name="groupedTask">The grouped task</param>
/// <param name="provider">The provider</param>
/// <param name="returnProperties">The return properties</param>
/// <param name="returnReferences">The return references</param>
/// <param name="returnMetadata">The return metadata</param>
/// <param name="includeVectors">The include vectors</param>
/// <param name="cancellationToken">The cancellation token</param>
public async Task<GenerativeWeaviateResult> NearVector(
VectorSearchInput.FactoryFn vectors,
Filter? filters = null,
Expand Down Expand Up @@ -143,6 +195,24 @@ await NearVector(
/// <summary>
/// Search near vector with generative AI capabilities and grouping using lambda builder.
/// </summary>
/// <param name="vectors">The vectors</param>
/// <param name="groupBy">The group by</param>
/// <param name="filters">The filters</param>
/// <param name="certainty">The certainty</param>
/// <param name="distance">The distance</param>
/// <param name="autoLimit">The auto limit</param>
/// <param name="limit">The limit</param>
/// <param name="offset">The offset</param>
/// <param name="rerank">The rerank</param>
/// <param name="boost">The boost for soft-ranking results. Preview: requires Weaviate 1.38+ (older servers silently ignore it)</param>
/// <param name="singlePrompt">The single prompt</param>
/// <param name="groupedTask">The grouped task</param>
/// <param name="provider">The provider</param>
/// <param name="returnProperties">The return properties</param>
/// <param name="returnReferences">The return references</param>
/// <param name="returnMetadata">The return metadata</param>
/// <param name="includeVectors">The include vectors</param>
/// <param name="cancellationToken">The cancellation token</param>
public async Task<GenerativeGroupByResult> NearVector(
VectorSearchInput.FactoryFn vectors,
GroupByRequest groupBy,
Expand Down
Loading