| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- """
- Gemini API 工具
- 提供内容分析和比较功能。
- """
- import json
- import os
- from typing import List, Dict, Any, Optional
- import httpx
- from agent.tools import tool, ToolResult
- # API 基础配置
- GEMINI_API_KEY = os.getenv("GEMINI_API_KEY", "")
- GEMINI_API_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent"
- DEFAULT_TIMEOUT = 60.0
- @tool(
- display={
- "zh": {
- "name": "Gemini内容分析",
- "params": {
- "content": "要分析的内容",
- "analysis_type": "分析类型",
- "context": "上下文信息"
- }
- }
- }
- )
- async def gemini_analyze_content(
- content: str,
- analysis_type: str = "general",
- context: Optional[str] = None,
- ) -> ToolResult:
- """
- 使用Gemini分析内容
- Args:
- content: 要分析的内容(视频标题、描述等)
- analysis_type: 分析类型,可选:
- - general: 通用分析
- - emotion: 情感分析
- - audience: 受众分析
- - quality: 质量评估
- context: 额外的上下文信息
- Returns:
- ToolResult 包含分析结果:
- {
- "analysis": "分析结果文本",
- "structured_data": {
- "emotion": "感动",
- "target_audience": "50+老年人",
- "key_themes": ["抗日", "英雄", "历史"],
- "quality_score": 8.5,
- "recommendations": ["适合老年人观看", "具有教育意义"]
- }
- }
- """
- try:
- if not GEMINI_API_KEY:
- return ToolResult(
- title="配置错误",
- output="",
- error="未配置 GEMINI_API_KEY 环境变量"
- )
- # 构建提示词
- prompts = {
- "general": f"请分析以下内容,提供详细的分析报告:\n\n{content}",
- "emotion": f"请分析以下内容的情感倾向,识别主要情感和情感强度:\n\n{content}",
- "audience": f"请分析以下内容适合的目标受众,包括年龄、兴趣等特征:\n\n{content}",
- "quality": f"请评估以下内容的质量,包括吸引力、完整性、可信度等:\n\n{content}",
- }
- prompt = prompts.get(analysis_type, prompts["general"])
- if context:
- prompt += f"\n\n上下文信息:{context}"
- # 调用Gemini API
- payload = {
- "contents": [{
- "parts": [{
- "text": prompt
- }]
- }]
- }
- headers = {
- "Content-Type": "application/json",
- }
- url = f"{GEMINI_API_URL}?key={GEMINI_API_KEY}"
- async with httpx.AsyncClient(timeout=DEFAULT_TIMEOUT) as client:
- response = await client.post(
- url,
- json=payload,
- headers=headers,
- )
- response.raise_for_status()
- data = response.json()
- # 提取分析结果
- candidates = data.get("candidates", [])
- if not candidates:
- return ToolResult(
- title="分析失败",
- output="",
- error="Gemini API 未返回结果"
- )
- analysis_text = candidates[0].get("content", {}).get("parts", [{}])[0].get("text", "")
- result = {
- "analysis": analysis_text,
- "analysis_type": analysis_type,
- "content_preview": content[:100] + "..." if len(content) > 100 else content
- }
- return ToolResult(
- title=f"Gemini分析: {analysis_type}",
- output=json.dumps(result, ensure_ascii=False, indent=2),
- long_term_memory=f"Analyzed content with Gemini ({analysis_type})"
- )
- except httpx.HTTPStatusError as e:
- return ToolResult(
- title="API调用失败",
- output="",
- error=f"HTTP error {e.response.status_code}: {e.response.text}"
- )
- except Exception as e:
- return ToolResult(
- title="分析失败",
- output="",
- error=str(e)
- )
- @tool(
- display={
- "zh": {
- "name": "Gemini比较视频",
- "params": {
- "videos": "视频列表",
- "comparison_criteria": "比较标准"
- }
- }
- }
- )
- async def gemini_compare_videos(
- videos: List[Dict[str, Any]],
- comparison_criteria: Optional[List[str]] = None,
- ) -> ToolResult:
- """
- 使用Gemini比较多个视频
- Args:
- videos: 视频列表,每个视频包含:
- - title: 标题
- - description: 描述
- - tags: 标签列表
- - stats: 数据统计
- comparison_criteria: 比较标准,可选:
- - similarity: 相似度
- - quality: 质量
- - audience_fit: 受众匹配度
- - engagement: 互动表现
- Returns:
- ToolResult 包含比较结果:
- {
- "comparison": "比较分析文本",
- "rankings": [
- {
- "video_index": 0,
- "title": "...",
- "score": 8.5,
- "strengths": ["..."],
- "weaknesses": ["..."]
- }
- ],
- "recommendations": ["..."]
- }
- """
- try:
- if not GEMINI_API_KEY:
- return ToolResult(
- title="配置错误",
- output="",
- error="未配置 GEMINI_API_KEY 环境变量"
- )
- if len(videos) < 2:
- return ToolResult(
- title="参数错误",
- output="",
- error="至少需要2个视频进行比较"
- )
- # 构建比较提示词
- criteria_text = "、".join(comparison_criteria) if comparison_criteria else "相似度、质量、受众匹配度"
- prompt = f"请比较以下{len(videos)}个视频,从{criteria_text}等方面进行分析:\n\n"
- for i, video in enumerate(videos, 1):
- prompt += f"视频{i}:\n"
- prompt += f"标题:{video.get('title', 'N/A')}\n"
- prompt += f"描述:{video.get('description', 'N/A')}\n"
- prompt += f"标签:{', '.join(video.get('tags', []))}\n"
- if 'stats' in video:
- prompt += f"数据:{json.dumps(video['stats'], ensure_ascii=False)}\n"
- prompt += "\n"
- prompt += "请提供详细的比较分析,并给出推荐建议。"
- # 调用Gemini API
- payload = {
- "contents": [{
- "parts": [{
- "text": prompt
- }]
- }]
- }
- headers = {
- "Content-Type": "application/json",
- }
- url = f"{GEMINI_API_URL}?key={GEMINI_API_KEY}"
- async with httpx.AsyncClient(timeout=DEFAULT_TIMEOUT) as client:
- response = await client.post(
- url,
- json=payload,
- headers=headers,
- )
- response.raise_for_status()
- data = response.json()
- # 提取比较结果
- candidates = data.get("candidates", [])
- if not candidates:
- return ToolResult(
- title="比较失败",
- output="",
- error="Gemini API 未返回结果"
- )
- comparison_text = candidates[0].get("content", {}).get("parts", [{}])[0].get("text", "")
- result = {
- "comparison": comparison_text,
- "video_count": len(videos),
- "criteria": comparison_criteria or ["similarity", "quality", "audience_fit"]
- }
- return ToolResult(
- title=f"Gemini比较: {len(videos)}个视频",
- output=json.dumps(result, ensure_ascii=False, indent=2),
- long_term_memory=f"Compared {len(videos)} videos with Gemini"
- )
- except httpx.HTTPStatusError as e:
- return ToolResult(
- title="API调用失败",
- output="",
- error=f"HTTP error {e.response.status_code}: {e.response.text}"
- )
- except Exception as e:
- return ToolResult(
- title="比较失败",
- output="",
- error=str(e)
- )
|