Files
ailine/backend/app/agent_subgraphs/dictionary/api_client.py
root f274df6e3d
All checks were successful
构建并部署 AI Agent 服务 / deploy (push) Successful in 5m44s
完成:词典和资讯 API 支持 async 和数据库缓存
2026-04-27 17:37:07 +08:00

193 lines
7.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
词典API调用工具
Dictionary API Client
支持 async 和真实数据库缓存
"""
from typing import Dict, Any, Optional
from dataclasses import dataclass
@dataclass
class DictionaryAPIClient:
"""
词典API客户端 - 可扩展支持多种API和数据库缓存
"""
# 可以配置多个API
youdao_api_key: Optional[str] = None
youdao_api_secret: Optional[str] = None
# 数据库 Repository可选用于缓存单词查询
word_repository: Optional[Any] = None
def __post_init__(self):
"""初始化后,如果有 repository 则支持 async"""
pass
async def query_word_db(self, user_id: str, word: str) -> Optional[Dict[str, Any]]:
"""从数据库缓存查询单词"""
if not self.word_repository:
return None
try:
entity = await self.word_repository.search_by_word(user_id, word)
if entity:
return {
"phonetic": entity.phonetic,
"part_of_speech": entity.part_of_speech,
"definitions": [entity.definition] if entity.definition else [],
"examples": [entity.examples] if entity.examples else []
}
except Exception as e:
print(f"从数据库查询单词失败:{e}")
return None
async def cache_word_db(self, user_id: str, word: str, data: Dict[str, Any]):
"""把单词查询结果缓存到数据库"""
if not self.word_repository:
return
try:
from ...db.models import WordEntity
entity = WordEntity(
user_id=user_id,
word=word,
phonetic=data.get("phonetic", ""),
part_of_speech=data.get("part_of_speech", ""),
definition=data.get("definitions", [""])[0] if data.get("definitions") else "",
examples=data.get("examples", [""])[0] if data.get("examples") else ""
)
await self.word_repository.insert(entity)
except Exception as e:
print(f"缓存单词到数据库失败:{e}")
async def query_word_youdao(self, word: str) -> Optional[Dict[str, Any]]:
"""
调用有道词典API查询单词async 版本)
注意需要配置有道API密钥才能使用
文档https://ai.youdao.com/doc.s#guide
"""
if not self.youdao_api_key or not self.youdao_api_secret:
return None
try:
# TODO: 实现真实的有道API调用用 httpx 或 aiohttp
# 这里是示例结构
return None
except Exception as e:
print(f"有道API调用失败{e}")
return None
async def translate_baidu(self, text: str, from_lang: str = "auto", to_lang: str = "zh") -> Optional[Dict[str, Any]]:
"""
调用百度翻译APIasync 版本)
注意需要配置百度API密钥才能使用
文档https://fanyi-api.baidu.com/doc/21
"""
# TODO: 实现真实的百度翻译API调用用 httpx 或 aiohttp
return None
def query_word_mock(self, word: str) -> Dict[str, Any]:
"""
模拟词典API - 目前用于演示
"""
mock_db = {
"serendipity": {
"phonetic": "/ˌserənˈdipədē/",
"part_of_speech": "n.",
"definitions": ["意外发现珍奇事物的能力", "机缘凑巧"],
"examples": ["Finding that old photo was pure serendipity."]
},
"ephemeral": {
"phonetic": "ˈfem(ə)rəl/",
"part_of_speech": "adj.",
"definitions": ["短暂的,瞬息的"],
"examples": ["Fame in the digital age is often ephemeral."]
},
"ubiquitous": {
"phonetic": "/yo͞oˈbikwədəs/",
"part_of_speech": "adj.",
"definitions": ["无处不在的", "普遍存在的"],
"examples": ["Smartphones have become ubiquitous in modern life."]
},
"eloquent": {
"phonetic": "/ˈeləkwənt/",
"part_of_speech": "adj.",
"definitions": ["雄辩的,有说服力的"],
"examples": ["She gave an eloquent speech at the conference."]
},
"resilient": {
"phonetic": "/rəˈzilyənt/",
"part_of_speech": "adj.",
"definitions": ["有复原力的,能适应的"],
"examples": ["The community has proven to be resilient in the face of challenges."]
}
}
if word.lower() in mock_db:
return mock_db[word.lower()]
else:
return {
"phonetic": "",
"part_of_speech": "n.",
"definitions": [f"{word}的释义1", f"{word}的释义2"],
"examples": [f"This is an example sentence with '{word}'."]
}
def translate_mock(self, text: str, from_lang: str = "auto", to_lang: str = "zh") -> Dict[str, Any]:
"""
模拟翻译API - 目前用于演示
"""
translations = {
"你好": "Hello",
"hello": "你好",
"人工智能": "Artificial Intelligence",
"artificial intelligence": "人工智能",
"ai": "人工智能",
"大模型": "Large Language Model",
"自然语言处理": "Natural Language Processing"
}
return {
"translated_text": translations.get(text.lower(), f"【翻译结果】{text}"),
"confidence": 0.95
}
def extract_terms_mock(self, text: str) -> list:
"""
模拟术语提取API
"""
return [
{"term": "AI", "type": "技术术语", "definition": "人工智能", "confidence": 0.95},
{"term": "LLM", "type": "技术术语", "definition": "大语言模型", "confidence": 0.92},
{"term": "NLP", "type": "技术术语", "definition": "自然语言处理", "confidence": 0.88}
]
# ========== 统一入口(优先查缓存) ==========
async def query_word(self, user_id: str = "default", word: str = "", use_cache: bool = True) -> Dict[str, Any]:
"""
查询单词(统一入口,优先查数据库缓存)
"""
# 1. 先查数据库缓存
if use_cache:
cached = await self.query_word_db(user_id, word)
if cached:
return cached
# 2. 查第三方 API暂未实现
api_result = await self.query_word_youdao(word)
if api_result:
if use_cache:
await self.cache_word_db(user_id, word, api_result)
return api_result
# 3. 用模拟数据(兜底)
mock_result = self.query_word_mock(word)
if use_cache:
await self.cache_word_db(user_id, word, mock_result)
return mock_result
# 单例实例(模拟模式,保持向后兼容)
dictionary_api = DictionaryAPIClient()