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
118 changes: 118 additions & 0 deletions docs/query-agent/_includes/code/structured_outputs.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import 'dotenv/config'
const { loadClientInternally, populateWeaviate } = await import('./util.mjs').catch(() => import('../docs/query-agent/_includes/code/util.mjs'));

const client = await loadClientInternally();
await populateWeaviate(client, false);


// START SOInstantiate
import { QueryAgent } from 'weaviate-agents';
import { z } from 'zod';

const qa = new QueryAgent(client, { collections: ['FinancialContracts'] });
// END SOInstantiate


{
// START SOBasicExampleBaseModel
const ContractSummary = z.object({
contract_id: z.string(),
contract_title: z.string(),
auto_renew: z.boolean(),
parties_involved: z.array(z.string()),
requires_action: z.boolean(),
});

const res = await qa.ask(
"Find the oldest contract and include if it automatically renews, who is involved, and if user action is needed",
{ outputFormat: ContractSummary }
);

console.log(res.finalAnswerParsed);
// END SOBasicExampleBaseModel
}


{
// START SOBasicDictExample
const res = await qa.ask(
"Find the oldest contract and include if it automatically renews, who is involved, and if user action is needed",
{
outputFormat: {
type: "object",
properties: {
contract_id: { title: "Contract Id", type: "string" },
contract_title: { title: "Contract Title", type: "string" },
auto_renew: { title: "Auto Renew", type: "boolean" },
parties_involved: { items: { type: "string" }, title: "Parties Involved", type: "array" },
requires_action: { title: "Requires Action", type: "boolean" },
},
required: ["contract_id", "contract_title", "auto_renew", "parties_involved", "requires_action"],
title: "ContractSummary",
additionalProperties: false,
},
}
);

console.log(res.finalAnswerParsed);
// END SOBasicDictExample
}


{
// START SOReasoningExample
const FinalAnswer = z.object({
reasoning: z.string(),
final_answer: z.string(),
});

const res = await qa.ask("What is the most recent contract about AI?", { outputFormat: FinalAnswer });

console.log(res.finalAnswerParsed);
// END SOReasoningExample
}


{
// START SONestedExampleBaseModel
const ContractInfo = z.object({
names_mentioned: z.array(z.string()).describe("All names within the contract text"),
contract_type: z.enum(["sales", "purchase", "other"]).describe("Determine the type of contract"),
summary: z.string().describe("Provide a brief summary of the contract."),
contract_uuid: z.uuid(),
});

const ContractInfoResponse = z.object({
contract_infos: z.array(ContractInfo),
overall_summary: z.string(),
});

const res = await qa.ask("Find and return all contracts about AI in 2023", { outputFormat: ContractInfoResponse });

console.dir(res.finalAnswerParsed, { depth: null });
// END SONestedExampleBaseModel
}


{
// START SOCitationExample
const CitedText = z.object({
sentence: z.string().describe("A single sentence from your answer, to be combined with other sentences"),
sources: z.array(z.uuid()).describe("The UUIDs of the sources that support the sentence"),
});

const CitedAnswer = z.object({
reasoning: z.string(),
final_answer: z.array(CitedText).describe(
"A list of cited sentences, that will combine together in a paragraph to be a full answer"
),
});

const res = await qa.ask("What is the most recent contract about AI?", { outputFormat: CitedAnswer });

console.dir(res.finalAnswerParsed, { depth: null });
// END SOCitationExample
}


await client.close();
105 changes: 105 additions & 0 deletions docs/query-agent/_includes/code/structured_outputs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import sys
sys.path.insert(0, "docs/query-agent/_includes/code")
from util import load_client_internally, populate_weaviate

client = load_client_internally()
populate_weaviate(client, False)


# START SOInstantiate
from weaviate.agents.query import QueryAgent

qa = QueryAgent(client=client, collections=["FinancialContracts"])
# END SOInstantiate


# START SOBasicExampleBaseModel
from pydantic import BaseModel

class ContractSummary(BaseModel):
contract_id: str
contract_title: str
auto_renew: bool
parties_involved: list[str]
requires_action: bool

res = qa.ask(
"Find the oldest contract and include if it automatically renews, who is involved, and if user action is needed",
output_format=ContractSummary,
)

print(res.final_answer_parsed)
# END SOBasicExampleBaseModel

# START SOBasicDictExample
res = qa.ask(
"Find the oldest contract and include if it automatically renews, who is involved, and if user action is needed",
output_format={
'properties': {
'contract_id': {'title': 'Contract Id', 'type': 'string'},
'contract_title': {'title': 'Contract Title', 'type': 'string'},
'auto_renew': {'title': 'Auto Renew', 'type': 'boolean'},
'parties_involved': {'items': {'type': 'string'}, 'title': 'Parties Involved', 'type': 'array'},
'requires_action': {'title': 'Requires Action', 'type': 'boolean'}
},
'required': ['contract_id', 'contract_title', 'auto_renew', 'parties_involved', 'requires_action'],
'title': 'ContractSummary',
'type': 'object'
}
)

print(res.final_answer_parsed)
# END SOBasicDictExample

# START SOReasoningExample
from pydantic import BaseModel

class FinalAnswer(BaseModel):
reasoning: str
final_answer: str

res = qa.ask("What is the most recent contract about AI?", output_format=FinalAnswer)

print(res.final_answer_parsed)
# END SOReasoningExample

# START SONestedExampleBaseModel
from pydantic import BaseModel, Field
from uuid import UUID
from typing import Literal

class ContractInfo(BaseModel):
names_mentioned: list[str] = Field(description="All names within the contract text")
contract_type: Literal["sales", "purchase", "other"] = Field(description="Determine the type of contract")
summary: str = Field(description="Provide a brief summary of the contract.")
contract_uuid: UUID

class ContractInfoResponse(BaseModel):
contract_infos: list[ContractInfo]
overall_summary: str

res = qa.ask("Find and return all contracts about AI in 2023", output_format=ContractInfoResponse)

print(res.final_answer_parsed)
# END SONestedExampleBaseModel

# START SOCitationExample
from pydantic import BaseModel, Field
from uuid import UUID

class CitedText(BaseModel):
sentence: str = Field(description="A single sentence from your answer, to be combined with other sentences")
sources: list[UUID] = Field(description="The UUIDs of the sources that support the sentence")

class CitedAnswer(BaseModel):
reasoning: str
final_answer: list[CitedText] = Field(
description="A list of cited sentences, that will combine together in a paragraph to be a full answer"
)

res = qa.ask("What is the most recent contract about AI?", output_format=CitedAnswer)

print(res.final_answer_parsed)
# END SOCitationExample

client.close()
25 changes: 22 additions & 3 deletions docs/query-agent/guides/ask_mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,17 @@ The `.ask()` method accepts several arguments:
| --- | --- | --- |
| `query` | `str \| list[ChatMessage]` | The user query you want the agent to answer. This can be a simple string (`"What is the highest-grossing product?"`) or a list of chat messages (for conversational context). [See the page on multi-turn conversations for more detail](../reference/multi_turn_conversations.md). |
| `collections` | `list[str \| QueryAgentCollectionConfig] \| None` | The name(s) of the collections to search. You can pass one or many collection names as a list of strings (e.g., `["ECommerce", "BookSales"]`), or provide collection configuration objects for more control. If specified in the `ask` method, it will overwrite those defined in the instantiation of `QueryAgent`. [See the page on collection configuration for more detail](../reference/advanced_collections.md). |
| `result_evaluation` | `Literal["llm", "none"]` | Controls whether the agent will ask an LLM to "evaluate" (i.e., rewrite or rephrase) the result based on all retrieved context. Accepts either:<br/>• `"none"` (default): faster and cheaper; where the final answer is the last LLM call and no further analysis is completed.<br/>• `"llm"`: higher cost/latency - enables a final step where an LLM subsets the sources retrieved to only those used in the answer, as well as enabling the optional fields `is_partial_answer` and `missing_information`. See [the response class](#response) for more details. |
| `result_evaluation` | `Literal["llm", "none"]` | Controls whether the agent will ask an LLM to "evaluate" the result based on all retrieved context. Accepts either:<br/>• `"none"` (default): faster and cheaper; where the final answer is the last LLM call and no further analysis is completed.<br/>• `"llm"`: higher cost/latency - enables a final step where an LLM subsets the sources retrieved to only those used in the answer, as well as enabling the optional fields `is_partial_answer` and `missing_information`. See [the response class](#response) for more details. |
| `output_format` | `dict \| type[BaseModel] \| None` | Optional schema for structured output in the final response. When set, `.ask()` returns a `ParsedAskModeResponse` instead of an `AskModeResponse`: the parsed result is added on a new `final_answer_parsed` field, and `final_answer` still holds the raw model output. See [the response class](#response) and [the page on structured outputs for more details](../reference/structured_outputs.md). |

</TabItem>
<TabItem value="ts_agents" label="JavaScript/TypeScript">
| Parameter | Type | Description |
| --- | --- | --- |
| `query` | `string \| ChatMessage[]` | The user query you want the agent to answer. This can be a simple string (`"What is the highest-grossing product?"`) or a list of chat messages (for conversational context). [See the page on multi-turn conversations for more detail](../reference/multi_turn_conversations.md). |
| `collections` | `(string \| QueryAgentCollectionConfig)[]` | The name(s) of the collections to search. You can pass one or many collection names as a list of strings (e.g., `["ECommerce", "BookSales"]`), or provide collection configuration objects for more control. [See the page on collection configuration for more detail](../reference/advanced_collections.md). If specified in the `ask` method, it will overwrite those defined in the instantiation of `QueryAgent`. |
| `resultEvaluation` | `"llm" \| "none"` | Controls whether the agent will ask an LLM to "evaluate" (i.e., rewrite or rephrase) the result based on all retrieved context. Accepts either:<br/>• `"none"`: faster and cheaper; default setting where the final answer is the last LLM call.<br/>• `"llm"`: higher cost/latency - enables a final step where an LLM subsets the sources retrieved to only those used in the answer, as well as enabling the optional fields `is_partial_answer` and `missing_information`. See [the response class](#response) for more details. |

| `resultEvaluation` | `"llm" \| "none"` | Controls whether the agent will ask an LLM to "evaluate" the result based on all retrieved context. Accepts either:<br/>• `"none"`: faster and cheaper; default setting where the final answer is the last LLM call.<br/>• `"llm"`: higher cost/latency - enables a final step where an LLM subsets the sources retrieved to only those used in the answer, as well as enabling the optional fields `is_partial_answer` and `missing_information`. See [the response class](#response) for more details. |
| `outputFormat` | `ZodType \| object` | Optional schema for structured output in the final response. Pass a [Zod](https://zod.dev/) schema (parsed and validated) or a raw [Draft 2020-12 JSON Schema](https://json-schema.org/draft/2020-12) object (parsed only). When set, `.ask()` returns a `ParsedAskModeResponse<T>` instead of an `AskModeResponse`: the typed result is added on a new `finalAnswerParsed` field, and `finalAnswer` still holds the raw model output. See [the response class](#response) and [the page on structured outputs for more details](../reference/structured_outputs.md). |
</TabItem>
</Tabs>

Expand All @@ -100,6 +101,14 @@ The `AskModeResponse` class has the following properties:
| `sources` | `list[Source] \| None` | A list of `Source` objects, which have an `object_id` property correlating to the UUID of the Weaviate object that was retrieved during the run. If `result_evaluation` is `"llm"`, these are subset to only those that are relevant to the `final_answer`. |

[See the client documentation for more detail.](https://weaviate-python-client.readthedocs.io/en/latest/weaviate-agents-python-client/docs/weaviate_agents.classes.html#weaviate_agents.classes.AskModeResponse)

If you provide the `output_format` parameter (`qa.ask(..., output_format=...)`), Ask Mode returns a `ParsedAskModeResponse` instead. It is a subclass of `AskModeResponse`, so it keeps every field above and adds one more. `final_answer` still holds the raw string from the model.

| Field | Type | Description |
| --- | --- | --- |
| `final_answer_parsed` | `<given_type>` | The final response, parsed into the schema given in `output_format`. |

The type of `final_answer_parsed` is a `dict` if a dictionary was supplied to `output_format`, otherwise it will be the exact type of the `BaseModel` given.
</TabItem>

<TabItem value="ts_agents" label="JavaScript/TypeScript">
Expand All @@ -116,6 +125,16 @@ The `AskModeResponse` class has the following properties:
| `sources` | `Source[]` | A list of `Source` objects, which have an `objectId` property correlating to the UUID of the Weaviate object that was retrieved during the run. If `resultEvaluation` is `"llm"`, these are subset to only those that are relevant to the `finalAnswer`. |

[See the client documentation for more detail.](https://weaviate.github.io/agents-typescript-client/types/AskModeResponse.html)

If you provide the `outputFormat` parameter (`qa.ask(..., { outputFormat: ... })`), Ask Mode returns a `ParsedAskModeResponse<T>` instead. It is an `AskModeResponse` with one more field, so it keeps every field above. `finalAnswer` still holds the raw string from the model.

| Field | Type | Description |
| --- | --- | --- |
| `finalAnswerParsed` | `<given_type>` | The final response, parsed into the schema given in `outputFormat`. |

The type of `finalAnswerParsed` is `Record<string, unknown>` if a raw JSON Schema object was supplied to `outputFormat`, otherwise it will be the inferred type of the Zod schema given (`z.infer<typeof schema>`).

[See the client documentation for more detail.](https://weaviate.github.io/agents-typescript-client/types/ParsedAskModeResponse.html)
</TabItem>

</Tabs>
Expand Down
2 changes: 1 addition & 1 deletion docs/query-agent/reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ See the different configuration options for the Query Agent and how you can cust
* **[Multi-turn Conversations](./multi_turn_conversations.md)**: Learn how to include multiple turns of conversations in a message history instead of a single user query.
* **[Additional Filters](./additional_filters.md)**: Define persistent filters that get added to every search the Query Agent performs.
* **[Collection Configuration](./advanced_collections.md)**: Setup your collections with more advanced configurations, such as named vectors, multi-tenancy and additional filters.

* **[Structured Outputs](./structured_outputs.md)**: Configure the format of the Ask Mode response to conform to a schema.


## Questions and feedback
Expand Down
Loading
Loading