更新谚语搜索,调整搜索函数
This commit is contained in:
parent
b16917215a
commit
fe6c84e310
27
README.md
27
README.md
|
|
@ -334,16 +334,19 @@ Authorization: Bearer <your_jwt_token>
|
||||||
#### 2.2 法语谚语详情
|
#### 2.2 法语谚语详情
|
||||||
|
|
||||||
- **接口**: `POST /search/proverb`
|
- **接口**: `POST /search/proverb`
|
||||||
- **描述**: 通过谚语ID获取法语谚语原文与中文解释。
|
- **描述**: 根据谚语ID返回法语谚语全文与中文释义。
|
||||||
- **需要认证**: 是
|
- **需要认证**: 是
|
||||||
- **查询参数**:
|
- **请求类型**: `application/x-www-form-urlencoded`
|
||||||
- `proverb_id`: 谚语ID (integer)
|
- **表单字段**:
|
||||||
|
- `proverb_id`: 谚语ID (integer,必填)
|
||||||
- **响应**:
|
- **响应**:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"proverb_text": "Petit à petit, l'oiseau fait son nid.",
|
"result": {
|
||||||
"chi_exp": "循序渐进才能取得成功。"
|
"proverb_text": "Petit à petit, l'oiseau fait son nid.",
|
||||||
|
"chi_exp": "循序渐进才能取得成功。"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -380,14 +383,13 @@ Authorization: Bearer <your_jwt_token>
|
||||||
#### 2.4 谚语联想建议
|
#### 2.4 谚语联想建议
|
||||||
|
|
||||||
- **接口**: `POST /search/proverb/list`
|
- **接口**: `POST /search/proverb/list`
|
||||||
- **描述**: 按输入内容(自动识别法语或中文)返回谚语候选列表。
|
- **描述**: 按输入内容返回谚语候选列表,后端会自动检测输入语言(中文/日文假名/拉丁字母),无法识别时退回法语字段搜索。
|
||||||
- **需要认证**: 是
|
- **需要认证**: 是
|
||||||
- **请求体**:
|
- **请求体**:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"query": "慢",
|
"query": "慢"
|
||||||
"language": "fr"
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -405,6 +407,9 @@ Authorization: Bearer <your_jwt_token>
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- **状态码**:
|
||||||
|
- `200`: 查询成功
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 3. 翻译模块 (`/translate`)
|
### 3. 翻译模块 (`/translate`)
|
||||||
|
|
@ -437,6 +442,7 @@ Authorization: Bearer <your_jwt_token>
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- **限制**: 依赖 Redis 计数器做限流,同一用户每秒最多 2 次请求(超出返回 `429`)
|
||||||
- **状态码**:
|
- **状态码**:
|
||||||
- `200`: 翻译成功
|
- `200`: 翻译成功
|
||||||
- `401`: 未授权
|
- `401`: 未授权
|
||||||
|
|
@ -452,7 +458,7 @@ Authorization: Bearer <your_jwt_token>
|
||||||
- `from_lang`: 源语言,默认为 `auto`
|
- `from_lang`: 源语言,默认为 `auto`
|
||||||
- `to_lang`: 目标语言,默认为 `zh`
|
- `to_lang`: 目标语言,默认为 `zh`
|
||||||
|
|
||||||
- **限制**: 每秒最多2次请求
|
- **限制**: 与标准翻译接口共享限流计数,同一用户每秒最多2次请求
|
||||||
- **状态码**:
|
- **状态码**:
|
||||||
- `200`: 翻译成功
|
- `200`: 翻译成功
|
||||||
- `429`: 请求频率过高
|
- `429`: 请求频率过高
|
||||||
|
|
@ -770,7 +776,8 @@ Authorization: Bearer <your_jwt_token>
|
||||||
- **需要认证**: 是
|
- **需要认证**: 是
|
||||||
- **查询参数**:
|
- **查询参数**:
|
||||||
- `count`: 抽题数量 (integer,默认 `20`)
|
- `count`: 抽题数量 (integer,默认 `20`)
|
||||||
- `lang`: 语种代码,支持 `fr-FR`(法语)、`ja-JP`(日语),默认 `fr-FR`
|
- **表单字段**:
|
||||||
|
- `lang`: 语种代码(`fr-FR` 或 `ja-JP`,默认 `fr-FR`)。由于实现方式,FastAPI 将其视为 form-data 字段,GET 请求需通过 form 提交或在调试文档中直接填写。
|
||||||
- **响应**:
|
- **响应**:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from typing import Literal, List
|
from typing import Literal, List
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
from fastapi import APIRouter, Depends, HTTPException, Request, Form
|
||||||
|
|
||||||
from app.api.search_dict import service
|
from app.api.search_dict import service
|
||||||
from app.api.search_dict.search_schemas import SearchRequest, WordSearchResponse, SearchItemFr, SearchItemJp, \
|
from app.api.search_dict.search_schemas import SearchRequest, WordSearchResponse, SearchItemFr, SearchItemJp, \
|
||||||
|
|
@ -167,10 +167,17 @@ async def search_word_list(query_word: SearchRequest, user=Depends(get_current_u
|
||||||
@dict_search.post("/search/proverb/list")
|
@dict_search.post("/search/proverb/list")
|
||||||
async def search_proverb_list(query_word: ProverbSearchRequest):
|
async def search_proverb_list(query_word: ProverbSearchRequest):
|
||||||
lang = service.detect_language(text=query_word.query)
|
lang = service.detect_language(text=query_word.query)
|
||||||
|
query = normalize_text(query_word.query) if lang == "fr" else query_word.query
|
||||||
suggest_proverbs = await service.suggest_proverb(
|
suggest_proverbs = await service.suggest_proverb(
|
||||||
query=query_word.query,
|
query=query_word.query,
|
||||||
lang=lang,
|
lang=lang,
|
||||||
model=ProverbFr,
|
model=ProverbFr,
|
||||||
|
search_field="search_text",
|
||||||
)
|
)
|
||||||
# TODO 使用法语词典时是否存在用英语输入的情况
|
# TODO 使用法语词典时是否存在用英语输入的情况
|
||||||
return {"list": suggest_proverbs}
|
return {"list": suggest_proverbs}
|
||||||
|
|
||||||
|
@dict_search.post("/search/proverb")
|
||||||
|
async def search_proverb(proverb_id:int = Form(...), user=Depends(get_current_user)):
|
||||||
|
result = await service.accurate_proverb(proverb_id=proverb_id)
|
||||||
|
return {"result": result}
|
||||||
|
|
|
||||||
|
|
@ -39,12 +39,13 @@ async def accurate_proverb(proverb_id: int) -> ProverbSearchResponse:
|
||||||
|
|
||||||
|
|
||||||
async def suggest_proverb(
|
async def suggest_proverb(
|
||||||
query: str,
|
query: str,
|
||||||
lang: Literal["fr", "zh", "jp"],
|
lang: Literal["fr", "zh", "jp"],
|
||||||
model: Type[Model],
|
model: Type[Model],
|
||||||
proverb_field: str = "text",
|
search_field: str = "search_text",
|
||||||
chi_exp_field: str = "chi_exp",
|
target_field: str = "text",
|
||||||
limit: int = 10,
|
chi_exp_field: str = "chi_exp",
|
||||||
|
limit: int = 10,
|
||||||
) -> List[Dict[str, str]]:
|
) -> List[Dict[str, str]]:
|
||||||
"""
|
"""
|
||||||
通用搜索建议函数,用于多语言谚语表。
|
通用搜索建议函数,用于多语言谚语表。
|
||||||
|
|
@ -71,15 +72,15 @@ async def suggest_proverb(
|
||||||
startswith_field = f"{chi_exp_field}__istartswith"
|
startswith_field = f"{chi_exp_field}__istartswith"
|
||||||
contains_field = f"{chi_exp_field}__icontains"
|
contains_field = f"{chi_exp_field}__icontains"
|
||||||
else:
|
else:
|
||||||
startswith_field = f"{proverb_field}__istartswith"
|
startswith_field = f"{search_field}__istartswith"
|
||||||
contains_field = f"{proverb_field}__icontains"
|
contains_field = f"{search_field}__icontains"
|
||||||
|
|
||||||
# ✅ 1. 开头匹配
|
# ✅ 1. 开头匹配
|
||||||
start_matches = await (
|
start_matches = await (
|
||||||
model.filter(**{startswith_field: keyword})
|
model.filter(**{startswith_field: keyword})
|
||||||
.order_by("-freq")
|
.order_by("-freq")
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.values("id", proverb_field, chi_exp_field)
|
.values("id", target_field, search_field, chi_exp_field)
|
||||||
)
|
)
|
||||||
|
|
||||||
# ✅ 2. 包含匹配(非开头)
|
# ✅ 2. 包含匹配(非开头)
|
||||||
|
|
@ -89,7 +90,7 @@ async def suggest_proverb(
|
||||||
)
|
)
|
||||||
.order_by("-freq")
|
.order_by("-freq")
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.values("id", proverb_field, chi_exp_field)
|
.values("id", target_field, search_field, chi_exp_field)
|
||||||
)
|
)
|
||||||
|
|
||||||
# ✅ 3. 合并去重并保持顺序
|
# ✅ 3. 合并去重并保持顺序
|
||||||
|
|
@ -100,7 +101,8 @@ async def suggest_proverb(
|
||||||
seen_ids.add(row["id"])
|
seen_ids.add(row["id"])
|
||||||
results.append({
|
results.append({
|
||||||
"id": row["id"],
|
"id": row["id"],
|
||||||
"proverb": row[proverb_field],
|
"proverb": row[target_field],
|
||||||
|
"search_text": row[search_field],
|
||||||
"chi_exp": row[chi_exp_field]
|
"chi_exp": row[chi_exp_field]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -225,4 +227,4 @@ async def __main():
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# asyncio.run(__main())
|
# asyncio.run(__main())
|
||||||
print(detect_language(text="ahsjdasd"))
|
print(detect_language(text="ahsjdasd"))
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ class ProverbFr(Model):
|
||||||
text = fields.TextField(description="法语谚语及常用表达")
|
text = fields.TextField(description="法语谚语及常用表达")
|
||||||
chi_exp = fields.TextField(description="中文释义")
|
chi_exp = fields.TextField(description="中文释义")
|
||||||
freq = fields.IntField(default=0)
|
freq = fields.IntField(default=0)
|
||||||
|
search_text = fields.TextField()
|
||||||
created_at = fields.DatetimeField(auto_now_add=True)
|
created_at = fields.DatetimeField(auto_now_add=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import asyncio
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
from tortoise import Tortoise, connections
|
from tortoise import Tortoise
|
||||||
from tortoise.exceptions import MultipleObjectsReturned
|
from tortoise.exceptions import MultipleObjectsReturned
|
||||||
|
|
||||||
from app.models.fr import DefinitionFr, WordlistFr
|
from app.models.fr import DefinitionFr, WordlistFr
|
||||||
|
|
@ -101,14 +101,13 @@ async def varification_eg():
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
await Tortoise.init(config=TORTOISE_ORM)
|
await Tortoise.init(config=TORTOISE_ORM)
|
||||||
await DefinitionFr.all().delete() # TRUNCATE TABLE definitions_fr;
|
# await DefinitionFr.all().delete() # TRUNCATE TABLE definitions_fr;
|
||||||
conn = connections.get("default")
|
# conn = connections.get("default")
|
||||||
await conn.execute_script("""
|
# await conn.execute_script("""
|
||||||
ALTER TABLE definitions_fr AUTO_INCREMENT = 1;
|
# ALTER TABLE definitions_fr AUTO_INCREMENT = 1;
|
||||||
""")
|
# """)
|
||||||
await import_def_fr()
|
# await import_def_fr()
|
||||||
# await import_wordlist_fr()
|
# # await import_wordlist_fr()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue