Skip to main content

data_for_seo/api/ai_optimization/
llm_responses.rs

1//! LLM Responses sub-API, shared by every provider.
2//!
3//! See <https://docs.dataforseo.com/v3/ai_optimization/chat_gpt/llm_responses/overview/>.
4
5use crate::entity::{
6    AiOptimizationLlmResponse, AiOptimizationLlmResponseModel, AiOptimizationTaskReady,
7};
8use crate::{DataForSeoApiResponse, DataForSeoClient};
9use serde::{Deserialize, Serialize};
10
11/// LLM Responses endpoints for a single provider (`chat_gpt`, `claude`, `gemini`).
12///
13/// These providers support both the Standard (`task_post`/`task_get`) and Live
14/// methods. Perplexity is Live-only and exposed separately.
15pub struct AiOptimizationApiLlmResponses<'a> {
16    pub(crate) client: &'a DataForSeoClient,
17    pub(crate) provider: &'static str,
18}
19
20impl AiOptimizationApiLlmResponses<'_> {
21    /// Lists the models available for this provider.
22    ///
23    /// `GET /v3/ai_optimization/{provider}/llm_responses/models`
24    /// See <https://docs.dataforseo.com/v3/ai_optimization/chat_gpt/llm_responses/models/>.
25    pub async fn models(&self) -> DataForSeoApiResponse<AiOptimizationLlmResponseModel> {
26        self.client
27            .http_get(&format!(
28                "/v3/ai_optimization/{}/llm_responses/models",
29                self.provider
30            ))
31            .await
32    }
33
34    /// Generates a response synchronously.
35    ///
36    /// `POST /v3/ai_optimization/{provider}/llm_responses/live`
37    /// See <https://docs.dataforseo.com/v3/ai_optimization/chat_gpt/llm_responses/live/>.
38    pub async fn live(
39        &self,
40        data: Vec<AiOptimizationLlmResponsesPost>,
41    ) -> DataForSeoApiResponse<AiOptimizationLlmResponse> {
42        self.client
43            .http_post(
44                &format!("/v3/ai_optimization/{}/llm_responses/live", self.provider),
45                &data,
46            )
47            .await
48    }
49
50    /// Queues a response task (Standard method).
51    ///
52    /// `POST /v3/ai_optimization/{provider}/llm_responses/task_post`
53    /// See <https://docs.dataforseo.com/v3/ai_optimization/chat_gpt/llm_responses/task_post/>.
54    pub async fn task_post(
55        &self,
56        data: Vec<AiOptimizationLlmResponsesPost>,
57    ) -> DataForSeoApiResponse<AiOptimizationLlmResponse> {
58        self.client
59            .http_post(
60                &format!(
61                    "/v3/ai_optimization/{}/llm_responses/task_post",
62                    self.provider
63                ),
64                &data,
65            )
66            .await
67    }
68
69    /// Lists tasks that have completed and are ready to collect.
70    ///
71    /// `GET /v3/ai_optimization/{provider}/llm_responses/tasks_ready`
72    /// See <https://docs.dataforseo.com/v3/ai_optimization/chat_gpt/llm_responses/tasks_ready/>.
73    pub async fn tasks_ready(&self) -> DataForSeoApiResponse<AiOptimizationTaskReady> {
74        self.client
75            .http_get(&format!(
76                "/v3/ai_optimization/{}/llm_responses/tasks_ready",
77                self.provider
78            ))
79            .await
80    }
81
82    /// Collects the result of a completed task by its `id`.
83    ///
84    /// `GET /v3/ai_optimization/{provider}/llm_responses/task_get/{id}`
85    /// See <https://docs.dataforseo.com/v3/ai_optimization/chat_gpt/llm_responses/task_get/>.
86    pub async fn task_get(&self, id: &str) -> DataForSeoApiResponse<AiOptimizationLlmResponse> {
87        self.client
88            .http_get(&format!(
89                "/v3/ai_optimization/{}/llm_responses/task_get/{}",
90                self.provider, id
91            ))
92            .await
93    }
94}
95
96/// Perplexity LLM Responses endpoints (Live-only).
97///
98/// See <https://docs.dataforseo.com/v3/ai_optimization/perplexity/llm_responses/overview/>.
99pub struct AiOptimizationApiPerplexityLlmResponses<'a> {
100    pub(crate) client: &'a DataForSeoClient,
101}
102
103impl AiOptimizationApiPerplexityLlmResponses<'_> {
104    /// Lists the Perplexity models available.
105    ///
106    /// `GET /v3/ai_optimization/perplexity/llm_responses/models`
107    pub async fn models(&self) -> DataForSeoApiResponse<AiOptimizationLlmResponseModel> {
108        self.client
109            .http_get("/v3/ai_optimization/perplexity/llm_responses/models")
110            .await
111    }
112
113    /// Generates a Perplexity response synchronously.
114    ///
115    /// `POST /v3/ai_optimization/perplexity/llm_responses/live`
116    /// See <https://docs.dataforseo.com/v3/ai_optimization/perplexity/llm_responses/live/>.
117    pub async fn live(
118        &self,
119        data: Vec<AiOptimizationLlmResponsesPost>,
120    ) -> DataForSeoApiResponse<AiOptimizationLlmResponse> {
121        self.client
122            .http_post("/v3/ai_optimization/perplexity/llm_responses/live", &data)
123            .await
124    }
125}
126
127/// A single turn of a conversation passed via `message_chain`.
128#[derive(Debug, Default, Serialize, Deserialize, Clone)]
129pub struct AiOptimizationLlmMessage {
130    /// Role of the message author (e.g. `"user"`, `"assistant"`).
131    pub role: String,
132    /// Text content of the message.
133    pub message: String,
134}
135
136impl AiOptimizationLlmMessage {
137    /// Creates a message with the given role and content.
138    pub fn new(role: &str, message: &str) -> AiOptimizationLlmMessage {
139        AiOptimizationLlmMessage {
140            role: role.to_string(),
141            message: message.to_string(),
142        }
143    }
144}
145
146/// Request body for the LLM Responses `live` and `task_post` endpoints.
147///
148/// `postback_url` and `pingback_url` apply only to `task_post`.
149#[derive(Debug, Default, Serialize, Deserialize, Clone)]
150pub struct AiOptimizationLlmResponsesPost {
151    /// The question or task to send to the model (max 500 characters).
152    pub user_prompt: String,
153    /// Model to use; a base name selects the latest version.
154    pub model_name: String,
155    /// Maximum tokens to generate (16–4096, default: 2048).
156    #[serde(skip_serializing_if = "Option::is_none")]
157    pub max_output_tokens: Option<i64>,
158    /// Sampling temperature (0–2, default: 0.94; unsupported by reasoning models).
159    #[serde(skip_serializing_if = "Option::is_none")]
160    pub temperature: Option<f64>,
161    /// Nucleus sampling probability (0–1, default: 0.92; mutually exclusive with `temperature`).
162    #[serde(skip_serializing_if = "Option::is_none")]
163    pub top_p: Option<f64>,
164    /// Whether the model may access the web (default: false).
165    #[serde(skip_serializing_if = "Option::is_none")]
166    pub web_search: Option<bool>,
167    /// Whether to force the model to use web search (default: false).
168    #[serde(skip_serializing_if = "Option::is_none")]
169    pub force_web_search: Option<bool>,
170    /// ISO country code to localize web search.
171    #[serde(skip_serializing_if = "Option::is_none")]
172    pub web_search_country_iso_code: Option<String>,
173    /// City name to localize web search.
174    #[serde(skip_serializing_if = "Option::is_none")]
175    pub web_search_city: Option<String>,
176    /// System instructions steering the model (max 500 characters).
177    #[serde(skip_serializing_if = "Option::is_none")]
178    pub system_message: Option<String>,
179    /// Prior conversation turns to include (max 10).
180    #[serde(skip_serializing_if = "Option::is_none")]
181    pub message_chain: Option<Vec<AiOptimizationLlmMessage>>,
182    /// URL to POST the result to when the task completes (`task_post` only).
183    #[serde(skip_serializing_if = "Option::is_none")]
184    pub postback_url: Option<String>,
185    /// URL to ping when the task completes (`task_post` only).
186    #[serde(skip_serializing_if = "Option::is_none")]
187    pub pingback_url: Option<String>,
188    /// User-defined task identifier (max 255 characters).
189    #[serde(skip_serializing_if = "Option::is_none")]
190    pub tag: Option<String>,
191}
192
193impl AiOptimizationLlmResponsesPost {
194    /// Creates a request with the given prompt and model.
195    pub fn new(user_prompt: &str, model_name: &str) -> AiOptimizationLlmResponsesPost {
196        AiOptimizationLlmResponsesPost {
197            user_prompt: user_prompt.to_string(),
198            model_name: model_name.to_string(),
199            ..Default::default()
200        }
201    }
202}