Python · AI एजेंट · Amazon
AI एजेंट को लाइव प्रोडक्ट डेटा दें
एक लैंग्वेज मॉडल सिर्फ़ वही जानता है जो उसके ट्रेनिंग डेटा में था। उससे पूछें कि किसी प्रोडक्ट की आज कीमत क्या है, तो वह अंदाज़ा लगाएगा या कहेगा कि उसे नहीं पता। इसका हल है मॉडल को लिखते समय आपके कोड से जवाब माँगने देना: आप कुछ “टूल” बताते हैं – किसी शॉप में सर्च, किसी प्रोडक्ट का लुकअप – और जब मॉडल को लाइव डेटा चाहिए, तो वह आपके प्रोग्राम से उनमें से एक चलाने को कहता है।
फिर आपका प्रोग्राम everydata.io को कॉल करता है, लाइव पेज से मौजूदा डेटा लेता है और मॉडल को वापस देता है, जो असली कीमतों और असली उपलब्धता के साथ जवाब देता है। यह OpenAI, Anthropic और ज़्यादातर दूसरे प्रोवाइडर के साथ एक ही तरह काम करता है; बस रैपिंग थोड़ी अलग होती है। यह गाइड टूल को प्रोवाइडर-न्यूट्रल रखती है और दोनों रैपिंग दिखाती है।
अपडेट: · everydata.io द्वारा
आख़िर में आपके पास क्या होगा
- दो Python फ़ंक्शन, जो लाइव Amazon सर्च रिज़ल्ट और प्रोडक्ट विवरण फ़ेच करते हैं।
- एक न्यूट्रल टूल विवरण, OpenAI-स्टाइल और Anthropic-स्टाइल tool definitions में बदला हुआ।
- हर प्रोवाइडर के लिए एक चालू सवाल-जवाब लूप।
आपको क्या चाहिए
- Python 3.10 या नया,
pip install requestsऔर आपके मॉडल प्रोवाइडर का SDK (pip install openaiयाpip install anthropic)। - everydata.io की फ़्री API key – यहाँ बनाएँ –
EVERYDATA_API_KEYमें। OPENAI_API_KEYयाANTHROPIC_API_KEYमें आपके मॉडल प्रोवाइडर की API key।
01tool calling चार चरणों में कैसे काम करता है
- आप सवाल के साथ टूल की एक लिस्ट भेजते हैं: एक नाम, हर टूल क्या करता है इस बारे में एक वाक्य, और वह कौन-से इनपुट लेता है।
- तुरंत जवाब देने के बजाय मॉडल कहता है “कृपया
search_amazonको keyword ‘usb c charger 20w’ के साथ चलाएँ”। - आपका कोड वह फ़ंक्शन चलाता है – यहाँ: everydata.io को एक रिक्वेस्ट – और नतीजा वापस भेजता है।
- मॉडल नतीजा पढ़ता है और अंतिम जवाब लिखता है। अगर उसे और चाहिए, तो पहले वह दूसरा टूल माँगता है।
मॉडल कभी आपकी everydata.io key नहीं देखता और कभी ख़ुद API कॉल नहीं करता। असल में क्या चलेगा, यह आपका कोड तय करता है।
02डेटा फ़ेच करने वाले फ़ंक्शन लिखें
ये सादे Python फ़ंक्शन हैं। हर एक एक रिक्वेस्ट करता है और सिर्फ़ वे फ़ील्ड रखता है जो मॉडल को चाहिए – पूरे प्रोडक्ट पेज में दर्जनों फ़ील्ड होते हैं, और हर अतिरिक्त फ़ील्ड जवाब बेहतर किए बिना टोकन ख़र्च करता है।
"""Two tools an AI model can call: search Amazon and look up one product – live, through everydata.io."""
import json
import os
import re
import time
import requests
API = "https://api.everydata.io"
KEY = os.environ["EVERYDATA_API_KEY"]
def _get(path: str, params: dict) -> dict:
"""One everydata.io request. Errors come back as data, so the model can explain them instead of crashing."""
retried = False
for _ in range(4):
try:
resp = requests.get(f"{API}{path}", params=params, headers={"x-api-key": KEY}, timeout=60)
except requests.RequestException as exc:
return {"error": "network", "detail": str(exc)[:300]}
if resp.status_code == 429:
# Too many requests at once. The answer says how long to wait: "... Try again in 12 seconds."
wait = re.search(r"in (\d+) seconds", resp.text)
time.sleep(int(wait.group(1)) + 1 if wait else 60)
continue
if resp.status_code >= 500 and not retried:
retried = True # the page could not be loaded – try once more (5xx answers are not counted)
time.sleep(5)
continue
if resp.status_code >= 400:
return {"error": resp.status_code, "detail": resp.text[:300]}
return resp.json()
return {"error": 429, "detail": "Still rate limited after waiting. Try again in a minute."}
def search_amazon(keyword: str, domainCode: str = "com") -> dict:
data = _get("/amz/amazon-search-by-keyword-asin",
{"keyword": keyword, "domainCode": domainCode, "excludeSponsored": "true"})
if "error" in data:
return data
keep = ("asin", "productDescription", "price", "currency", "productRating", "countReview")
# Only the first five results and only the fields the model needs: fewer tokens, better answers.
return {"results": [{k: p.get(k) for k in keep} for p in data.get("searchProductDetails", [])[:5]]}
def get_amazon_product(asin: str, domainCode: str = "com") -> dict:
data = _get("/amz/amazon-lookup-product-by-asin", {"asin": asin, "domainCode": domainCode})
if "error" in data:
return data
keep = ("productTitle", "asin", "price", "retailPrice", "currency",
"productRating", "countReview", "warehouseAvailability", "features")
return {k: data.get(k) for k in keep}
FUNCTIONS = {"search_amazon": search_amazon, "get_amazon_product": get_amazon_product}
def run_tool(name: str, args: dict) -> str:
"""Run the tool the model asked for and return the result as a JSON string."""
fn = FUNCTIONS.get(name)
if fn is None:
return json.dumps({"error": f"unknown tool {name}"})
try:
return json.dumps(fn(**args), ensure_ascii=False)
except Exception as exc: # wrong arguments, unexpected data … – tell the model instead of crashing
return json.dumps({"error": "tool failed", "detail": f"{type(exc).__name__}: {exc}"[:300]})फ़ंक्शन के छाँटने से पहले search endpoint यह लौटाता है (छोटा किया गया डॉक्यूमेंटेड उदाहरण):
{
"responseStatus": "PRODUCT_FOUND_RESPONSE",
"responseMessage": "Product successfully found!",
"domainCode": "com",
"keyword": "laptop",
"numberOfProducts": 26,
"searchProductDetails": [
{
"productDescription": "Acer Aspire 14 AI Copilot+ PC - Intel Core Ultra 5 226V & 14” WUXGA Touch - NPU: Up to 40 Tops - GPU: Up to 53 Tops | Intel Arc 130V | 16GB LPDDR5X | 1TB Gen 4 SSD | Wi-Fi 6E | A14-52MT-59DP",
"asin": "B0FGJ14KRX",
"countReview": 20,
"price": 548.44,
"productRating": "4.0 out of 5 stars",
"currency": "USD"
}
],
"currentPage": 1,
"lastPage": 20
}03टूल एक बार बताएँ, फिर हर प्रोवाइडर के लिए रैप करें
विवरण वह है जिसे पढ़कर मॉडल तय करता है कि टूल कब इस्तेमाल करना है, इसलिए इसे मॉडल के लिए लिखें: यह क्या लौटाता है और कब काम का है। इनपुट JSON Schema में बताए जाते हैं, जिसे हर बड़ा प्रोवाइडर समझता है। बस उसके आसपास का envelope अलग होता है।
# Add to tools.py – one description per tool, written for the model, in plain JSON Schema.
TOOL_SPECS = [
{
"name": "search_amazon",
"description": "Search Amazon right now. Returns up to 5 products with ASIN, title, current price, "
"currency and rating. Use it when the user asks what is available or what something costs.",
"parameters": {
"type": "object",
"properties": {
"keyword": {"type": "string", "description": "What to search for, e.g. 'usb c charger 20w'"},
"domainCode": {"type": "string", "description": "Amazon marketplace: com, de, co.uk, fr, it, es …"},
},
"required": ["keyword"],
},
},
{
"name": "get_amazon_product",
"description": "Live details of one Amazon product by ASIN: title, price, list price, availability, "
"rating and key features. A price of 0 means the page shows no price right now.",
"parameters": {
"type": "object",
"properties": {
"asin": {"type": "string", "description": "10-character Amazon product ID, e.g. B07ZPKN6YR"},
"domainCode": {"type": "string", "description": "Amazon marketplace: com, de, co.uk, fr, it, es …"},
},
"required": ["asin"],
},
},
]
# OpenAI-style (Chat Completions): the schema goes under "function" -> "parameters".
OPENAI_TOOLS = [{"type": "function", "function": spec} for spec in TOOL_SPECS]
# Anthropic-style (Messages API): the same schema is called "input_schema".
ANTHROPIC_TOOLS = [
{"name": s["name"], "description": s["description"], "input_schema": s["parameters"]}
for s in TOOL_SPECS
]पैरामीटर के नाम API से मेल खाते हैं (keyword, asin, domainCode), इसलिए मॉडल के arguments सीधे चरण 2 के फ़ंक्शन में भेजे जा सकते हैं।
04इसे Anthropic-स्टाइल API के साथ चलाएँ
लूप सवाल भेजता है, मॉडल जो भी टूल माँगे उसे चलाता है, नतीजे tool_result ब्लॉक के रूप में लौटाता है और मॉडल के टेक्स्ट में जवाब देने पर रुक जाता है।
import anthropic
from tools import ANTHROPIC_TOOLS, run_tool
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY
MAX_ROUNDS = 5 # hard limit on tool rounds – every tool call is one everydata.io request
messages = [{"role": "user", "content": "What does a 20W USB-C charger cost on amazon.com right now?"}]
for _ in range(MAX_ROUNDS):
response = client.messages.create(
model="claude-opus-5",
max_tokens=16000,
tools=ANTHROPIC_TOOLS,
messages=messages,
)
if response.stop_reason != "tool_use":
break
messages.append({"role": "assistant", "content": response.content})
messages.append({
"role": "user",
"content": [
{"type": "tool_result", "tool_use_id": block.id, "content": run_tool(block.name, block.input)}
for block in response.content
if block.type == "tool_use"
],
})
else:
raise SystemExit(f"Stopped after {MAX_ROUNDS} tool rounds without a final answer. "
"Ask a more specific question or raise MAX_ROUNDS.")
print("".join(block.text for block in response.content if block.type == "text"))05इसे OpenAI-स्टाइल API के साथ चलाएँ
वही लूप, अलग मैसेज आकार: टूल रिक्वेस्ट tool_calls में आती हैं, arguments JSON स्ट्रिंग के रूप में, और हर नतीजा tool रोल वाले मैसेज के रूप में वापस जाता है। कई दूसरे प्रोवाइडर और लोकल मॉडल सर्वर भी यह OpenAI-स्टाइल फ़ॉर्मैट स्वीकार करते हैं।
import json
import os
from openai import OpenAI
from tools import OPENAI_TOOLS, run_tool
client = OpenAI() # reads OPENAI_API_KEY
MODEL = os.environ["OPENAI_MODEL"] # any chat model that supports function calling
MAX_ROUNDS = 5 # hard limit on tool rounds – every tool call is one everydata.io request
messages = [{"role": "user", "content": "What does a 20W USB-C charger cost on amazon.com right now?"}]
for _ in range(MAX_ROUNDS):
response = client.chat.completions.create(model=MODEL, messages=messages, tools=OPENAI_TOOLS)
message = response.choices[0].message
if not message.tool_calls:
break
messages.append(message)
for call in message.tool_calls:
try:
args = json.loads(call.function.arguments)
except json.JSONDecodeError:
result = json.dumps({"error": "arguments were not valid JSON"})
else:
result = run_tool(call.function.name, args)
messages.append({"role": "tool", "tool_call_id": call.id, "content": result})
else:
raise SystemExit(f"Stopped after {MAX_ROUNDS} tool rounds without a final answer. "
"Ask a more specific question or raise MAX_ROUNDS.")
print(message.content)06यूज़र के सामने रखने से पहले
- टूल राउंड पर सख़्त सीमा रखें। हर tool call एक everydata.io रिक्वेस्ट है, इसलिए बिना सीमा वाला लूप आपका quota ख़त्म कर सकता है। सीमा पूरी होने पर ऊपर की स्क्रिप्ट आधा जवाब प्रिंट करने के बजाय एक साफ़ मैसेज के साथ रुक जाती हैं।
- एरर को डेटा के रूप में लौटाएँ (
_getऔरrun_toolयही करते हैं)। तब मॉडल चुपचाप विफल होने के बजाय यूज़र को बता सकता है कि कोई पेज लोड नहीं हो सका। जब आप एक साथ बहुत ज़्यादा रिक्वेस्ट भेजते हैं (429) तो_getरुकता है और विफल पेज लोड (5xx) को एक बार और आज़माता है; 5xx जवाब आपके quota में नहीं गिने जाते। - नतीजे छाँटें। छह-छह फ़ील्ड वाले पाँच सर्च रिज़ल्ट अच्छे जवाब के लिए आमतौर पर काफ़ी होते हैं।
- टूल विवरण में मॉडल को बताएँ कि
0कीमत का मतलब “अभी कोई कीमत नहीं दिख रही” है, ताकि वह प्रोडक्ट को मुफ़्त न बताए।
क्या आप यही टूल अपने ऐप के बजाय Claude Desktop, Claude Code या ChatGPT में चाहते हैं? उन्हें एक MCP सर्वर में रैप करें – देखें लाइव वेब डेटा के लिए MCP टूल बनाएँ।
इस गाइड में इस्तेमाल किए गए endpoints
Search Products · Amazon API
Product Details by ASIN · Amazon API
इस डेटा से आप और क्या कर सकते हैं
कोई भी Amazon प्रोडक्ट पेज स्ट्रक्चर्ड JSON में: टाइटल, ब्रांड, कीमत, रेटिंग, इमेज, बुलेट, स्पेसिफ़िकेशन, वेरिएशन और टॉप रिव्यू। रियलटाइम, URL या ASIN से।
कीवर्ड से Amazon सर्च रिज़ल्ट JSON में पाएँ: हर पेज पर ASIN, कीमत, रेटिंग, Prime फ़्लैग, बिक्री मात्रा और sponsored मार्कर, किसी भी मार्केटप्लेस पर।
15+ मार्केटप्लेस पर Amazon की कीमतें रियलटाइम में ट्रैक करें। लाइव buy-box कीमत, लिस्ट प्राइस, स्टॉक और price-history endpoint – हर ASIN के लिए एक JSON कॉल।
अपने डेटा के साथ आज़माएँ
फ़्री प्लान में हर महीने 100 रिक्वेस्ट शामिल हैं, हर प्लेटफ़ॉर्म पर इस्तेमाल करने लायक – इस गाइड को शुरू से आख़िर तक फ़ॉलो करने के लिए काफ़ी।